예제 #1
0
def test_merge():
    """
    Functional test of merge().
    """
    # Subgraph 1
    sg1 = empty_graph("Graph 1")
    n1 = node('Add', inputs=['x1', 'x2'], outputs=['sum'])
    sg1 = add_node(sg1, n1)
    sg1 = add_input(sg1, 'x1', "FLOAT", [1])
    sg1 = add_input(sg1, 'x2', "FLOAT", [1])
    sg1 = add_output(sg1, 'sum', "FLOAT", [1])

    # Subgraph 2
    sg2 = empty_graph("Graph 2")
    sg2 = add_constant(sg2, "const", np.array([7]), "FLOAT")
    n2 = node("Equal", inputs=['sum', 'const'], outputs=['equal'])
    sg2 = add_node(sg2, n2)

    sg2 = add_input(sg2, 'sum', "FLOAT", [1])
    sg2 = add_output(sg2, 'equal', "BOOL", [1])

    g = merge(sg1, sg2, outputs=["sum"], inputs=["sum"])

    data = {
        "x1": np.array([2]).astype(np.float32),
        "x2": np.array([5]).astype(np.float32)
    }
    result = run(g, inputs=data, outputs=["equal"])
    assert result[
        0], "Sum of 2 and 5 should be equal to constant 7. Merged failed."
예제 #2
0
def test_concat():
    """
    Functional test for concat
    """
    g1 = empty_graph("G1")
    n1 = node('Add',
              inputs=['x1_1', 'x1_2'],
              outputs=['sum_1'],
              name="node_name")
    g1 = add_input(g1, 'x1_1', "FLOAT", [1])
    g1 = add_input(g1, 'x1_2', "FLOAT", [1])
    g1 = add_output(g1, 'sum_1', "FLOAT", [1])
    g1 = add_node(g1, n1)

    g2 = empty_graph("G2")
    n2 = node('Add',
              inputs=['x2_1', 'x2_2'],
              outputs=['sum_2'],
              name="node_name")
    g2 = add_input(g2, 'x2_2', "FLOAT", [1])
    g2 = add_output(g2, 'sum_2', "FLOAT", [1])
    g2 = add_node(g2, n2)

    g = concat(g1, g2, False, True, edge_match=[("x1_2", "x2_1")])

    data = {
        "x1_1": np.array([2]).astype(np.float32),
        "x1_2": np.array([5]).astype(np.float32),
        "x2_2": np.array([5]).astype(np.float32)
    }
    result = run(g, inputs=data, outputs=["sum_1", "sum_2"])
    assert result[
        0], "Sum of 2 and 5 should be equal to constant 7. Concat failed."
예제 #3
0
def test_check():

    # Invalid, no input/output:
    g = empty_graph()
    n1 = node('Add', inputs=['x1', 'x2'], outputs=['sum'])
    g = add_node(g, n1)
    assert not check(g), "Graph is not complete."

    # Valid graph
    g = add_input(g, 'x1', "FLOAT", [1])
    g = add_input(g, 'x2', "FLOAT", [1])
    g = add_output(g, 'sum', "FLOAT", [1])
    assert check(g), "Graph should pass checks."

    # Invalid: None operator:
    g = empty_graph()
    n1 = node('None', inputs=['x1', 'x2'], outputs=['sum'])
    g = add_node(g, n1)
    g = add_input(g, 'x1', "FLOAT", [1])
    g = add_input(g, 'x2', "FLOAT", [1])
    g = add_output(g, 'sum', "FLOAT", [1])
    assert not check(g), "Graph should not pass checks."

    # Invalid: Dynamic size input
    g = empty_graph()
    n1 = node('Add', inputs=['x1', 'x2'], outputs=['sum'])
    g = add_node(g, n1)
    g = add_input(g, 'x1', "FLOAT", [])
    g = add_input(g, 'x2', "FLOAT", [1])
    g = add_output(g, 'sum', "FLOAT", [1])
    assert not check(g), "Graph should not pass checks."

    check(g, _sclbl_check=False, _onnx_check=False)
    check(g, _onnx_check=False)  # Operator check.
