diff --git a/x2paddle/convert.py b/x2paddle/convert.py index 92ec1cf502943ee6220aac887a60bbab34f0b0cd..efd665732e6b278fb862fc56df02b548eb7cdced 100644 --- a/x2paddle/convert.py +++ b/x2paddle/convert.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License" # you may not use this file except in compliance with the License. diff --git a/x2paddle/op_mapper/paddle_custom_layer/__init__.py b/x2paddle/op_mapper/paddle_custom_layer/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/x2paddle/op_mapper/paddle_custom_layer/__pycache__/__init__.cpython-37.pyc b/x2paddle/op_mapper/paddle_custom_layer/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b86f3a42a7a72082d54f17434f5860f02e6c3109 Binary files /dev/null and b/x2paddle/op_mapper/paddle_custom_layer/__pycache__/__init__.cpython-37.pyc differ diff --git a/x2paddle/op_mapper/paddle_custom_layer/__pycache__/multiclass_nms.cpython-37.pyc b/x2paddle/op_mapper/paddle_custom_layer/__pycache__/multiclass_nms.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..404e41db99321e1947e1c4a45e5bd28cfa4ebf7c Binary files /dev/null and b/x2paddle/op_mapper/paddle_custom_layer/__pycache__/multiclass_nms.cpython-37.pyc differ diff --git a/x2paddle/op_mapper/paddle_custom_layer/__pycache__/yolo_box.cpython-37.pyc b/x2paddle/op_mapper/paddle_custom_layer/__pycache__/yolo_box.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e45db9914363379695edfbb335d9be86a7327352 Binary files /dev/null and b/x2paddle/op_mapper/paddle_custom_layer/__pycache__/yolo_box.cpython-37.pyc differ diff --git a/x2paddle/op_mapper/paddle_custom_layer/multiclass_nms.py b/x2paddle/op_mapper/paddle_custom_layer/multiclass_nms.py new file mode 100644 index 0000000000000000000000000000000000000000..743c20f3fe001c2105dbc268bbfc7a8597a833b2 --- /dev/null +++ b/x2paddle/op_mapper/paddle_custom_layer/multiclass_nms.py @@ -0,0 +1,415 @@ +# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License" +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math +import sys +import os +import numpy as np +import paddle.fluid.core as core +import paddle.fluid as fluid +import onnx +import warnings +from onnx import helper, onnx_pb + + +def multiclass_nms(op, block): + """ + Convert the paddle multiclass_nms to onnx op. + This op is get the select boxes from origin boxes. + """ + inputs = dict() + outputs = dict() + attrs = dict() + for name in op.input_names: + inputs[name] = op.input(name) + for name in op.output_names: + outputs[name] = op.output(name) + for name in op.attr_names: + attrs[name] = op.attr(name) + + result_name = outputs['Out'][0] + background = attrs['background_label'] + normalized = attrs['normalized'] + if normalized == False: + warnings.warn( + 'The parameter normalized of multiclass_nms OP of Paddle is False, which has diff with ONNX. \ + Please set normalized=True in multiclass_nms of Paddle' + ) + + #convert the paddle attribute to onnx tensor + name_score_threshold = [outputs['Out'][0] + "@score_threshold"] + name_iou_threshold = [outputs['Out'][0] + "@iou_threshold"] + name_keep_top_k = [outputs['Out'][0] + '@keep_top_k'] + name_keep_top_k_2D = [outputs['Out'][0] + '@keep_top_k_1D'] + + node_score_threshold = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_score_threshold, + value=onnx.helper.make_tensor( + name=name_score_threshold[0] + "@const", + data_type=onnx.TensorProto.FLOAT, + dims=(), + vals=[float(attrs['score_threshold'])])) + + node_iou_threshold = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_iou_threshold, + value=onnx.helper.make_tensor( + name=name_iou_threshold[0] + "@const", + data_type=onnx.TensorProto.FLOAT, + dims=(), + vals=[float(attrs['nms_threshold'])])) + + node_keep_top_k = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_keep_top_k, + value=onnx.helper.make_tensor( + name=name_keep_top_k[0] + "@const", + data_type=onnx.TensorProto.INT64, + dims=(), + vals=[np.int64(attrs['keep_top_k'])])) + + node_keep_top_k_2D = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_keep_top_k_2D, + value=onnx.helper.make_tensor( + name=name_keep_top_k_2D[0] + "@const", + data_type=onnx.TensorProto.INT64, + dims=[1, 1], + vals=[np.int64(attrs['keep_top_k'])])) + + # the paddle data format is x1,y1,x2,y2 + kwargs = {'center_point_box': 0} + + name_select_nms = [outputs['Out'][0] + "@select_index"] + node_select_nms= onnx.helper.make_node( + 'NonMaxSuppression', + inputs=inputs['BBoxes'] + inputs['Scores'] + name_keep_top_k +\ + name_iou_threshold + name_score_threshold, + outputs=name_select_nms) + # step 1 nodes select the nms class + node_list = [ + node_score_threshold, node_iou_threshold, node_keep_top_k, + node_keep_top_k_2D, node_select_nms + ] + + # create some const value to use + name_const_value = [result_name+"@const_0", + result_name+"@const_1",\ + result_name+"@const_2",\ + result_name+"@const_-1"] + value_const_value = [0, 1, 2, -1] + for name, value in zip(name_const_value, value_const_value): + node = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=[name], + value=onnx.helper.make_tensor( + name=name + "@const", + data_type=onnx.TensorProto.INT64, + dims=[1], + vals=[value])) + node_list.append(node) + + # Ine this code block, we will deocde the raw score data, reshape N * C * M to 1 * N*C*M + # and the same time, decode the select indices to 1 * D, gather the select_indices + outputs_gather_1 = [result_name + "@gather_1"] + node_gather_1 = onnx.helper.make_node( + 'Gather', + inputs=name_select_nms + [result_name + "@const_1"], + outputs=outputs_gather_1, + axis=1) + node_list.append(node_gather_1) + + outputs_squeeze_gather_1 = [result_name + "@sequeeze_gather_1"] + node_squeeze_gather_1 = onnx.helper.make_node( + 'Squeeze', + inputs=outputs_gather_1, + outputs=outputs_squeeze_gather_1, + axes=[1]) + node_list.append(node_squeeze_gather_1) + + outputs_gather_2 = [result_name + "@gather_2"] + node_gather_2 = onnx.helper.make_node( + 'Gather', + inputs=name_select_nms + [result_name + "@const_2"], + outputs=outputs_gather_2, + axis=1) + node_list.append(node_gather_2) + + #slice the class is not 0 + if background == 0: + outputs_nonzero = [result_name + "@nonzero"] + node_nonzero = onnx.helper.make_node( + 'NonZero', inputs=outputs_squeeze_gather_1, outputs=outputs_nonzero) + node_list.append(node_nonzero) + else: + name_thresh = [result_name + "@thresh"] + node_thresh = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_thresh, + value=onnx.helper.make_tensor( + name=name_thresh[0] + "@const", + data_type=onnx.TensorProto.INT32, + dims=[1], + vals=[-1])) + node_list.append(node_thresh) + + outputs_cast = [result_name + "@cast"] + node_cast = onnx.helper.make_node( + 'Cast', inputs=outputs_squeeze_gather_1, outputs=outputs_cast, to=6) + node_list.append(node_cast) + + outputs_greater = [result_name + "@greater"] + node_greater = onnx.helper.make_node( + 'Greater', + inputs=outputs_cast + name_thresh, + outputs=outputs_greater) + node_list.append(node_greater) + + outputs_nonzero = [result_name + "@nonzero"] + node_nonzero = onnx.helper.make_node( + 'NonZero', inputs=outputs_greater, outputs=outputs_nonzero) + node_list.append(node_nonzero) + + outputs_gather_1_nonzero = [result_name + "@gather_1_nonzero"] + node_gather_1_nonzero = onnx.helper.make_node( + 'Gather', + inputs=outputs_gather_1 + outputs_nonzero, + outputs=outputs_gather_1_nonzero, + axis=0) + node_list.append(node_gather_1_nonzero) + + outputs_gather_2_nonzero = [result_name + "@gather_2_nonzero"] + node_gather_2_nonzero = onnx.helper.make_node( + 'Gather', + inputs=outputs_gather_2 + outputs_nonzero, + outputs=outputs_gather_2_nonzero, + axis=0) + node_list.append(node_gather_2_nonzero) + + # reshape scores N * C * M to (N*C*M) * 1 + outputs_reshape_scores_rank1 = [result_name + "@reshape_scores_rank1"] + node_reshape_scores_rank1 = onnx.helper.make_node( + "Reshape", + inputs=inputs['Scores'] + [result_name + "@const_-1"], + outputs=outputs_reshape_scores_rank1) + node_list.append(node_reshape_scores_rank1) + + # get the shape of scores + outputs_shape_scores = [result_name + "@shape_scores"] + node_shape_scores = onnx.helper.make_node( + 'Shape', inputs=inputs['Scores'], outputs=outputs_shape_scores) + node_list.append(node_shape_scores) + + # gather the index: 2 shape of scores + outputs_gather_scores_dim1 = [result_name + "@gather_scores_dim1"] + node_gather_scores_dim1 = onnx.helper.make_node( + 'Gather', + inputs=outputs_shape_scores + [result_name + "@const_2"], + outputs=outputs_gather_scores_dim1, + axis=0) + node_list.append(node_gather_scores_dim1) + + # mul class * M + outputs_mul_classnum_boxnum = [result_name + "@mul_classnum_boxnum"] + node_mul_classnum_boxnum = onnx.helper.make_node( + 'Mul', + inputs=outputs_gather_1_nonzero + outputs_gather_scores_dim1, + outputs=outputs_mul_classnum_boxnum) + node_list.append(node_mul_classnum_boxnum) + + # add class * M * index + outputs_add_class_M_index = [result_name + "@add_class_M_index"] + node_add_class_M_index = onnx.helper.make_node( + 'Add', + inputs=outputs_mul_classnum_boxnum + outputs_gather_2_nonzero, + outputs=outputs_add_class_M_index) + node_list.append(node_add_class_M_index) + + # Squeeze the indices to 1 dim + outputs_squeeze_select_index = [result_name + "@squeeze_select_index"] + node_squeeze_select_index = onnx.helper.make_node( + 'Squeeze', + inputs=outputs_add_class_M_index, + outputs=outputs_squeeze_select_index, + axes=[0, 2]) + node_list.append(node_squeeze_select_index) + + # gather the data from flatten scores + outputs_gather_select_scores = [result_name + "@gather_select_scores"] + node_gather_select_scores = onnx.helper.make_node('Gather', + inputs=outputs_reshape_scores_rank1 + \ + outputs_squeeze_select_index, + outputs=outputs_gather_select_scores, + axis=0) + node_list.append(node_gather_select_scores) + + # get nums to input TopK + outputs_shape_select_num = [result_name + "@shape_select_num"] + node_shape_select_num = onnx.helper.make_node( + 'Shape', + inputs=outputs_gather_select_scores, + outputs=outputs_shape_select_num) + node_list.append(node_shape_select_num) + + outputs_gather_select_num = [result_name + "@gather_select_num"] + node_gather_select_num = onnx.helper.make_node( + 'Gather', + inputs=outputs_shape_select_num + [result_name + "@const_0"], + outputs=outputs_gather_select_num, + axis=0) + node_list.append(node_gather_select_num) + + outputs_unsqueeze_select_num = [result_name + "@unsqueeze_select_num"] + node_unsqueeze_select_num = onnx.helper.make_node( + 'Unsqueeze', + inputs=outputs_gather_select_num, + outputs=outputs_unsqueeze_select_num, + axes=[0]) + node_list.append(node_unsqueeze_select_num) + + outputs_concat_topK_select_num = [result_name + "@conat_topK_select_num"] + node_conat_topK_select_num = onnx.helper.make_node( + 'Concat', + inputs=outputs_unsqueeze_select_num + name_keep_top_k_2D, + outputs=outputs_concat_topK_select_num, + axis=0) + node_list.append(node_conat_topK_select_num) + + outputs_cast_concat_topK_select_num = [ + result_name + "@concat_topK_select_num" + ] + node_outputs_cast_concat_topK_select_num = onnx.helper.make_node( + 'Cast', + inputs=outputs_concat_topK_select_num, + outputs=outputs_cast_concat_topK_select_num, + to=6) + node_list.append(node_outputs_cast_concat_topK_select_num) + # get min(topK, num_select) + outputs_compare_topk_num_select = [result_name + "@compare_topk_num_select"] + node_compare_topk_num_select = onnx.helper.make_node( + 'ReduceMin', + inputs=outputs_cast_concat_topK_select_num, + outputs=outputs_compare_topk_num_select, + keepdims=0) + node_list.append(node_compare_topk_num_select) + + # unsqueeze the indices to 1D tensor + outputs_unsqueeze_topk_select_indices = [ + result_name + "@unsqueeze_topk_select_indices" + ] + node_unsqueeze_topk_select_indices = onnx.helper.make_node( + 'Unsqueeze', + inputs=outputs_compare_topk_num_select, + outputs=outputs_unsqueeze_topk_select_indices, + axes=[0]) + node_list.append(node_unsqueeze_topk_select_indices) + + # cast the indices to INT64 + outputs_cast_topk_indices = [result_name + "@cast_topk_indices"] + node_cast_topk_indices = onnx.helper.make_node( + 'Cast', + inputs=outputs_unsqueeze_topk_select_indices, + outputs=outputs_cast_topk_indices, + to=7) + node_list.append(node_cast_topk_indices) + + # select topk scores indices + outputs_topk_select_topk_indices = [result_name + "@topk_select_topk_values",\ + result_name + "@topk_select_topk_indices"] + node_topk_select_topk_indices = onnx.helper.make_node( + 'TopK', + inputs=outputs_gather_select_scores + outputs_cast_topk_indices, + outputs=outputs_topk_select_topk_indices) + node_list.append(node_topk_select_topk_indices) + + # gather topk label, scores, boxes + outputs_gather_topk_scores = [result_name + "@gather_topk_scores"] + node_gather_topk_scores = onnx.helper.make_node( + 'Gather', + inputs=outputs_gather_select_scores + + [outputs_topk_select_topk_indices[1]], + outputs=outputs_gather_topk_scores, + axis=0) + node_list.append(node_gather_topk_scores) + + outputs_gather_topk_class = [result_name + "@gather_topk_class"] + node_gather_topk_class = onnx.helper.make_node( + 'Gather', + inputs=outputs_gather_1_nonzero + [outputs_topk_select_topk_indices[1]], + outputs=outputs_gather_topk_class, + axis=1) + node_list.append(node_gather_topk_class) + + # gather the boxes need to gather the boxes id, then get boxes + outputs_gather_topk_boxes_id = [result_name + "@gather_topk_boxes_id"] + node_gather_topk_boxes_id = onnx.helper.make_node( + 'Gather', + inputs=outputs_gather_2_nonzero + [outputs_topk_select_topk_indices[1]], + outputs=outputs_gather_topk_boxes_id, + axis=1) + node_list.append(node_gather_topk_boxes_id) + + # squeeze the gather_topk_boxes_id to 1 dim + outputs_squeeze_topk_boxes_id = [result_name + "@squeeze_topk_boxes_id"] + node_squeeze_topk_boxes_id = onnx.helper.make_node( + 'Squeeze', + inputs=outputs_gather_topk_boxes_id, + outputs=outputs_squeeze_topk_boxes_id, + axes=[0, 2]) + node_list.append(node_squeeze_topk_boxes_id) + + outputs_gather_select_boxes = [result_name + "@gather_select_boxes"] + node_gather_select_boxes = onnx.helper.make_node( + 'Gather', + inputs=inputs['BBoxes'] + outputs_squeeze_topk_boxes_id, + outputs=outputs_gather_select_boxes, + axis=1) + node_list.append(node_gather_select_boxes) + + # concat the final result + # before concat need to cast the class to float + outputs_cast_topk_class = [result_name + "@cast_topk_class"] + node_cast_topk_class = onnx.helper.make_node( + 'Cast', + inputs=outputs_gather_topk_class, + outputs=outputs_cast_topk_class, + to=1) + node_list.append(node_cast_topk_class) + + outputs_unsqueeze_topk_scores = [result_name + "@unsqueeze_topk_scores"] + node_unsqueeze_topk_scores = onnx.helper.make_node( + 'Unsqueeze', + inputs=outputs_gather_topk_scores, + outputs=outputs_unsqueeze_topk_scores, + axes=[0, 2]) + node_list.append(node_unsqueeze_topk_scores) + + inputs_concat_final_results = outputs_cast_topk_class + outputs_unsqueeze_topk_scores +\ + outputs_gather_select_boxes + outputs_concat_final_results = outputs['Out'] + node_concat_final_results = onnx.helper.make_node( + 'Concat', + inputs=inputs_concat_final_results, + outputs=outputs_concat_final_results, + axis=2) + node_list.append(node_concat_final_results) + + return node_list diff --git a/x2paddle/op_mapper/paddle_custom_layer/yolo_box.py b/x2paddle/op_mapper/paddle_custom_layer/yolo_box.py new file mode 100644 index 0000000000000000000000000000000000000000..50e048c4aaadcedf9ef566d39487bdb11a32f5d1 --- /dev/null +++ b/x2paddle/op_mapper/paddle_custom_layer/yolo_box.py @@ -0,0 +1,824 @@ +import onnx +import numpy as np +from onnx import onnx_pb, helper + + +def get_old_name(arg, name_prefix=''): + """Get the old rame for a possible renamed argument + """ + prefix_index = arg.find(name_prefix) + + if prefix_index != -1: + last_prefix = arg[len(name_prefix):] + else: + last_prefix = arg + idx = last_prefix.find('@') + if idx != -1: + last_prefix = last_prefix[:idx] + return name_prefix + last_prefix + + +def yolo_box(op, block): + inputs = dict() + outputs = dict() + attrs = dict() + for name in op.input_names: + inputs[name] = op.input(name) + for name in op.output_names: + outputs[name] = op.output(name) + for name in op.attr_names: + attrs[name] = op.attr(name) + model_name = outputs['Boxes'][0] + input_shape = block.vars[get_old_name(inputs['X'][0])].shape + image_size = inputs['ImgSize'] + input_height = input_shape[2] + input_width = input_shape[3] + + class_num = attrs['class_num'] + anchors = attrs['anchors'] + num_anchors = int(len(anchors)) // 2 + downsample_ratio = attrs['downsample_ratio'] + input_size = input_height * downsample_ratio + conf_thresh = attrs['conf_thresh'] + conf_thresh_mat = np.ones([num_anchors * input_height * input_width + ]) * conf_thresh + + node_list = [] + im_outputs = [] + + x_shape = [1, num_anchors, 5 + class_num, input_height, input_width] + name_x_shape = [model_name + "@x_shape"] + node_x_shape = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_x_shape, + value=onnx.helper.make_tensor( + name=name_x_shape[0] + "@const", + data_type=onnx.TensorProto.INT64, + dims=[5], + vals=x_shape)) + node_list.append(node_x_shape) + + outputs_x_reshape = [model_name + "@reshape"] + node_x_reshape = onnx.helper.make_node( + 'Reshape', inputs=inputs['X'] + name_x_shape, outputs=outputs_x_reshape) + node_list.append(node_x_reshape) + + outputs_x_transpose = [model_name + "@x_transpose"] + node_x_transpose = onnx.helper.make_node( + 'Transpose', + inputs=outputs_x_reshape, + outputs=outputs_x_transpose, + perm=[0, 1, 3, 4, 2]) + node_list.append(node_x_transpose) + + range_x = [] + range_y = [] + for i in range(0, input_width): + range_x.append(i) + for j in range(0, input_height): + range_y.append(j) + + name_range_x = [model_name + "@range_x"] + node_range_x = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_range_x, + value=onnx.helper.make_tensor( + name=name_range_x[0] + "@const", + data_type=onnx.TensorProto.FLOAT, + dims=[input_width], + vals=range_x)) + node_list.append(node_range_x) + + name_range_y = [model_name + "@range_y"] + node_range_y = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_range_y, + value=onnx.helper.make_tensor( + name=name_range_y[0] + "@const", + data_type=onnx.TensorProto.FLOAT, + dims=[input_height], + vals=range_y)) + node_list.append(node_range_y) + + range_x_new_shape = [1, input_width] + range_y_new_shape = [input_height, 1] + + name_range_x_new_shape = [model_name + "@range_x_new_shape"] + node_range_x_new_shape = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_range_x_new_shape, + value=onnx.helper.make_tensor( + name=name_range_x_new_shape[0] + "@const", + data_type=onnx.TensorProto.INT64, + dims=[len(range_x_new_shape)], + vals=range_x_new_shape)) + node_list.append(node_range_x_new_shape) + + name_range_y_new_shape = [model_name + "@range_y_new_shape"] + node_range_y_new_shape = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_range_y_new_shape, + value=onnx.helper.make_tensor( + name=name_range_y_new_shape[0] + "@const", + data_type=onnx.TensorProto.INT64, + dims=[len(range_y_new_shape)], + vals=range_y_new_shape)) + node_list.append(node_range_y_new_shape) + + outputs_range_x_reshape = [model_name + "@range_x_reshape"] + node_range_x_reshape = onnx.helper.make_node( + 'Reshape', + inputs=name_range_x + name_range_x_new_shape, + outputs=outputs_range_x_reshape) + node_list.append(node_range_x_reshape) + + outputs_range_y_reshape = [model_name + "@range_y_reshape"] + node_range_y_reshape = onnx.helper.make_node( + 'Reshape', + inputs=name_range_y + name_range_y_new_shape, + outputs=outputs_range_y_reshape) + node_list.append(node_range_y_reshape) + + outputs_grid_x = [model_name + "@grid_x"] + node_grid_x = onnx.helper.make_node( + "Tile", + inputs=outputs_range_x_reshape + name_range_y_new_shape, + outputs=outputs_grid_x) + node_list.append(node_grid_x) + + outputs_grid_y = [model_name + "@grid_y"] + node_grid_y = onnx.helper.make_node( + "Tile", + inputs=outputs_range_y_reshape + name_range_x_new_shape, + outputs=outputs_grid_y) + node_list.append(node_grid_y) + + outputs_box_x = [model_name + "@box_x"] + outputs_box_y = [model_name + "@box_y"] + outputs_box_w = [model_name + "@box_w"] + outputs_box_h = [model_name + "@box_h"] + outputs_conf = [model_name + "@conf"] + outputs_prob = [model_name + "@prob"] + + node_split_input = onnx.helper.make_node( + "Split", + inputs=outputs_x_transpose, + outputs=outputs_box_x + outputs_box_y + outputs_box_w\ + + outputs_box_h + outputs_conf + outputs_prob, + axis=-1, + split=[1, 1, 1, 1, 1, class_num]) + node_list.append(node_split_input) + + outputs_box_x_sigmoid = [model_name + "@box_x_sigmoid"] + outputs_box_y_sigmoid = [model_name + "@box_y_sigmoid"] + + node_box_x_sigmoid = onnx.helper.make_node( + "Sigmoid", inputs=outputs_box_x, outputs=outputs_box_x_sigmoid) + node_list.append(node_box_x_sigmoid) + + node_box_y_sigmoid = onnx.helper.make_node( + "Sigmoid", inputs=outputs_box_y, outputs=outputs_box_y_sigmoid) + node_list.append(node_box_y_sigmoid) + + outputs_box_x_squeeze = [model_name + "@box_x_squeeze"] + outputs_box_y_squeeze = [model_name + "@box_y_squeeze"] + + node_box_x_squeeze = onnx.helper.make_node( + 'Squeeze', + inputs=outputs_box_x_sigmoid, + outputs=outputs_box_x_squeeze, + axes=[4]) + node_list.append(node_box_x_squeeze) + + node_box_y_squeeze = onnx.helper.make_node( + 'Squeeze', + inputs=outputs_box_y_sigmoid, + outputs=outputs_box_y_squeeze, + axes=[4]) + node_list.append(node_box_y_squeeze) + + outputs_box_x_add_grid = [model_name + "@box_x_add_grid"] + outputs_box_y_add_grid = [model_name + "@box_y_add_grid"] + + node_box_x_add_grid = onnx.helper.make_node( + "Add", + inputs=outputs_grid_x + outputs_box_x_squeeze, + outputs=outputs_box_x_add_grid) + node_list.append(node_box_x_add_grid) + + node_box_y_add_grid = onnx.helper.make_node( + "Add", + inputs=outputs_grid_y + outputs_box_y_squeeze, + outputs=outputs_box_y_add_grid) + node_list.append(node_box_y_add_grid) + + name_input_h = [model_name + "@input_h"] + name_input_w = [model_name + "@input_w"] + + node_input_h = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_input_h, + value=onnx.helper.make_tensor( + name=name_input_w[0] + "@const", + data_type=onnx.TensorProto.FLOAT, + dims=(), + vals=[input_height])) + node_list.append(node_input_h) + + node_input_w = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_input_w, + value=onnx.helper.make_tensor( + name=name_input_w[0] + "@const", + data_type=onnx.TensorProto.FLOAT, + dims=(), + vals=[input_width])) + node_list.append(node_input_w) + + outputs_box_x_encode = [model_name + "@box_x_encode"] + outputs_box_y_encode = [model_name + "@box_y_encode"] + + node_box_x_encode = onnx.helper.make_node( + 'Div', + inputs=outputs_box_x_add_grid + name_input_w, + outputs=outputs_box_x_encode) + node_list.append(node_box_x_encode) + + node_box_y_encode = onnx.helper.make_node( + 'Div', + inputs=outputs_box_y_add_grid + name_input_h, + outputs=outputs_box_y_encode) + node_list.append(node_box_y_encode) + + name_anchor_tensor = [model_name + "@anchor_tensor"] + node_anchor_tensor = onnx.helper.make_node( + "Constant", + inputs=[], + outputs=name_anchor_tensor, + value=onnx.helper.make_tensor( + name=name_anchor_tensor[0] + "@const", + data_type=onnx.TensorProto.FLOAT, + dims=[len(anchors)], + vals=anchors)) + node_list.append(node_anchor_tensor) + + anchor_shape = [int(num_anchors), 2] + name_anchor_shape = [model_name + "@anchor_shape"] + node_anchor_shape = onnx.helper.make_node( + "Constant", + inputs=[], + outputs=name_anchor_shape, + value=onnx.helper.make_tensor( + name=name_anchor_shape[0] + "@const", + data_type=onnx.TensorProto.INT64, + dims=[2], + vals=anchor_shape)) + node_list.append(node_anchor_shape) + + outputs_anchor_tensor_reshape = [model_name + "@anchor_tensor_reshape"] + node_anchor_tensor_reshape = onnx.helper.make_node( + "Reshape", + inputs=name_anchor_tensor + name_anchor_shape, + outputs=outputs_anchor_tensor_reshape) + node_list.append(node_anchor_tensor_reshape) + + name_input_size = [model_name + "@input_size"] + node_input_size = onnx.helper.make_node( + "Constant", + inputs=[], + outputs=name_input_size, + value=onnx.helper.make_tensor( + name=name_input_size[0] + "@const", + data_type=onnx.TensorProto.FLOAT, + dims=(), + vals=[input_size])) + node_list.append(node_input_size) + + outputs_anchors_div_input_size = [model_name + "@anchors_div_input_size"] + node_anchors_div_input_size = onnx.helper.make_node( + "Div", + inputs=outputs_anchor_tensor_reshape + name_input_size, + outputs=outputs_anchors_div_input_size) + node_list.append(node_anchors_div_input_size) + + outputs_anchor_w = [model_name + "@anchor_w"] + outputs_anchor_h = [model_name + "@anchor_h"] + + node_anchor_split = onnx.helper.make_node( + 'Split', + inputs=outputs_anchors_div_input_size, + outputs=outputs_anchor_w + outputs_anchor_h, + axis=1, + split=[1, 1]) + node_list.append(node_anchor_split) + + new_anchor_shape = [1, int(num_anchors), 1, 1] + name_new_anchor_shape = [model_name + "@new_anchor_shape"] + node_new_anchor_shape = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_new_anchor_shape, + value=onnx.helper.make_tensor( + name=name_new_anchor_shape[0] + "@const", + data_type=onnx.TensorProto.INT64, + dims=[len(new_anchor_shape)], + vals=new_anchor_shape)) + node_list.append(node_new_anchor_shape) + + outputs_anchor_w_reshape = [model_name + "@anchor_w_reshape"] + outputs_anchor_h_reshape = [model_name + "@anchor_h_reshape"] + + node_anchor_w_reshape = onnx.helper.make_node( + 'Reshape', + inputs=outputs_anchor_w + name_new_anchor_shape, + outputs=outputs_anchor_w_reshape) + node_list.append(node_anchor_w_reshape) + + node_anchor_h_reshape = onnx.helper.make_node( + 'Reshape', + inputs=outputs_anchor_h + name_new_anchor_shape, + outputs=outputs_anchor_h_reshape) + node_list.append(node_anchor_h_reshape) + + outputs_box_w_squeeze = [model_name + "@box_w_squeeze"] + node_box_w_squeeze = onnx.helper.make_node( + 'Squeeze', + inputs=outputs_box_w, + outputs=outputs_box_w_squeeze, + axes=[4]) + node_list.append(node_box_w_squeeze) + + outputs_box_h_squeeze = [model_name + "@box_h_squeeze"] + node_box_h_squeeze = onnx.helper.make_node( + 'Squeeze', + inputs=outputs_box_h, + outputs=outputs_box_h_squeeze, + axes=[4]) + node_list.append(node_box_h_squeeze) + + outputs_box_w_exp = [model_name + "@box_w_exp"] + node_box_w_exp = onnx.helper.make_node( + "Exp", inputs=outputs_box_w_squeeze, outputs=outputs_box_w_exp) + node_list.append(node_box_w_exp) + + outputs_box_h_exp = [model_name + "@box_h_exp"] + node_box_h_exp = onnx.helper.make_node( + "Exp", inputs=outputs_box_h_squeeze, outputs=outputs_box_h_exp) + node_list.append(node_box_h_exp) + + outputs_box_w_encode = [model_name + "box_w_encode"] + outputs_box_h_encode = [model_name + "box_h_encode"] + + node_box_w_encode = onnx.helper.make_node( + 'Mul', + inputs=outputs_box_w_exp + outputs_anchor_w_reshape, + outputs=outputs_box_w_encode) + node_list.append(node_box_w_encode) + + node_box_h_encode = onnx.helper.make_node( + 'Mul', + inputs=outputs_box_h_exp + outputs_anchor_h_reshape, + outputs=outputs_box_h_encode) + node_list.append(node_box_h_encode) + + outputs_conf_sigmoid = [model_name + "@conf_sigmoid"] + node_conf_sigmoid = onnx.helper.make_node( + 'Sigmoid', inputs=outputs_conf, outputs=outputs_conf_sigmoid) + node_list.append(node_conf_sigmoid) + + name_conf_thresh = [model_name + "@conf_thresh"] + node_conf_thresh = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_conf_thresh, + value=onnx.helper.make_tensor( + name=name_conf_thresh[0] + "@const", + data_type=onnx.TensorProto.FLOAT, + dims=[num_anchors * input_height * input_width], + vals=conf_thresh_mat)) + node_list.append(node_conf_thresh) + + conf_shape = [1, int(num_anchors), input_height, input_width, 1] + name_conf_shape = [model_name + "@conf_shape"] + node_conf_shape = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_conf_shape, + value=onnx.helper.make_tensor( + name=name_conf_shape[0] + "@const", + data_type=onnx.TensorProto.INT64, + dims=[len(conf_shape)], + vals=conf_shape)) + node_list.append(node_conf_shape) + + outputs_conf_thresh_reshape = [model_name + "@conf_thresh_reshape"] + node_conf_thresh_reshape = onnx.helper.make_node( + 'Reshape', + inputs=name_conf_thresh + name_conf_shape, + outputs=outputs_conf_thresh_reshape) + node_list.append(node_conf_thresh_reshape) + + outputs_conf_sub = [model_name + "@conf_sub"] + node_conf_sub = onnx.helper.make_node( + 'Sub', + inputs=outputs_conf_sigmoid + outputs_conf_thresh_reshape, + outputs=outputs_conf_sub) + node_list.append(node_conf_sub) + + outputs_conf_clip = [model_name + "@conf_clip"] + node_conf_clip = onnx.helper.make_node( + 'Clip', inputs=outputs_conf_sub, outputs=outputs_conf_clip) + node_list.append(node_conf_clip) + + zeros = [0] + name_zeros = [model_name + "@zeros"] + node_zeros = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_zeros, + value=onnx.helper.make_tensor( + name=name_zeros[0] + "@const", + data_type=onnx.TensorProto.FLOAT, + dims=(), + vals=zeros)) + node_list.append(node_zeros) + + outputs_conf_clip_bool = [model_name + "@conf_clip_bool"] + node_conf_clip_bool = onnx.helper.make_node( + 'Greater', + inputs=outputs_conf_clip + name_zeros, + outputs=outputs_conf_clip_bool) + node_list.append(node_conf_clip_bool) + + outputs_conf_clip_cast = [model_name + "@conf_clip_cast"] + node_conf_clip_cast = onnx.helper.make_node( + 'Cast', + inputs=outputs_conf_clip_bool, + outputs=outputs_conf_clip_cast, + to=1) + node_list.append(node_conf_clip_cast) + + outputs_conf_set_zero = [model_name + "@conf_set_zero"] + node_conf_set_zero = onnx.helper.make_node( + 'Mul', + inputs=outputs_conf_sigmoid + outputs_conf_clip_cast, + outputs=outputs_conf_set_zero) + node_list.append(node_conf_set_zero) + + outputs_prob_sigmoid = [model_name + "@prob_sigmoid"] + node_prob_sigmoid = onnx.helper.make_node( + 'Sigmoid', inputs=outputs_prob, outputs=outputs_prob_sigmoid) + node_list.append(node_prob_sigmoid) + + new_shape = [1, int(num_anchors), input_height, input_width, 1] + name_new_shape = [model_name + "@new_shape"] + node_new_shape = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_new_shape, + value=onnx.helper.make_tensor( + name=name_new_shape[0] + "@const", + data_type=onnx.TensorProto.INT64, + dims=[len(new_shape)], + vals=new_shape)) + node_list.append(node_new_shape) + + outputs_conf_new_shape = [model_name + "@_conf_new_shape"] + node_conf_new_shape = onnx.helper.make_node( + 'Reshape', + inputs=outputs_conf_set_zero + name_new_shape, + outputs=outputs_conf_new_shape) + node_list.append(node_conf_new_shape) + + outputs_score = [model_name + "@score"] + node_score = onnx.helper.make_node( + 'Mul', + inputs=outputs_prob_sigmoid + outputs_conf_new_shape, + outputs=outputs_score) + node_list.append(node_score) + + outputs_conf_bool = [model_name + "@conf_bool"] + node_conf_bool = onnx.helper.make_node( + 'Greater', + inputs=outputs_conf_new_shape + name_zeros, + outputs=outputs_conf_bool) + node_list.append(node_conf_bool) + + outputs_box_x_new_shape = [model_name + "@box_x_new_shape"] + node_box_x_new_shape = onnx.helper.make_node( + 'Reshape', + inputs=outputs_box_x_encode + name_new_shape, + outputs=outputs_box_x_new_shape) + node_list.append(node_box_x_new_shape) + + outputs_box_y_new_shape = [model_name + "@box_y_new_shape"] + node_box_y_new_shape = onnx.helper.make_node( + 'Reshape', + inputs=outputs_box_y_encode + name_new_shape, + outputs=outputs_box_y_new_shape) + node_list.append(node_box_y_new_shape) + + outputs_box_w_new_shape = [model_name + "@box_w_new_shape"] + node_box_w_new_shape = onnx.helper.make_node( + 'Reshape', + inputs=outputs_box_w_encode + name_new_shape, + outputs=outputs_box_w_new_shape) + node_list.append(node_box_w_new_shape) + + outputs_box_h_new_shape = [model_name + "@box_h_new_shape"] + node_box_h_new_shape = onnx.helper.make_node( + 'Reshape', + inputs=outputs_box_h_encode + name_new_shape, + outputs=outputs_box_h_new_shape) + node_list.append(node_box_h_new_shape) + + outputs_pred_box = [model_name + "@pred_box"] + node_pred_box = onnx.helper.make_node( + 'Concat', + inputs=outputs_box_x_new_shape + outputs_box_y_new_shape + \ + outputs_box_w_new_shape + outputs_box_h_new_shape, + outputs=outputs_pred_box, + axis=4) + node_list.append(node_pred_box) + + outputs_conf_cast = [model_name + "conf_cast"] + node_conf_cast = onnx.helper.make_node( + 'Cast', inputs=outputs_conf_bool, outputs=outputs_conf_cast, to=1) + node_list.append(node_conf_cast) + + outputs_pred_box_mul_conf = [model_name + "@pred_box_mul_conf"] + node_pred_box_mul_conf = onnx.helper.make_node( + 'Mul', + inputs=outputs_pred_box + outputs_conf_cast, + outputs=outputs_pred_box_mul_conf) + node_list.append(node_pred_box_mul_conf) + + box_shape = [1, int(num_anchors) * input_height * input_width, 4] + name_box_shape = [model_name + "@box_shape"] + node_box_shape = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_box_shape, + value=onnx.helper.make_tensor( + name=name_box_shape[0] + "@const", + data_type=onnx.TensorProto.INT64, + dims=[len(box_shape)], + vals=box_shape)) + node_list.append(node_box_shape) + + outputs_pred_box_new_shape = [model_name + "@pred_box_new_shape"] + node_pred_box_new_shape = onnx.helper.make_node( + 'Reshape', + inputs=outputs_pred_box_mul_conf + name_box_shape, + outputs=outputs_pred_box_new_shape) + node_list.append(node_pred_box_new_shape) + + outputs_pred_box_x = [model_name + "@_pred_box_x"] + outputs_pred_box_y = [model_name + "@_pred_box_y"] + outputs_pred_box_w = [model_name + "@_pred_box_w"] + outputs_pred_box_h = [model_name + "@_pred_box_h"] + + node_pred_box_split = onnx.helper.make_node( + 'Split', + inputs=outputs_pred_box_new_shape, + outputs=outputs_pred_box_x + outputs_pred_box_y + outputs_pred_box_w + + outputs_pred_box_h, + axis=2) + node_list.append(node_pred_box_split) + + name_number_two = [model_name + "@number_two"] + node_number_two = onnx.helper.make_node( + "Constant", + inputs=[], + outputs=name_number_two, + value=onnx.helper.make_tensor( + name=name_number_two[0] + "@const", + data_type=onnx.TensorProto.FLOAT, + dims=(), + vals=[2])) + node_list.append(node_number_two) + + outputs_half_w = [model_name + "@half_w"] + node_half_w = onnx.helper.make_node( + "Div", + inputs=outputs_pred_box_w + name_number_two, + outputs=outputs_half_w) + node_list.append(node_half_w) + + outputs_half_h = [model_name + "@half_h"] + node_half_h = onnx.helper.make_node( + "Div", + inputs=outputs_pred_box_h + name_number_two, + outputs=outputs_half_h) + node_list.append(node_half_h) + + outputs_pred_box_x1 = [model_name + "@pred_box_x1"] + node_pred_box_x1 = onnx.helper.make_node( + 'Sub', + inputs=outputs_pred_box_x + outputs_half_w, + outputs=outputs_pred_box_x1) + node_list.append(node_pred_box_x1) + + outputs_pred_box_y1 = [model_name + "@pred_box_y1"] + node_pred_box_y1 = onnx.helper.make_node( + 'Sub', + inputs=outputs_pred_box_y + outputs_half_h, + outputs=outputs_pred_box_y1) + node_list.append(node_pred_box_y1) + + outputs_pred_box_x2 = [model_name + "@pred_box_x2"] + node_pred_box_x2 = onnx.helper.make_node( + 'Add', + inputs=outputs_pred_box_x + outputs_half_w, + outputs=outputs_pred_box_x2) + node_list.append(node_pred_box_x2) + + outputs_pred_box_y2 = [model_name + "@pred_box_y2"] + node_pred_box_y2 = onnx.helper.make_node( + 'Add', + inputs=outputs_pred_box_y + outputs_half_h, + outputs=outputs_pred_box_y2) + node_list.append(node_pred_box_y2) + + outputs_sqeeze_image_size = [model_name + "@sqeeze_image_size"] + node_sqeeze_image_size = onnx.helper.make_node( + "Squeeze", + axes=[0], + inputs=image_size, + outputs=outputs_sqeeze_image_size) + node_list.append(node_sqeeze_image_size) + + output_img_height = [model_name + "@img_height"] + output_img_width = [model_name + "@img_width"] + node_image_size_split = onnx.helper.make_node( + "Split", + inputs=outputs_sqeeze_image_size, + outputs=output_img_height + output_img_width, + axis=-1, + split=[1, 1]) + node_list.append(node_image_size_split) + + output_img_width_cast = [model_name + "@img_width_cast"] + node_img_width_cast = onnx.helper.make_node( + 'Cast', inputs=output_img_width, outputs=output_img_width_cast, to=1) + node_list.append(node_img_width_cast) + + output_img_height_cast = [model_name + "@img_height_cast"] + node_img_height_cast = onnx.helper.make_node( + 'Cast', inputs=output_img_height, outputs=output_img_height_cast, to=1) + node_list.append(node_img_height_cast) + + outputs_pred_box_x1_decode = [model_name + "@pred_box_x1_decode"] + outputs_pred_box_y1_decode = [model_name + "@pred_box_y1_decode"] + outputs_pred_box_x2_decode = [model_name + "@pred_box_x2_decode"] + outputs_pred_box_y2_decode = [model_name + "@pred_box_y2_decode"] + + node_pred_box_x1_decode = onnx.helper.make_node( + 'Mul', + inputs=outputs_pred_box_x1 + output_img_width_cast, + outputs=outputs_pred_box_x1_decode) + node_list.append(node_pred_box_x1_decode) + + node_pred_box_y1_decode = onnx.helper.make_node( + 'Mul', + inputs=outputs_pred_box_y1 + output_img_height_cast, + outputs=outputs_pred_box_y1_decode) + node_list.append(node_pred_box_y1_decode) + + node_pred_box_x2_decode = onnx.helper.make_node( + 'Mul', + inputs=outputs_pred_box_x2 + output_img_width_cast, + outputs=outputs_pred_box_x2_decode) + node_list.append(node_pred_box_x2_decode) + + node_pred_box_y2_decode = onnx.helper.make_node( + 'Mul', + inputs=outputs_pred_box_y2 + output_img_height_cast, + outputs=outputs_pred_box_y2_decode) + node_list.append(node_pred_box_y2_decode) + + name_number_one = [model_name + "@one"] + node_number_one = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=name_number_one, + value=onnx.helper.make_tensor( + name=name_number_one[0] + "@const", + data_type=onnx.TensorProto.FLOAT, + dims=(), + vals=[1])) + node_list.append(node_number_one) + + output_new_img_height = [model_name + "@new_img_height"] + node_new_img_height = onnx.helper.make_node( + 'Sub', + inputs=output_img_height_cast + name_number_one, + outputs=output_new_img_height) + node_list.append(node_new_img_height) + + output_new_img_width = [model_name + "@new_img_width"] + node_new_img_width = onnx.helper.make_node( + 'Sub', + inputs=output_img_width_cast + name_number_one, + outputs=output_new_img_width) + node_list.append(node_new_img_width) + + outputs_pred_box_x2_sub_w = [model_name + "@pred_box_x2_sub_w"] + node_pred_box_x2_sub_w = onnx.helper.make_node( + 'Sub', + inputs=outputs_pred_box_x2_decode + output_new_img_width, + outputs=outputs_pred_box_x2_sub_w) + node_list.append(node_pred_box_x2_sub_w) + + outputs_pred_box_y2_sub_h = [model_name + "@pred_box_y2_sub_h"] + node_pred_box_y2_sub_h = onnx.helper.make_node( + 'Sub', + inputs=outputs_pred_box_y2_decode + output_new_img_height, + outputs=outputs_pred_box_y2_sub_h) + node_list.append(node_pred_box_y2_sub_h) + + outputs_pred_box_x1_clip = [model_name + "@pred_box_x1_clip"] + outputs_pred_box_y1_clip = [model_name + "@pred_box_y1_clip"] + outputs_pred_box_x2_clip = [model_name + "@pred_box_x2_clip"] + outputs_pred_box_y2_clip = [model_name + "@pred_box_y2_clip"] + + node_pred_box_x1_clip = onnx.helper.make_node( + 'Clip', + inputs=outputs_pred_box_x1_decode, + outputs=outputs_pred_box_x1_clip, + min=0.0, + max=float(np.inf)) + node_list.append(node_pred_box_x1_clip) + + node_pred_box_y1_clip = onnx.helper.make_node( + 'Clip', + inputs=outputs_pred_box_y1_decode, + outputs=outputs_pred_box_y1_clip, + min=0.0, + max=float(np.inf)) + node_list.append(node_pred_box_y1_clip) + + node_pred_box_x2_clip = onnx.helper.make_node( + 'Clip', + inputs=outputs_pred_box_x2_sub_w, + outputs=outputs_pred_box_x2_clip, + min=0.0, + max=float(np.inf)) + node_list.append(node_pred_box_x2_clip) + + node_pred_box_y2_clip = onnx.helper.make_node( + 'Clip', + inputs=outputs_pred_box_y2_sub_h, + outputs=outputs_pred_box_y2_clip, + min=0.0, + max=float(np.inf)) + node_list.append(node_pred_box_y2_clip) + + outputs_pred_box_x2_res = [model_name + "@box_x2_res"] + node_pred_box_x2_res = onnx.helper.make_node( + 'Sub', + inputs=outputs_pred_box_x2_decode + outputs_pred_box_x2_clip, + outputs=outputs_pred_box_x2_res) + node_list.append(node_pred_box_x2_res) + + outputs_pred_box_y2_res = [model_name + "@box_y2_res"] + node_pred_box_y2_res = onnx.helper.make_node( + 'Sub', + inputs=outputs_pred_box_y2_decode + outputs_pred_box_y2_clip, + outputs=outputs_pred_box_y2_res) + node_list.append(node_pred_box_y2_res) + + node_pred_box_result = onnx.helper.make_node( + 'Concat', + inputs=outputs_pred_box_x1_clip + outputs_pred_box_y1_clip + + outputs_pred_box_x2_res + outputs_pred_box_y2_res, + outputs=outputs['Boxes'], + axis=-1) + node_list.append(node_pred_box_result) + + score_shape = [1, input_height * input_width * int(num_anchors), class_num] + name_score_shape = [model_name + "@score_shape"] + node_score_shape = onnx.helper.make_node( + "Constant", + inputs=[], + outputs=name_score_shape, + value=onnx.helper.make_tensor( + name=name_score_shape[0] + "@const", + data_type=onnx.TensorProto.INT64, + dims=[len(score_shape)], + vals=score_shape)) + node_list.append(node_score_shape) + + node_score_new_shape = onnx.helper.make_node( + 'Reshape', + inputs=outputs_score + name_score_shape, + outputs=outputs['Scores']) + node_list.append(node_score_new_shape) + return node_list diff --git a/x2paddle/op_mapper/paddle_op_mapper.py b/x2paddle/op_mapper/paddle_op_mapper.py index 6c2c97da433014773f56e633881cd0c4e8d2ee6e..373b89cb1e071117f8bcc539885cb61dfafc7ce4 100644 --- a/x2paddle/op_mapper/paddle_op_mapper.py +++ b/x2paddle/op_mapper/paddle_op_mapper.py @@ -21,6 +21,8 @@ import paddle.fluid.core as core import paddle.fluid as fluid import onnx from onnx import helper, onnx_pb +from .paddle_custom_layer.yolo_box import yolo_box +from .paddle_custom_layer.multiclass_nms import multiclass_nms class PaddleOpMapper(object): @@ -73,6 +75,19 @@ class PaddleOpMapper(object): pads=op.attr('paddings') + op.attr('paddings')) return node + def conv2d_transpose(self, op, block): + kernel_shape = block.var(op.input('Filter')[0]).shape + node = helper.make_node( + 'ConvTranspose', + inputs=op.input('Input') + op.input('Filter'), + outputs=op.output('Output'), + dilations=op.attr('dilations'), + kernel_shape=kernel_shape[-2:], + strides=op.attr('strides'), + group=1, + pads=op.attr('paddings') + op.attr('paddings')) + return node + def relu(self, op, block): node = helper.make_node( 'Relu', inputs=op.input('X'), outputs=op.output('Out')) @@ -83,6 +98,19 @@ class PaddleOpMapper(object): 'Sigmoid', inputs=op.input('X'), outputs=op.output('Out')) return node + def exp(self, op, block): + node = helper.make_node( + 'Exp', inputs=op.input('X'), outputs=op.output('Out')) + return node + + def leaky_relu(self, op, block): + node = helper.make_node( + 'LeakyRelu', + inputs=op.input('X'), + outputs=op.output('Out'), + alpha=op.attr('alpha')) + return node + def elementwise_add(self, op, block): axis = op.attr('axis') x_shape = block.var(op.input('X')[0]).shape @@ -112,6 +140,35 @@ class PaddleOpMapper(object): else: raise Excpetion("Unexpected situation happend in elementwise_add") + def elementwise_sub(self, op, block): + axis = op.attr('axis') + x_shape = block.var(op.input('X')[0]).shape + y_shape = block.var(op.input('Y')[0]).shape + if len(y_shape) == 1 and axis == 1: + shape_name = self.get_name(op.type, 'shape') + shape_value = [1] * len(x_shape) + shape_value[axis] = y_shape[0] + shape_node = self.make_constant_node( + shape_name, onnx_pb.TensorProto.INT64, shape_value) + temp_value = self.get_name(op.type, 'temp') + y_node = helper.make_node( + 'Reshape', + inputs=[op.input('Y')[0], shape_name], + outputs=[temp_value]) + node = helper.make_node( + 'Sub', + inputs=[op.input('X')[0], temp_value], + outputs=op.output('Out')) + return [shape_node, y_node, node] + elif len(x_shape) == len(y_shape): + node = helper.make_node( + 'Sub', + inputs=[op.input('X')[0], op.input('Y')[0]], + outputs=op.output('Out')) + return node + else: + raise Excpetion("Unexpected situation happend in elementwise_sub") + def pool2d(self, op, block): pool_type = { 'max': ('MaxPool', 'GlobalMaxPool'), @@ -412,10 +469,12 @@ class PaddleOpMapper(object): def bilinear_interp(self, op, block): input_names = op.input_names coordinate_transformation_mode = 'half_pixel' - shape_dtype = block.var(op.input('OutSize')[0]).dtype if op.attr('align_corners'): coordinate_transformation_mode = 'align_corners' - if 'OutSize' in input_names and len(op.input('OutSize')) > 0: + if ('OutSize' in input_names and len(op.input('OutSize')) > 0) or ( + 'SizeTensor' in input_names + and len(op.input('SizeTensor')) > 0): + node_list = list() roi_node = self.make_constant_node( self.get_name(op.type, 'roi'), onnx_pb.TensorProto.FLOAT, [1, 1, 1, 1, 1, 1, 1, 1]) @@ -444,16 +503,42 @@ class PaddleOpMapper(object): 'Slice', inputs=[shape_name0, starts_name, ends_name], outputs=[shape_name1]) - shape_name2 = self.get_name(op.type, "shape.cast") - shape_node2 = helper.make_node( - 'Cast', - inputs=op.input('OutSize'), - outputs=[shape_name2], - to=onnx_pb.TensorProto.INT64) + node_list.extend([ + roi_node, empty_node, shape_node0, starts_node, ends_node, + shape_node1 + ]) + # shape_name2 = self.get_name(op.type, "shape.cast") + # shape_node2 = helper.make_node( + # 'Cast', + # inputs=op.input('OutSize'), + # outputs=[shape_name2], + # to=onnx_pb.TensorProto.INT64) + if 'OutSize' in input_names and len(op.input('OutSize')) > 0: + cast_shape_name = self.get_name(op.type, "shape.cast") + cast_shape_node = helper.make_node( + 'Cast', + inputs=op.input('OutSize'), + outputs=[cast_shape_name], + to=onnx_pb.TensorProto.INT64) + node_list.append(cast_shape_node) + else: + concat_shape_name = self.get_name(op.type, "shape.concat") + concat_shape_node = helper.make_node( + "Concat", + inputs=op.input('SizeTensor'), + outputs=[concat_shape_name], + axis=0) + cast_shape_name = self.get_name(op.type, "shape.cast") + cast_shape_node = helper.make_node( + 'Cast', + inputs=[concat_shape_name], + outputs=[cast_shape_name], + to=onnx_pb.TensorProto.INT64) + node_list.extend([concat_shape_node, cast_shape_node]) shape_name3 = self.get_name(op.type, "shape.concat") shape_node3 = helper.make_node( 'Concat', - inputs=[shape_name1, shape_name2], + inputs=[shape_name1, cast_shape_name], outputs=[shape_name3], axis=0) result_node = helper.make_node( @@ -462,10 +547,8 @@ class PaddleOpMapper(object): outputs=op.output('Out'), mode='linear', coordinate_transformation_mode=coordinate_transformation_mode) - return [ - roi_node, empty_node, shape_node0, starts_node, ends_node, - shape_node1, shape_node2, shape_node3, result_node - ] + node_list.extend([shape_node3, result_node]) + return node_list elif 'Scale' in input_names and len(op.input('Scale')) > 0: node = helper.make_node( 'Resize', @@ -552,6 +635,41 @@ class PaddleOpMapper(object): beta=offset) return node + def hard_swish(self, op, block): + min_name = self.get_name(op.type, 'min') + max_name = self.get_name(op.type, 'max') + scale_name = self.get_name(op.type, 'scale') + offset_name = self.get_name(op.type, 'offset') + min_node = self.make_constant_node(min_name, onnx_pb.TensorProto.FLOAT, + 0) + max_node = self.make_constant_node(max_name, onnx_pb.TensorProto.FLOAT, + op.attr('threshold')) + scale_node = self.make_constant_node(scale_name, + onnx_pb.TensorProto.FLOAT, + op.attr('scale')) + offset_node = self.make_constant_node(offset_name, + onnx_pb.TensorProto.FLOAT, + op.attr('offset')) + + name0 = self.get_name(op.type, 'add') + node0 = helper.make_node( + 'Add', inputs=[op.input('X')[0], offset_name], outputs=[name0]) + name1 = self.get_name(op.type, 'relu') + node1 = helper.make_node( + 'Clip', + inputs=[name0, min_name, max_name], + outputs=[name1], + ) + name2 = self.get_name(op.type, 'mul') + node2 = helper.make_node( + 'Mul', inputs=[op.input('X')[0], name1], outputs=[name2]) + node3 = helper.make_node( + 'Div', inputs=[name2, scale_name], outputs=op.output('Out')) + return [ + min_node, max_node, scale_node, offset_node, node0, node1, node2, + node3 + ] + def elementwise_mul(self, op, block): axis = op.attr('axis') x_shape = block.var(op.input('X')[0]).shape @@ -617,6 +735,18 @@ class PaddleOpMapper(object): keepdims=0) return node + def yolo_box(self, op, block): + return yolo_box(op, block) + + def multiclass_nms(self, op, block): + return multiclass_nms(op, block) + + def reciprocal(self, op, block): + inputs = op.input(op.input_names[0]) + outputs = op.output(op.output_names[0]) + node = helper.make_node('Reciprocal', inputs=inputs, outputs=outputs) + return node + def convert_weights(self, program): var_names = program.global_block().vars nodes = list() @@ -651,6 +781,7 @@ class PaddleOpMapper(object): sys.stdout.write( "\rTotal:{}, Current:{} : {} ".format( len(block.ops), i + 1, op.type)) + sys.stdout.flush() if not hasattr(self, op.type): unsupported_ops.add(op.type) continue