예제 #4
0
def test_delete_node():
    g = empty_graph()
    n = node('Add', inputs=['x1', 'x2'], outputs=['sum'], name="node_name")
    g = add_node(g, n)
    assert len(g.node) == 1, "Node not properly added."
    g = delete_node(g, "node_name")
    assert len(g.node) == 0, "Node not properly deleted."
예제 #5
0
def test__parse_element():
    g = empty_graph()
    dims = [4, 3, 7]
    g = add_output(g, 'sum', "FLOAT", dims)
    for elem in g.output:
        _, elem_type, _ = _parse_element(elem)
    assert elem_type == "FLOAT", "Element not properly parsed."
예제 #6
0
def test_graph_to_file():
    g = empty_graph()
    check1 = graph_to_file(g, "")
    assert not check1, "Graph to file failed should have failed."
    check2 = graph_to_file(g, "files/test_graph_to_file.onnx")
    assert check2, "Graph to file failed to write file."
    os.remove("files/test_graph_to_file.onnx")
예제 #7
0
def test_clean():
    g = empty_graph()
    n1 = node('Add', inputs=['x1', 'x2'], outputs=['sum'])
    g = add_node(g, n1)
    g = add_input(g, 'x1', "FLOAT", [1])
    g = add_input(g, 'x2', "FLOAT", [1])
    g = add_output(g, 'sum', "FLOAT", [1])
    g = clean(g)
    assert type(g) == xpb2.GraphProto, "Clean failed."
예제 #8
0
def test_add_nodes():
    g = empty_graph()
    for i in range(10):
        n = node('Add', inputs=['x1', 'x2'], outputs=['sum'])
        g = add_node(g, n)
    assert len(g.node) == 10, "Nodes not properly added."
    check = add_node(False, True)
    assert not check, "Incorrectly able to add to non-graph."
    check = add_node(g, False)
    assert not check, "Incorrectly able to add a non-node."
예제 #9
0
def test_replace_output():
    g = empty_graph()
    g = add_output(g, "test", "FLOAT", [0])
    g = replace_output(g, "test", "FLOAT", [10,10])

    type = getattr(g.output[0], "type", False)  # get the output type
    ttype = getattr(type, "tensor_type", False)
    shape = getattr(ttype, "shape", False)
    dim = getattr(shape, "dim", False)
    dim_val = getattr(dim[0], "dim_value", False)

    assert dim_val == 10, "New dimension should be 10"
예제 #10
0
def test_split():
    """
    Functional test for split
    """
    g1 = empty_graph("G1")
    n1 = node('Add', inputs=['x1_1', 'x1_2'], outputs=['sum_1'], name="n1")
    g1 = add_input(g1, 'x1_1', "FLOAT", [1])
    g1 = add_input(g1, 'x1_2', "FLOAT", [1])
    g1 = add_output(g1, 'sum_1', "FLOAT", [1])
    g1 = add_node(g1, n1)

    g2 = empty_graph("G2")
    n2 = node('Add', inputs=['x2_1', 'x2_2'], outputs=['sum_2'], name="n2")
    g2 = add_input(g2, 'x2_1', "FLOAT", [1])
    g2 = add_input(g2, 'x2_2', "FLOAT", [1])
    g2 = add_output(g2, 'sum_2', "FLOAT", [1])
    g2 = add_node(g2, n2)

    g3 = empty_graph("G3")
    n3 = node('Add', inputs=['x3_1', 'x3_2'], outputs=['sum_3'], name="n3")
    g3 = add_input(g3, 'x3_1', "FLOAT", [1])
    g3 = add_input(g3, 'x3_2', "FLOAT", [1])
    g3 = add_output(g3, 'sum_3', "FLOAT", [1])
    g3 = add_node(g3, n3)

    g = split(g1,
              g2,
              g3,
              cg1_match=[("sum_1", "x2_2")],
              cg2_match=[("sum_1", "x3_1")])

    data = {
        "x1_1": np.array([1]).astype(np.float32),
        "x1_2": np.array([2]).astype(np.float32),
        "x2_1": np.array([3]).astype(np.float32),
        "x3_2": np.array([4]).astype(np.float32),
    }
    result = run(g, inputs=data, outputs=["sum_2", "sum_3"])
    assert result[
        0], "Sum of 1,2, and 3 should be equal to constant 6. Split failed."
예제 #11
0
def test_add_constant():

    # Simple add graph
    g = empty_graph()
    n1 = node('Add', inputs=['x1', 'x2'], outputs=['sum'])
    g = add_node(g, n1)

    # Add input and constant
    g = add_constant(g, 'x1', np.array([1]), "INT64")
    g = add_constant(g, 'x2', np.array([5]), "INT64")

    # Output:
    g = add_output(g, 'sum', "INT64", [1])

    # This works, but seems to fail for other data types...
    result = run(g, inputs={}, outputs=["sum"])
    assert result[0] == 6, "Add constant failed."
    # todo(McK): Does not work for INT16 / INT8, check?
예제 #12
0
# Because the if statement to switch between values of 100 and 0 requires a boolean input condition, we add
# a constant node with the value of 7, and add an equals node:
g = so.add_constant(g, "cut", np.array([7]), "INT64")
n2 = so.node("Equal", inputs=['argmax', 'cut'], outputs=['seven'])
g = so.add_node(g, n2)

# Lets again test:
g = so.add_output(g, 'seven', "BOOL", [1])
result = so.run(g, inputs={"input": img_input}, outputs=["seven"])
print(result)  # Prints true... we are getting closer!
g = so.delete_output(g, 'seven')

# Here we build an if statement. Note that the if "switches" between two graphs, so let's first create the
# two graphs (which can obviously be much more complex). We start with the if:
then_graph = so.empty_graph("then-graph")
then_graph = so.add_constant(then_graph, "then_value", np.array([100]),
                             "FLOAT")
then_graph = so.add_output(then_graph, "then_value", "FLOAT", [1])
so.display(
    then_graph)  # See, this is a very small graph, no input, only output

# Same for else
else_graph = so.empty_graph("else-graph")
else_graph = so.add_constant(else_graph, "iff_value", np.array([0]), "FLOAT")
else_graph = so.add_output(else_graph, "iff_value", "FLOAT", [1])

# Now, the If node which switches between the if and the else graph
n3 = so.node("If",
             inputs=['seven'],
             outputs=['horse'],
예제 #13
0
def test_add_node():
    g = empty_graph()
    n = node('Add', inputs=['x1', 'x2'], outputs=['sum'])
    g = add_node(g, n)
    assert len(g.node) == 1, "Node not properly added."
예제 #14
0
This example combines two (sub) graphs into a single graph describing a longer pipeline.

The setup builds on example II (example_02.py). We create 2 separate graphs:
1. Graph that resizes an image from 600x450 to 400x300
2. The empty container graph (check_container.onnx) which takes a 400x300 image

Next, we merge the two graphs into one single ONNX file.
"""

# Let's open the large image and inspect the shape:
large_img = np.array(Image.open("images/1-BIG.JPG"), dtype=np.int32)
print(large_img.shape)  # 450x600x3

# First subgraph for resize:
sg1 = so.empty_graph("resize_graph")
sg1 = so.add_input(sg1, "large_image", "INT32", [450, 600, 3])  # Add the input

# The resize node:
e1 = so.constant("roi", np.array([]),
                 "FLOAT")  # Note the empty fields for roi and scales.
e2 = so.constant("scales", np.array([]), "FLOAT")
c1 = so.constant("size", np.array([300, 400, 3]), "INT64")
n1 = so.node("Resize",
             inputs=['large_image', 'roi', 'scales', 'size'],
             outputs=['small_image'])
sg1 = so.add_nodes(sg1, [e1, e2, c1, n1])
sg1 = so.add_output(sg1, "small_image", "INT32", [300, 400, 3])

# Check and clean
sg1 = so.clean(sg1)
예제 #15
0
def test__input_details():
    g = empty_graph()
    g = add_input(g, 'sum', "FLOAT", [4, 3, 7])
    in_det = _input_details(g)
    assert in_det['sum']['data_type'] == "FLOAT", "Input details not correct."
예제 #16
0
def test__output_details():
    g = empty_graph()
    g = add_output(g, 'sum', "FLOAT", [4, 3, 7])
    out_det = _output_details(g)
    assert out_det['sum'][
        'data_type'] == "FLOAT", "Output details not correct."
예제 #17
0
def test_add_output():
    g = empty_graph()
    g = add_output(g, "test", "FLOAT", [0])
    name = getattr(g.output[0], "name", False)  # get the first output name:
    assert name == "test", "'test' should be in list of outputs."
예제 #18
0
def test_empty_graph():
    g = empty_graph()
    assert type(g) is xpb2.GraphProto, "Failed to create empty graph."
예제 #19
0
https://towardsdatascience.com/onnx-for-image-processing-from-scratch-6694f9b141b0

This example relies on the image "source/images/empty-average.JPG" which provides an average of several
pictures of an empty container.

The logic that we build is simple:
- Given an image of an object (for example 1.JPG in the source/images/ folder
- Subtract the empty-image (which is encoded as a constant in the ONNX graph)
- Compute absolute values
- Sum all elements of the result into a single scalar
- Compare the scalar to a threshold (another constant)
If the threshold is reached, we conclude that the container is filled.
"""

# Start with the empty graph:
g = so.empty_graph()

# Create the constant node encoding the empty image and add it to the graph:
# Note the type encoding as np.int64.
reference_image = np.array(Image.open("images/empty-average.JPG"),
                           dtype=np.int32)
g = so.add_constant(g, "c1", reference_image, "INT32")

# Add the first input (note, same shape):
g = so.add_input(g, 'in', "INT32", reference_image.shape)

# Add the Subtract, Absolute, ReduceSum, and Less nodes
# Node how the names again enforce the topology of the graph
n1 = so.node("Sub", inputs=['in', 'c1'], outputs=['sub'])
n2 = so.node("Abs", inputs=['sub'], outputs=['abs'])
n3 = so.node("ReduceSum", inputs=['abs'], outputs=['sum'],
예제 #20
0
def test_delete_output():
    g = empty_graph()
    g = add_output(g, "test", "FLOAT", [0])
    g = delete_output(g, "test")
    assert len(g.output) == 0, "There should not be any outputs after delete."
예제 #21
0
def test_list_outputs():
    g = empty_graph()
    assert list_outputs(g), "No outputs listed."
    g = add_output(g, "test", "FLOAT", [0])
    list_outputs(g)
    assert not list_outputs(False), "List outputs should be false."
예제 #22
0
EXAMPLE MERGE: a number of examples usages of the merge, join, split, and concat functions.

Note that merge(), join(), and split() are high level wrappers around concat(), each effectively assuming that the
resulting graph is "complete" (i.e., it is a valid onnx graph including input and output). Concat itself is more
flexible and can be used for intermediate merging/concatenation of partial graphs (i.e., graphs that are not yet
finished).

Below we provide a number of examples of each of the functions. We recommend using so.display() throughout to visualize
the resulting graphs and truly understand how the graphs are joined together. Examples are all very simple (small graphs,
scalar operations, etc.), but don't underestimate the complexities involved; with larger graphs the behavior of
the concat function can be challenging.
"""

# # Lets start by creating a few simple (and complete) graphs which we will use throughout:
# # Simple absolute value graph:
g1 = so.empty_graph("g_1")
n1 = so.node('Abs', inputs=['in_1_1'], outputs=['out_1_1'], name="node_1_1")
g1 = so.add_input(g1, 'in_1_1', "FLOAT", [1])
g1 = so.add_output(g1, 'out_1_1', "FLOAT", [1])
g1 = so.add_node(g1, n1)
# so.display(g1)
# data = {"in_1_1": np.array([2]).astype(np.float32)}
# print(so.run(g1, inputs=data, outputs=["out_1_1"]))

# # Simple max value graph:
g2 = so.empty_graph("g_2")
n2 = so.node('Max',
             inputs=['in_2_1', 'in_2_2'],
             outputs=['out_2_1'],
             name="node_2_1")
g2 = so.add_input(g2, 'in_2_1', "FLOAT", [1])
예제 #23
0
def test_rename_output():
    g = empty_graph()
    g = add_output(g, "test", "FLOAT", [0])
    g = rename_output(g, "test", "new_name")
    name = getattr(g.output[0], "name", False)  # get the first output name:
    assert name == "new_name", "New name should be in list of outputs."