diff --git a/testdata/cv/dnn_face/detection/cascades_labels.txt b/testdata/cv/dnn_face/detection/cascades_labels.txt index c687037af..dba3ca7aa 100644 --- a/testdata/cv/dnn_face/detection/cascades_labels.txt +++ b/testdata/cv/dnn_face/detection/cascades_labels.txt @@ -88,8 +88,9 @@ er.png 141 256 32 42 150 273 165 272 159 281 153 288 165 287 68 127 31 38 78 140 92 140 86 147 80 155 91 154 image_00000000_0.png -1 +2 317 160 14 16 321 166 327 167 324 169 322 172 326 172 +236 181 10 12 238 186 244 186 240 188 238 190 243 190 karen-and-rob.png 2 191 30 47 61 206 54 227 55 217 66 206 75 225 76 diff --git a/testdata/cv/qrcode/flipped/flipped_1.png b/testdata/cv/qrcode/flipped/flipped_1.png new file mode 100644 index 000000000..49a639eb5 Binary files /dev/null and b/testdata/cv/qrcode/flipped/flipped_1.png differ diff --git a/testdata/cv/qrcode/flipped/flipped_2.png b/testdata/cv/qrcode/flipped/flipped_2.png new file mode 100644 index 000000000..0c1752846 Binary files /dev/null and b/testdata/cv/qrcode/flipped/flipped_2.png differ diff --git a/testdata/cv/qrcode/issue_3478.png b/testdata/cv/qrcode/issue_3478.png new file mode 100644 index 000000000..9b21eeea7 Binary files /dev/null and b/testdata/cv/qrcode/issue_3478.png differ diff --git a/testdata/dnn/download_models.py b/testdata/dnn/download_models.py index 1e05bd2da..d82892d65 100755 --- a/testdata/dnn/download_models.py +++ b/testdata/dnn/download_models.py @@ -942,11 +942,6 @@ def get_confirm_token(response): # in case of large files url='https://drive.google.com/uc?export=dowload&id=19YWhArrNccaoSza0CfkXlA8im4-lAGsR', sha='1b4dd21a6baa5e3523156776970895bd3db6960a', filename='onnx/models/DB_TD500_resnet50.onnx'), - Model( - name='YuNet', - url='https://github.com/ShiqiYu/libfacedetection.train/raw/1688402dbd9b9fc4a3a6793810f558b7407ff384/tasks/task1/onnx/yunet_120x160.onnx', - sha='dfe691ae0c8e38d39d1a437e3f7e5fda7b256bdd', - filename='onnx/models/yunet-202202.onnx'), Model( name='face_recognizer_fast', url='https://drive.google.com/uc?export=dowload&id=1ClK9WiB492c5OZFKveF3XiHCejoOxINW', @@ -1020,6 +1015,47 @@ def get_confirm_token(response): # in case of large files url='https://raw.githubusercontent.com/zihaomu/opencv_extra_data_backup/main/NanoTrackV2/models/nanotrack_head_sim_v2.onnx', sha='39f168489671700cf739e402dfc67d41ce648aef', filename='onnx/models/nanotrack_head_sim_v2.onnx'), + Model( + name='Face Mesh (TFLite)', + url='https://storage.googleapis.com/mediapipe-assets/face_landmark.tflite?generation=1668295060280094', + sha='eb01d1d88c833aaea64c880506da72e4a4f43154', + filename='tflite/face_landmark.tflite'), + Model( + name='Face Detection (TFLite)', + url='https://storage.googleapis.com/mediapipe-assets/face_detection_short_range.tflite?generation=1661875748538815', + sha='e8f749fafc23bb88daac85bc9f7e0698436f29a0', + filename='tflite/face_detection_short_range.tflite'), + Model( + name='Selfie Segmentation (TFLite)', + url='https://storage.googleapis.com/mediapipe-assets/selfie_segmentation.tflite?generation=1661875931201364', + sha='8d497f51bd678fa5fb95c3871be72eb5d722b831', + filename='tflite/selfie_segmentation.tflite'), + Model( + name='Hair Segmentation (TFLite)', + url='https://storage.googleapis.com/mediapipe-assets/hair_segmentation.tflite?generation=1661875756623461', + sha='bba28400dfc264b1ed7ee95df718fada1879644d', + filename='tflite/hair_segmentation.tflite'), + Model( + name='YuNet', + url='https://github.com/ShiqiYu/libfacedetection.train/raw/02246e79b1e976c83d1e135a85e0628120c93769/onnx/yunet_s_640_640.onnx', + sha='acbe4b5976ade60c4b866a30d0720d71589c8bbc', + filename='onnx/models/yunet-202303.onnx'), + Model( + name='EfficientDet (TFLite)', + url='https://storage.googleapis.com/mediapipe-assets/coco_efficientdet_lite0_v1_1.0_quant_2021_09_06.tflite?generation=1661875692679200', + sha='200217d746d58e68028a64ad0472631060e6affb', + filename='tflite/coco_efficientdet_lite0_v1_1.0_quant_2021_09_06.tflite'), + Model( + name='PP_OCRv3_DB_text_det (ONNX)', + url='https://github.com/zihaomu/zihaomu/files/9740907/PP_OCRv3_DB_text_det.tar.gz', + sha='a2a008361d785fbe32a22ec2106621ecd1576f48', + filename='PP_OCRv3_DB_text_det.tar.gz'), + Model( + name='PP_OCRv3_DB_text_det (ONNX)', + archive='PP_OCRv3_DB_text_det.tar.gz', + member='PP_OCRv3_DB_text_det/PP_OCRv3_DB_text_det.onnx', + sha='f541f0b448561c7ad919ba9fffa72ff105062934', + filename='onnx/models/PP_OCRv3_DB_text_det.onnx'), ] # Note: models will be downloaded to current working directory diff --git a/testdata/dnn/onnx/data/input_clip-vit-base-head.npy b/testdata/dnn/onnx/data/input_clip-vit-base-head.npy new file mode 100644 index 000000000..8a97d825e Binary files /dev/null and b/testdata/dnn/onnx/data/input_clip-vit-base-head.npy differ diff --git a/testdata/dnn/onnx/data/input_conv3d_depthwise_bias.npy b/testdata/dnn/onnx/data/input_conv3d_depthwise_bias.npy new file mode 100644 index 000000000..eee015335 Binary files /dev/null and b/testdata/dnn/onnx/data/input_conv3d_depthwise_bias.npy differ diff --git a/testdata/dnn/onnx/data/input_gelu.npy b/testdata/dnn/onnx/data/input_gelu.npy new file mode 100644 index 000000000..8207c29f1 Binary files /dev/null and b/testdata/dnn/onnx/data/input_gelu.npy differ diff --git a/testdata/dnn/onnx/data/input_gelu_approximation.npy b/testdata/dnn/onnx/data/input_gelu_approximation.npy new file mode 100644 index 000000000..8207c29f1 Binary files /dev/null and b/testdata/dnn/onnx/data/input_gelu_approximation.npy differ diff --git a/testdata/dnn/onnx/data/input_gemm_vector_bias.npy b/testdata/dnn/onnx/data/input_gemm_vector_bias.npy new file mode 100644 index 000000000..e58467a84 Binary files /dev/null and b/testdata/dnn/onnx/data/input_gemm_vector_bias.npy differ diff --git a/testdata/dnn/onnx/data/input_gru_cell_batchsize_1_seqlen_50.npy b/testdata/dnn/onnx/data/input_gru_cell_batchsize_1_seqlen_50.npy new file mode 100644 index 000000000..8812b646e Binary files /dev/null and b/testdata/dnn/onnx/data/input_gru_cell_batchsize_1_seqlen_50.npy differ diff --git a/testdata/dnn/onnx/data/input_gru_cell_batchsize_50_seqlen_1.npy b/testdata/dnn/onnx/data/input_gru_cell_batchsize_50_seqlen_1.npy new file mode 100644 index 000000000..95fa77e55 Binary files /dev/null and b/testdata/dnn/onnx/data/input_gru_cell_batchsize_50_seqlen_1.npy differ diff --git a/testdata/dnn/onnx/data/input_gru_cell_batchsize_5_seqlen_5.npy b/testdata/dnn/onnx/data/input_gru_cell_batchsize_5_seqlen_5.npy new file mode 100644 index 000000000..ec103bfa0 Binary files /dev/null and b/testdata/dnn/onnx/data/input_gru_cell_batchsize_5_seqlen_5.npy differ diff --git a/testdata/dnn/onnx/data/input_lstm_cell_batchsize_1_seqlen_50.npy b/testdata/dnn/onnx/data/input_lstm_cell_batchsize_1_seqlen_50.npy new file mode 100644 index 000000000..806c97c06 Binary files /dev/null and b/testdata/dnn/onnx/data/input_lstm_cell_batchsize_1_seqlen_50.npy differ diff --git a/testdata/dnn/onnx/data/input_lstm_cell_batchsize_50_seqlen_1.npy b/testdata/dnn/onnx/data/input_lstm_cell_batchsize_50_seqlen_1.npy new file mode 100644 index 000000000..95fa77e55 Binary files /dev/null and b/testdata/dnn/onnx/data/input_lstm_cell_batchsize_50_seqlen_1.npy differ diff --git a/testdata/dnn/onnx/data/input_lstm_cell_batchsize_5_seqlen_5.npy b/testdata/dnn/onnx/data/input_lstm_cell_batchsize_5_seqlen_5.npy new file mode 100644 index 000000000..42b667838 Binary files /dev/null and b/testdata/dnn/onnx/data/input_lstm_cell_batchsize_5_seqlen_5.npy differ diff --git a/testdata/dnn/onnx/data/input_lstm_init_h0_c0_0.npy b/testdata/dnn/onnx/data/input_lstm_init_h0_c0_0.npy new file mode 100644 index 000000000..9a5664908 Binary files /dev/null and b/testdata/dnn/onnx/data/input_lstm_init_h0_c0_0.npy differ diff --git a/testdata/dnn/onnx/data/input_lstm_init_h0_c0_1.npy b/testdata/dnn/onnx/data/input_lstm_init_h0_c0_1.npy new file mode 100644 index 000000000..0374ce93d Binary files /dev/null and b/testdata/dnn/onnx/data/input_lstm_init_h0_c0_1.npy differ diff --git a/testdata/dnn/onnx/data/input_lstm_init_h0_c0_2.npy b/testdata/dnn/onnx/data/input_lstm_init_h0_c0_2.npy new file mode 100644 index 000000000..0a6f757f6 Binary files /dev/null and b/testdata/dnn/onnx/data/input_lstm_init_h0_c0_2.npy differ diff --git a/testdata/dnn/onnx/data/input_lstm_layout_0_0.npy b/testdata/dnn/onnx/data/input_lstm_layout_0_0.npy new file mode 100644 index 000000000..c8ec8b322 Binary files /dev/null and b/testdata/dnn/onnx/data/input_lstm_layout_0_0.npy differ diff --git a/testdata/dnn/onnx/data/input_lstm_layout_0_1.npy b/testdata/dnn/onnx/data/input_lstm_layout_0_1.npy new file mode 100644 index 000000000..e57ab41e0 Binary files /dev/null and b/testdata/dnn/onnx/data/input_lstm_layout_0_1.npy differ diff --git a/testdata/dnn/onnx/data/input_lstm_layout_0_2.npy b/testdata/dnn/onnx/data/input_lstm_layout_0_2.npy new file mode 100644 index 000000000..e57ab41e0 Binary files /dev/null and b/testdata/dnn/onnx/data/input_lstm_layout_0_2.npy differ diff --git a/testdata/dnn/onnx/data/input_lstm_layout_1_0.npy b/testdata/dnn/onnx/data/input_lstm_layout_1_0.npy new file mode 100644 index 000000000..8e35ae13d Binary files /dev/null and b/testdata/dnn/onnx/data/input_lstm_layout_1_0.npy differ diff --git a/testdata/dnn/onnx/data/input_lstm_layout_1_1.npy b/testdata/dnn/onnx/data/input_lstm_layout_1_1.npy new file mode 100644 index 000000000..e57ab41e0 Binary files /dev/null and b/testdata/dnn/onnx/data/input_lstm_layout_1_1.npy differ diff --git a/testdata/dnn/onnx/data/input_lstm_layout_1_2.npy b/testdata/dnn/onnx/data/input_lstm_layout_1_2.npy new file mode 100644 index 000000000..e57ab41e0 Binary files /dev/null and b/testdata/dnn/onnx/data/input_lstm_layout_1_2.npy differ diff --git a/testdata/dnn/onnx/data/input_qlinearsoftmax_v11.npy b/testdata/dnn/onnx/data/input_qlinearsoftmax_v11.npy new file mode 100644 index 000000000..0585506ba Binary files /dev/null and b/testdata/dnn/onnx/data/input_qlinearsoftmax_v11.npy differ diff --git a/testdata/dnn/onnx/data/input_qlinearsoftmax_v13.npy b/testdata/dnn/onnx/data/input_qlinearsoftmax_v13.npy new file mode 100644 index 000000000..0585506ba Binary files /dev/null and b/testdata/dnn/onnx/data/input_qlinearsoftmax_v13.npy differ diff --git a/testdata/dnn/onnx/data/input_split_5.npy b/testdata/dnn/onnx/data/input_split_5.npy new file mode 100644 index 000000000..6a9b2c92b Binary files /dev/null and b/testdata/dnn/onnx/data/input_split_5.npy differ diff --git a/testdata/dnn/onnx/data/input_split_6.npy b/testdata/dnn/onnx/data/input_split_6.npy new file mode 100644 index 000000000..6a9b2c92b Binary files /dev/null and b/testdata/dnn/onnx/data/input_split_6.npy differ diff --git a/testdata/dnn/onnx/data/input_where_layer.npy b/testdata/dnn/onnx/data/input_where_layer.npy new file mode 100644 index 000000000..ddf2fe692 Binary files /dev/null and b/testdata/dnn/onnx/data/input_where_layer.npy differ diff --git a/testdata/dnn/onnx/data/output_clip-vit-base-head.npy b/testdata/dnn/onnx/data/output_clip-vit-base-head.npy new file mode 100644 index 000000000..fa0ee8023 Binary files /dev/null and b/testdata/dnn/onnx/data/output_clip-vit-base-head.npy differ diff --git a/testdata/dnn/onnx/data/output_conv3d_depthwise_bias.npy b/testdata/dnn/onnx/data/output_conv3d_depthwise_bias.npy new file mode 100644 index 000000000..8a14b4f03 Binary files /dev/null and b/testdata/dnn/onnx/data/output_conv3d_depthwise_bias.npy differ diff --git a/testdata/dnn/onnx/data/output_gelu.npy b/testdata/dnn/onnx/data/output_gelu.npy new file mode 100644 index 000000000..6f94cabfb Binary files /dev/null and b/testdata/dnn/onnx/data/output_gelu.npy differ diff --git a/testdata/dnn/onnx/data/output_gelu_approximation.npy b/testdata/dnn/onnx/data/output_gelu_approximation.npy new file mode 100644 index 000000000..0cbcc4272 Binary files /dev/null and b/testdata/dnn/onnx/data/output_gelu_approximation.npy differ diff --git a/testdata/dnn/onnx/data/output_gemm_vector_bias.npy b/testdata/dnn/onnx/data/output_gemm_vector_bias.npy new file mode 100644 index 000000000..bcdb223ce Binary files /dev/null and b/testdata/dnn/onnx/data/output_gemm_vector_bias.npy differ diff --git a/testdata/dnn/onnx/data/output_gru_cell_batchsize_1_seqlen_50.npy b/testdata/dnn/onnx/data/output_gru_cell_batchsize_1_seqlen_50.npy new file mode 100644 index 000000000..127266a98 Binary files /dev/null and b/testdata/dnn/onnx/data/output_gru_cell_batchsize_1_seqlen_50.npy differ diff --git a/testdata/dnn/onnx/data/output_gru_cell_batchsize_50_seqlen_1.npy b/testdata/dnn/onnx/data/output_gru_cell_batchsize_50_seqlen_1.npy new file mode 100644 index 000000000..812e8dc5f Binary files /dev/null and b/testdata/dnn/onnx/data/output_gru_cell_batchsize_50_seqlen_1.npy differ diff --git a/testdata/dnn/onnx/data/output_gru_cell_batchsize_5_seqlen_5.npy b/testdata/dnn/onnx/data/output_gru_cell_batchsize_5_seqlen_5.npy new file mode 100644 index 000000000..157ab712c Binary files /dev/null and b/testdata/dnn/onnx/data/output_gru_cell_batchsize_5_seqlen_5.npy differ diff --git a/testdata/dnn/onnx/data/output_lstm_cell_batchsize_1_seqlen_50.npy b/testdata/dnn/onnx/data/output_lstm_cell_batchsize_1_seqlen_50.npy new file mode 100644 index 000000000..596f08d7e Binary files /dev/null and b/testdata/dnn/onnx/data/output_lstm_cell_batchsize_1_seqlen_50.npy differ diff --git a/testdata/dnn/onnx/data/output_lstm_cell_batchsize_50_seqlen_1.npy b/testdata/dnn/onnx/data/output_lstm_cell_batchsize_50_seqlen_1.npy new file mode 100644 index 000000000..812e8dc5f Binary files /dev/null and b/testdata/dnn/onnx/data/output_lstm_cell_batchsize_50_seqlen_1.npy differ diff --git a/testdata/dnn/onnx/data/output_lstm_cell_batchsize_5_seqlen_5.npy b/testdata/dnn/onnx/data/output_lstm_cell_batchsize_5_seqlen_5.npy new file mode 100644 index 000000000..e46ceebf1 Binary files /dev/null and b/testdata/dnn/onnx/data/output_lstm_cell_batchsize_5_seqlen_5.npy differ diff --git a/testdata/dnn/onnx/data/output_lstm_init_h0_c0.npy b/testdata/dnn/onnx/data/output_lstm_init_h0_c0.npy new file mode 100644 index 000000000..6ff51f60b Binary files /dev/null and b/testdata/dnn/onnx/data/output_lstm_init_h0_c0.npy differ diff --git a/testdata/dnn/onnx/data/output_lstm_layout_0.npy b/testdata/dnn/onnx/data/output_lstm_layout_0.npy new file mode 100644 index 000000000..e57ab41e0 Binary files /dev/null and b/testdata/dnn/onnx/data/output_lstm_layout_0.npy differ diff --git a/testdata/dnn/onnx/data/output_lstm_layout_1.npy b/testdata/dnn/onnx/data/output_lstm_layout_1.npy new file mode 100644 index 000000000..e57ab41e0 Binary files /dev/null and b/testdata/dnn/onnx/data/output_lstm_layout_1.npy differ diff --git a/testdata/dnn/onnx/data/output_qlinearsoftmax_v11.npy b/testdata/dnn/onnx/data/output_qlinearsoftmax_v11.npy new file mode 100644 index 000000000..d5c203314 Binary files /dev/null and b/testdata/dnn/onnx/data/output_qlinearsoftmax_v11.npy differ diff --git a/testdata/dnn/onnx/data/output_qlinearsoftmax_v13.npy b/testdata/dnn/onnx/data/output_qlinearsoftmax_v13.npy new file mode 100644 index 000000000..e36e64d79 Binary files /dev/null and b/testdata/dnn/onnx/data/output_qlinearsoftmax_v13.npy differ diff --git a/testdata/dnn/onnx/data/output_split_5.npy b/testdata/dnn/onnx/data/output_split_5.npy new file mode 100644 index 000000000..6a9b2c92b Binary files /dev/null and b/testdata/dnn/onnx/data/output_split_5.npy differ diff --git a/testdata/dnn/onnx/data/output_split_6.npy b/testdata/dnn/onnx/data/output_split_6.npy new file mode 100644 index 000000000..6a9b2c92b Binary files /dev/null and b/testdata/dnn/onnx/data/output_split_6.npy differ diff --git a/testdata/dnn/onnx/data/output_where_layer.npy b/testdata/dnn/onnx/data/output_where_layer.npy new file mode 100644 index 000000000..4253f5c6b Binary files /dev/null and b/testdata/dnn/onnx/data/output_where_layer.npy differ diff --git a/testdata/dnn/onnx/generate_onnx_models.py b/testdata/dnn/onnx/generate_onnx_models.py index 534369f84..bec86026f 100644 --- a/testdata/dnn/onnx/generate_onnx_models.py +++ b/testdata/dnn/onnx/generate_onnx_models.py @@ -13,7 +13,8 @@ import onnxsim import google.protobuf.text_format import io -from typing import Optional +from typing import Optional, Tuple, Any +from onnx import TensorProto def assertExpected(s): if not (isinstance(s, str) or (sys.version_info[0] == 2 and isinstance(s, unicode))): @@ -421,6 +422,10 @@ def forward(self, x): conv3d = nn.Conv3d(2, 3, (2, 3, 3), stride=(1, 2, 3), padding=(0, 1, 2), groups=1, dilation=(1, 2, 3), bias=True) save_data_and_model("conv3d_bias", input, conv3d) +input = Variable(torch.randn(1, 8, 1, 10, 10)) +conv3d = nn.Conv3d(8, 8, (1, 1, 1), stride=(1, 1, 1), padding=(1, 1, 1), groups=8, dilation=(1, 1, 1), bias=True) +save_data_and_model("conv3d_depthwise_bias", input, conv3d, export_params=True) + input = torch.randn(1, 2, 3, 4, 6) maxpool3d = nn.MaxPool3d((3, 2, 5), stride=(2, 1, 2), padding=(1, 0, 2)) save_data_and_model("max_pool3d", input, maxpool3d) @@ -520,6 +525,37 @@ def generate_slice_neg_starts(): generate_slice_neg_starts() +def postprocess_model(model_path, inputs_shapes): + onnx_model = onnx.load(model_path) + + def update_inputs_dims(model, input_dims): + """ + This function updates the sizes of dimensions of the model's inputs to the values + provided in input_dims. if the dim value provided is negative, a unique dim_param + will be set for that dimension. + """ + def update_dim(tensor, dim, i, j, dim_param_prefix): + dim_proto = tensor.type.tensor_type.shape.dim[j] + if isinstance(dim, int): + if dim >= 0: + dim_proto.dim_value = dim + else: + dim_proto.dim_param = dim_param_prefix + str(i) + '_' + str(j) + elif isinstance(dim, str): + dim_proto.dim_param = dim + else: + raise ValueError('Only int or str is accepted as dimension value, incorrect type: {}'.format(type(dim))) + + for i, input_dim_arr in enumerate(input_dims): + for j, dim in enumerate(input_dim_arr): + update_dim(model.graph.input[i], dim, i, j, 'in_') + + onnx.checker.check_model(model) + return model + + onnx_model = update_inputs_dims(onnx_model, inputs_shapes) + onnx.save(onnx_model, model_path) + input_2 = Variable(torch.randn(6, 6)) custom_slice_list = [ slice(1, 3, 1), @@ -845,6 +881,13 @@ def forward(self, x): model = Split(dim=0, split_size_sections=[1, 1]) save_data_and_model("split_4", input, model) +input2 = Variable(torch.tensor([1., 2., 3.], dtype=torch.float32)) +model = Split(dim=0, split_size_sections=[1, 2]) +save_data_and_model("split_5", input2, model, version=13) + +model = Split(dim=-1, split_size_sections=[1, 2]) +save_data_and_model("split_6", input2, model, version=13) + class SplitSizes(nn.Module): def __init__(self, *args, **kwargs): super(SplitSizes, self).__init__() @@ -1103,7 +1146,33 @@ def forward(self, x): lstm = LSTM(features, hidden, batch, bidirectional=True) save_data_and_model("lstm_bidirectional", input, lstm) +class LSTM_hidden_state_inputs(nn.Module): + + def __init__(self, features, hidden, batch, num_layers=1, bidirectional=False): + super(LSTM_hidden_state_inputs, self).__init__() + self.lstm = nn.LSTM(features, hidden, num_layers, bidirectional=bidirectional) + + def forward(self, x, h, c): + return self.lstm(x, (h, c))[0] +batch = 1 +features = 16 +hidden = 8 +seq_len = 2 +num_layers = 1 +bidirectional = False + +lstm = LSTM_hidden_state_inputs( + features, + hidden, + batch, + num_layers=num_layers, + bidirectional=bidirectional +) +input = torch.randn(seq_len, batch, features) +h0 = torch.randn(num_layers + int(bidirectional), batch, hidden) +c0 = torch.randn(num_layers + int(bidirectional), batch, hidden) +save_data_and_model_multy_inputs("lstm_init_h0_c0", lstm, input, h0, c0, export_params=True) class HiddenLSTM(nn.Module): def __init__(self, input_size, hidden_size, num_layers=1, is_bidirectional=False): @@ -1162,7 +1231,7 @@ def forward(self, t): class LSTM(nn.Module): - def __init__(self): + def __init__(self, features, hidden, batch, num_layers, bidirectional): super(LSTM, self).__init__() self.lstm = nn.LSTM(features, hidden, num_layers, bidirectional=bidirectional) self.h0 = torch.from_numpy(np.ones((num_layers + int(bidirectional), batch, hidden), dtype=np.float32)) @@ -1177,15 +1246,281 @@ def forward(self, x): input_ = Variable(torch.randn(seq_len, batch, features)) -lstm = LSTM() +lstm = LSTM(features, hidden, batch, num_layers, bidirectional) save_data_and_model("lstm_cell_bidirectional", input_, lstm, export_params=True) bidirectional = False input_ = Variable(torch.randn(seq_len, batch, features)) -lstm = LSTM() +lstm = LSTM(features, hidden, batch, num_layers, bidirectional) save_data_and_model("lstm_cell_forward", input_, lstm, export_params=True) +## Test for various sequence lengths and batch sizes +tup_bs_sl = [(1, 50), (50, 1), (5, 5)] +features = 4 +hidden = 3 +num_layers = 1 +bidirectional = False + +for sl, bs in tup_bs_sl: + input_ = Variable(torch.randn(sl, bs, features)) + lstm = LSTM(features, hidden, bs, num_layers, bidirectional) + gru = GRU(features, hidden, num_layers, bidirectional) + save_data_and_model(f"lstm_cell_batchsize_{bs}_seqlen_{sl}", input_, lstm, export_params=True) + save_data_and_model(f"gru_cell_batchsize_{bs}_seqlen_{sl}", input_, lstm, export_params=True) + +class LayoutLSTM: + def __init__(self, **params: Any) -> None: + # LSTM Input Names + X = "X" + W = "W" + R = "R" + B = "B" + H_0 = "initial_h" + C_0 = "initial_c" + P = "P" + LAYOUT = "layout" + + number_of_gates = 4 + number_of_peepholes = 3 + weight_scale = 1 + + + hidden_size = params["hidden_size"] + input_size = params["input_size"] + layout = params[LAYOUT] if LAYOUT in params else 0 + + batch_size = params[X].shape[0] if layout else params[X].shape[1] + + # Initializing Inputs + params[W] = weight_scale * np.ones( + (1, number_of_gates * hidden_size, input_size) + ).astype(np.float32) + params[R] = weight_scale * np.ones( + (1, number_of_gates * hidden_size, hidden_size) + ).astype(np.float32) + + params[B] = np.ones((1, 2 * number_of_gates * hidden_size)).astype(np.float32) + + if H_0 not in params and C_0 not in params: + params[H_0] = np.ones((1, batch_size, hidden_size)).astype(np.float32) + params[C_0] = np.ones((1, batch_size, hidden_size)).astype(np.float32) + + params[P] = weight_scale * np.ones((1, number_of_peepholes * hidden_size)).astype( + np.float32) + + self.num_directions = params[W].shape[0] + + if self.num_directions == 1: + + x = params[X] + x = x if layout == 0 else np.swapaxes(x, 0, 1) + + + b = ( + params[B] + if B in params + else np.ones(1, 2 * number_of_gates * hidden_size, dtype=np.float32) + ) + p = ( + params[P] + if P in params + else np.ones(1, number_of_peepholes * hidden_size, dtype=np.float32) + ) + h_0 = ( + params[H_0] + if H_0 in params + else np.ones((1, batch_size, hidden_size), dtype=np.float32) + ) + c_0 = ( + params[C_0] + if C_0 in params + else np.ones((1, batch_size, hidden_size), dtype=np.float32) + ) + + self.X = x + self.W = params[W] + self.R = params[R] + self.B = params[B] + self.P = params[P] + self.H_0 = params[H_0] + self.C_0 = params[C_0] + self.LAYOUT = layout + else: + raise NotImplementedError() + + def f(self, x: np.ndarray) -> np.ndarray: + return 1 / (1 + np.exp(-x)) + + def g(self, x: np.ndarray) -> np.ndarray: + return np.tanh(x) + + def h(self, x: np.ndarray) -> np.ndarray: + return np.tanh(x) + + def step(self) -> Tuple[np.ndarray, np.ndarray]: + + self.W = np.squeeze(self.W, axis=0) + self.R = np.squeeze(self.R, axis=0) + self.B = np.squeeze(self.B, axis=0) + self.P = np.squeeze(self.P, axis=0) + self.H_0 = np.squeeze(self.H_0, axis=0) + self.C_0 = np.squeeze(self.C_0, axis=0) + + seq_length = self.X.shape[0] + hidden_size = self.H_0.shape[-1] + batch_size = self.X.shape[1] + + Y = np.empty([seq_length, self.num_directions, batch_size, hidden_size]) + h_list = [] + + [p_i, p_o, p_f] = np.split(self.P, 3) + H_t = self.H_0 + C_t = self.C_0 + for x in np.split(self.X, self.X.shape[0], axis=0): + gates = ( + np.dot(x, np.transpose(self.W)) + + np.dot(H_t, np.transpose(self.R)) + + np.add(*np.split(self.B, 2)) + ) + i, o, f, c = np.split(gates, 4, -1) + i = self.f(i + p_i * C_t) + f = self.f(f + p_f * C_t) + c = self.g(c) + C = f * C_t + i * c + o = self.f(o + p_o * C) + H = o * self.h(C) + h_list.append(H) + H_t = H + C_t = C + + concatenated = np.concatenate(h_list) + if self.num_directions == 1: + Y[:, 0, :, :] = concatenated + + if self.LAYOUT == 0: + Y_h = Y[-1] + else: + Y_h = Y[-1, :, :, :] + Y = np.transpose(Y, [2, 0, 1, 3]) + + Y = np.squeeze(Y) + return Y, Y_h + +def _extract_value_info(x, name, type_proto=None): # type: (Union[List[Any], np.ndarray, None], Text, Optional[TypeProto]) -> onnx.ValueInfoProto + if type_proto is None: + if x is None: + raise NotImplementedError("_extract_value_info: both input and type_proto arguments cannot be None.") + elif isinstance(x, list): + elem_type = onnx.mapping.NP_TYPE_TO_TENSOR_TYPE[x[0].dtype] + shape = None + tensor_type_proto = onnx.helper.make_tensor_type_proto(elem_type, shape) + type_proto = onnx.helper.make_sequence_type_proto(tensor_type_proto) + else: + elem_type = onnx.mapping.NP_TYPE_TO_TENSOR_TYPE[x.dtype] + shape = x.shape + type_proto = onnx.helper.make_tensor_type_proto(elem_type, shape) + return onnx.helper.make_value_info(name, type_proto) + +def save_model_and_data_lstm_layout(lstm, layout, x, hx, cx, basename): + + W = onnx.helper.make_tensor( + name="W", + data_type = TensorProto.FLOAT, + dims = lstm.W.shape, + vals = lstm.W.flatten() + ) + + B = onnx.helper.make_tensor( + name="B", + data_type = TensorProto.FLOAT, + dims = lstm.B.shape, + vals = lstm.B.flatten() + ) + + R = onnx.helper.make_tensor( + name="R", + data_type = TensorProto.FLOAT, + dims = lstm.R.shape, + vals = lstm.R.flatten() + ) + + lstm_node = onnx.helper.make_node( + "LSTM", + inputs=["x", "W", "R", "B", "", "hx", "cx"], + outputs=["y", "y_h"], + name = "LSTM", + layout=layout, + hidden_size=hidden_size, + ) + + Y, Y_h = lstm.step() + + inputs = [x, hx, cx] + outputs = [Y, Y_h] + present_inputs = ['x', 'hx', 'cx'] + present_outputs = ['y', 'y_h'] + + input_type_protos = [None] * len(inputs) + output_type_protos = [None] * len(outputs) + + inputs_vi = [_extract_value_info(arr, arr_name, input_type) + for arr, arr_name, input_type in zip(inputs, present_inputs, input_type_protos)] + outputs_vi = [_extract_value_info(arr, arr_name, output_type) + for arr, arr_name, output_type in zip(outputs, present_outputs, output_type_protos)] + + # Create the graph + lstm_graph = onnx.helper.make_graph( + [lstm_node], + "layout_lstm", + inputs=inputs_vi, + outputs=outputs_vi, + initializer=[W, R, B] + ) + + m = onnx.helper.make_model(lstm_graph, producer_name="backend-test") + model_file = os.path.join("models", basename + ".onnx") + onnx.save(m, model_file) + onnx.checker.check_model(m) + + for i, data in enumerate(inputs): + input_files = os.path.join("data", "input_" + basename + f"_{str(i)}.npy") + data = data.astype(np.float32) + np.save(input_files, np.ascontiguousarray(data.data)) + + output_file = os.path.join("data", "output_" + basename + ".npy") + Y_h = data.astype(np.float32) + np.save(output_file, np.ascontiguousarray(Y_h.data)) + + + +## Generate data and model for testing LSTM Layout attribute +input_size = 3 +hidden_size = 7 +batch_size = 5 +seq_length = 2 + +hx = np.ones((1, batch_size, hidden_size)).astype(np.float32) +cx = np.ones((1, batch_size, hidden_size)).astype(np.float32) + +for layout in [0, 1]: + if layout: + x = np.ones((batch_size, seq_length, input_size)).astype(np.float32) + else: + x = np.ones((seq_length, batch_size, input_size)).astype(np.float32) + + lstm = LayoutLSTM( + X=x, + initial_h=hx, + initial_c=cx, + layout=layout, + hidden_size=hidden_size, + input_size=input_size + ) + + save_model_and_data_lstm_layout(lstm, layout, x, hx, cx, f"lstm_layout_{str(layout)}") + + class MatMul(nn.Module): def __init__(self): super(MatMul, self).__init__() @@ -1891,36 +2226,6 @@ def forward(self, x): model = GatherMultiOutput() save_data_and_model("gather_multi_output", x, model) -def postprocess_model(model_path, inputs_shapes): - onnx_model = onnx.load(model_path) - - def update_inputs_dims(model, input_dims): - """ - This function updates the sizes of dimensions of the model's inputs to the values - provided in input_dims. if the dim value provided is negative, a unique dim_param - will be set for that dimension. - """ - def update_dim(tensor, dim, i, j, dim_param_prefix): - dim_proto = tensor.type.tensor_type.shape.dim[j] - if isinstance(dim, int): - if dim >= 0: - dim_proto.dim_value = dim - else: - dim_proto.dim_param = dim_param_prefix + str(i) + '_' + str(j) - elif isinstance(dim, str): - dim_proto.dim_param = dim - else: - raise ValueError('Only int or str is accepted as dimension value, incorrect type: {}'.format(type(dim))) - - for i, input_dim_arr in enumerate(input_dims): - for j, dim in enumerate(input_dim_arr): - update_dim(model.graph.input[i], dim, i, j, 'in_') - - onnx.checker.check_model(model) - return model - - onnx_model = update_inputs_dims(onnx_model, inputs_shapes) - onnx.save(onnx_model, model_path) class UnsqueezeAndConv(nn.Module): def __init__(self): @@ -2112,6 +2417,21 @@ def forward(self, x): x = torch.randn(2, 3, 4) save_data_and_model("cumsum_3d_dim_2", x, CumSum(dim=2), version=11) +# where layer +class Where(nn.Module): + def __init__(self, *args, **kwargs): + super(Where, self).__init__() + + def forward(self, x): + a = torch.ones((6,6)) + b = torch.zeros((2, 6, 6)) + + return torch.where(x > 0, a, b) + +input = Variable(torch.randn(1, 2, 6, 6)) +model = Where(input) +save_data_and_model("where_layer", input, model, 13) + # tf2onnx models def save_data_and_tf_function(tf_function, name, input): input = input.astype(np.float32) @@ -2336,6 +2656,31 @@ def gemm_reference_implementation(A: np.ndarray, B: np.ndarray, C: Optional[np.n output_np = gemm_reference_implementation(weight_np.T, input_np.T) save_data_and_model("gemm_first_const", input_np, output_np, gemm_model) +## gemm with bias +def generate_gemm_bias(name, inputA, inputB, inputC): + outputY = gemm_reference_implementation(inputA, inputB, inputC) + + A = onnx.helper.make_tensor_value_info("A", onnx.TensorProto.FLOAT, inputA.shape) + B = onnx.helper.make_tensor_value_info("B", onnx.TensorProto.FLOAT, inputB.shape) + C = onnx.helper.make_tensor_value_info("C", onnx.TensorProto.FLOAT, inputC.shape) + B_INIT = onnx.helper.make_tensor("B", onnx.TensorProto.FLOAT, inputB.shape, inputB) + C_INIT = onnx.helper.make_tensor("C", onnx.TensorProto.FLOAT, inputC.shape, inputC) + Y = onnx.helper.make_tensor_value_info("Y", onnx.TensorProto.FLOAT, outputY.shape) + node = onnx.helper.make_node("Gemm", inputs=["A", "B", "C"], outputs=["Y"]) + graph = onnx.helper.make_graph([node], name, [A, B, C], [Y], [B_INIT, C_INIT]) + model = onnx.helper.make_model(graph, producer_name=name) + onnx.save(model, os.path.join("models", name + ".onnx")) + + input_files = os.path.join("data", "input_" + name) + np.save(input_files, inputA.data) + output_files = os.path.join("data", "output_" + name) + np.save(output_files, np.ascontiguousarray(outputY.data)) + +inputA = np.random.ranf([3, 6]).astype(np.float32) +inputB = np.random.ranf([6, 4]).astype(np.float32) +inputC = np.random.ranf([1, 4]).astype(np.float32) +generate_gemm_bias("gemm_vector_bias", inputA, inputB, inputC) + # ########################## ReduceSum with Dynamic Batch ########################## input_np = np.random.rand(2, 4, 4, 4).astype("float32") inputs = [onnx.helper.make_tensor_value_info("input1", onnx.mapping.NP_TYPE_TO_TENSOR_TYPE[input_np.dtype], shape=('?', 4, 4, 4))] @@ -2492,7 +2837,7 @@ def get_name(self, op_type): self.name_dict[op_type] += 1 else: self.name_dict[op_type] = 0 - + return "{}.{}".format(op_type, self.name_dict[op_type]) node_name_manager = NodeNameManager() @@ -2573,3 +2918,51 @@ def make_node_with_constant(op_type, constant_value, inputs=None, outputs=None, gen_layer_norm_expanded() gen_layer_norm_expanded(constant_as_initializers=True) + +################# GELU ################# + +x = torch.randn(1, 5, 20) +gelu = nn.GELU() +save_data_and_model("gelu", x, gelu) + +gelu_approximation = nn.GELU('tanh') +save_data_and_model("gelu_approximation", x, gelu_approximation) + +# Test data for a part of model: https://huggingface.co/openai/clip-vit-base-patch32 +input = np.random.standard_normal((1, 1, 3)).astype(np.float32) +embedding = np.array([4, 5, 6], dtype=np.float32) +data = np.random.standard_normal((2, 3)).astype(np.float32) +indices = np.array([[0, 1]], dtype=np.int64) + +output = np.concatenate((embedding.reshape(1, 1, 3), input), axis=1) + np.take(data, indices, axis=0) + +embedding = onnx.numpy_helper.from_array(embedding, name='embedding') +X = onnx.helper.make_tensor_value_info('input', onnx.TensorProto.FLOAT, input.shape) +Y = onnx.helper.make_tensor_value_info('output', onnx.TensorProto.FLOAT, output.shape) + +shape = np.array([1, 1, -1], dtype=np.int32) +shape = onnx.numpy_helper.from_array(shape, name='shape') +expand = onnx.helper.make_node("Expand", inputs=['embedding', 'shape'], outputs=['expand']) + +one = np.array([1, 1, 1], dtype=np.float32) +one = onnx.numpy_helper.from_array(one, name='one') +mul = onnx.helper.make_node("Mul", inputs=['input', 'one'], outputs=['input_mul']) + +concat = onnx.helper.make_node("Concat", inputs=['expand', 'input_mul'], outputs=['concat'], axis=1) + +data = onnx.numpy_helper.from_array(data, name='data') +indices = onnx.numpy_helper.from_array(indices, name='indices') + +gather = onnx.helper.make_node("Gather", inputs=['data', 'indices'], outputs=['gather']) +add = onnx.helper.make_node("Add", inputs=['concat', 'gather'], outputs=['output']) + +name = "clip-vit-base-head" +graph = onnx.helper.make_graph([mul, expand, concat, gather, add], name, [X], [Y], [embedding, data, indices, shape, one]) + +model = onnx.helper.make_model(graph, producer_name=name) +onnx.save(model, os.path.join("models", name + ".onnx")) + +input_files = os.path.join("data", "input_" + name) +np.save(input_files, input.data) +output_files = os.path.join("data", "output_" + name) +np.save(output_files, np.ascontiguousarray(output.data)) diff --git a/testdata/dnn/onnx/generate_quantized_onnx_models.py b/testdata/dnn/onnx/generate_quantized_onnx_models.py index 6d812b883..a4b265280 100644 --- a/testdata/dnn/onnx/generate_quantized_onnx_models.py +++ b/testdata/dnn/onnx/generate_quantized_onnx_models.py @@ -33,8 +33,8 @@ def quantize_and_save_model(name, input, model, act_type="uint8", wt_type="uint8 activation_type=type_dict[act_type], weight_type=type_dict[wt_type]) os.remove(float_model_path) - os.remove(os.path.join("models", "dummy-opt.onnx")) - os.remove("augmented_model.onnx") + # os.remove(os.path.join("models", "dummy-opt.onnx")) + # os.remove("augmented_model.onnx") sess = rt.InferenceSession(quantized_model_path, None) input = np.random.uniform(-1, 1, sess.get_inputs()[0].shape).astype("float32") @@ -284,4 +284,148 @@ def forward(self, x): input = Variable(torch.randn(1, 3)) model = Gemm() -quantize_and_save_model("quantized_gemm", input, model, act_type="int8", wt_type="int8", per_channel=False) \ No newline at end of file +quantize_and_save_model("quantized_gemm", input, model, act_type="int8", wt_type="int8", per_channel=False) + +shape = [1, 10, 3] +axis = 1 +name = "qlinearsoftmax_v13" +input = torch.rand(shape) +model = nn.Softmax(dim=axis) +# NOTE: this needs latest pytorch to have opset>= 13 +quantize_and_save_model(name, input, model, act_type="int8", wt_type="int8", per_channel=False) + +def generate_qlinearsoftmax(shape=[1, 10, 3], axis=1, opset=11, name="qlinearsoftmax", previous_name="qlinearsoftmax_v13"): + from onnx import helper, TensorProto + + # get scales and zero points + previous_model = onnx.load("models/{}.onnx".format(previous_name)) + previous_model_graph = previous_model.graph + previous_model_nodes = previous_model_graph.node + scales = [] + zero_points = [] + def get_val_from_initializers(initializers, name): + for init in initializers: + if init.name == name: + if init.int32_data: + return init.int32_data[0] + elif init.float_data: + return init.float_data[0] + else: + raise NotImplementedError() + scales.append(get_val_from_initializers(previous_model_graph.initializer, previous_model_nodes[1].input[1])) + zero_points.append(get_val_from_initializers(previous_model_graph.initializer, previous_model_nodes[1].input[2])) + scales.append(get_val_from_initializers(previous_model_graph.initializer, previous_model_nodes[1].input[3])) + zero_points.append(get_val_from_initializers(previous_model_graph.initializer, previous_model_nodes[1].input[4])) + + + def make_initializers(input_output_names, scales, zero_points): + names = [ + input_output_names[0] + "_scale", + input_output_names[0] + "_zero_point", + input_output_names[1] + "_scale", + input_output_names[1] + "_zero_point", + ] + + initializers = [] + initializers.append(helper.make_tensor(names[0], TensorProto.FLOAT, [], np.array([scales[0]], dtype=np.float32))) + initializers.append(helper.make_tensor(names[1], TensorProto.INT8, [], np.array([zero_points[0]], dtype=np.int8))) + initializers.append(helper.make_tensor(names[2], TensorProto.FLOAT, [], np.array([scales[1]], dtype=np.float32))) + initializers.append(helper.make_tensor(names[3], TensorProto.INT8, [], np.array([zero_points[1]], dtype=np.int8))) + + return initializers + + def make_quantize_dequantize(input_name, output_name, shape, dequantize=False): + input_names = [ + input_name, + input_name.split('_')[0] + "_scale", + input_name.split('_')[0] + "_zero_point", + ] + output_names = [ + output_name + ] + + inputs = [] + if dequantize: + inputs.append(helper.make_tensor_value_info(input_names[0], TensorProto.INT8, shape)) + else: + inputs.append(helper.make_tensor_value_info(input_names[0], TensorProto.FLOAT, shape)) + inputs.append(helper.make_tensor_value_info(input_names[1], TensorProto.FLOAT, [])) + inputs.append(helper.make_tensor_value_info(input_names[2], TensorProto.INT8, [])) + + outputs = [] + if dequantize: + outputs.append(helper.make_tensor_value_info(output_names[0], TensorProto.FLOAT, shape)) + else: + outputs.append(helper.make_empty_tensor_value_info(output_names[0])) + + node_type = "DequantizeLinear" if dequantize else "QuantizeLinear" + node = helper.make_node(node_type, input_names, output_names) + + return node, inputs[0], outputs[0] + + def make_qlinearsoftmax(input_name, output_name, axis, opset): + input_names = [ + input_name, + input_name.split('_')[0] + "_scale", + input_name.split('_')[0] + "_zero_point", + output_name.split('_')[0] + "_scale", + output_name.split('_')[0] + "_zero_point", + ] + output_names = [ + output_name + ] + + inputs = [] + inputs.append(helper.make_empty_tensor_value_info(input_names[0])) + inputs.append(helper.make_tensor_value_info(input_names[1], TensorProto.FLOAT, [])) + inputs.append(helper.make_tensor_value_info(input_names[2], TensorProto.INT8, [])) + inputs.append(helper.make_tensor_value_info(input_names[3], TensorProto.FLOAT, [])) + inputs.append(helper.make_tensor_value_info(input_names[4], TensorProto.INT8, [])) + + outputs = [] + outputs.append(helper.make_empty_tensor_value_info(output_names[0])) + + node = helper.make_node("QLinearSoftmax", input_names, output_names, domain="com.microsoft", axis=axis, opset=opset) + + return node, inputs[0], outputs[0] + + input_names = ["input", "input_quantized", "output_quantized"] + output_names = ["input_quantized", "output_quantized", "output"] + + shared_initializers = make_initializers([input_names[0], output_names[-1]], scales, zero_points) + node_quantize, graph_input, _ = make_quantize_dequantize(input_names[0], output_names[0], shape) + node_qsoftmax, _, _ = make_qlinearsoftmax(input_names[1], output_names[1], axis, opset) + node_dequantize, _, graph_output = make_quantize_dequantize(input_names[2], output_names[2], shape, dequantize=True) + + # create graph + name = "{}_v{}".format(name, opset) + graph = helper.make_graph( + [node_quantize, node_qsoftmax, node_dequantize], + name, + [graph_input], + [graph_output], + shared_initializers, + ) + + # create model + model = helper.make_model(graph, producer_name="github.com/opencv/opencv_extra") + model.opset_import.extend([helper.make_opsetid("com.microsoft", 1)]) + # ignore model check to create non-standard operators + model_path = "models/{}.onnx".format(name) + onnx.save(model, model_path) + print("model is saved to {}".format(model_path)) + + sess = rt.InferenceSession(model_path) + # input = np.random.uniform(-1, 1, sess.get_inputs()[0].shape).astype("float32") + input = np.load("data/input_{}.npy".format(previous_name)).astype(np.float32) + output = sess.run([sess.get_outputs()[0].name], {sess.get_inputs()[0].name : input})[0] + + print(name + " input has sizes", input.shape) + input_files = os.path.join("data", "input_" + name) + np.save(input_files, input.data) + + print(name + " output has sizes", output.shape) + output_files = os.path.join("data", "output_" + name) + np.save(output_files, np.ascontiguousarray(output.data)) + +generate_qlinearsoftmax(shape, axis, name="qlinearsoftmax", previous_name=name) diff --git a/testdata/dnn/onnx/models/clip-vit-base-head.onnx b/testdata/dnn/onnx/models/clip-vit-base-head.onnx new file mode 100644 index 000000000..bf82f52ae Binary files /dev/null and b/testdata/dnn/onnx/models/clip-vit-base-head.onnx differ diff --git a/testdata/dnn/onnx/models/conv3d_depthwise_bias.onnx b/testdata/dnn/onnx/models/conv3d_depthwise_bias.onnx new file mode 100644 index 000000000..b64f3dc6d Binary files /dev/null and b/testdata/dnn/onnx/models/conv3d_depthwise_bias.onnx differ diff --git a/testdata/dnn/onnx/models/gelu.onnx b/testdata/dnn/onnx/models/gelu.onnx new file mode 100644 index 000000000..7f4966619 Binary files /dev/null and b/testdata/dnn/onnx/models/gelu.onnx differ diff --git a/testdata/dnn/onnx/models/gelu_approximation.onnx b/testdata/dnn/onnx/models/gelu_approximation.onnx new file mode 100644 index 000000000..4374ddafd Binary files /dev/null and b/testdata/dnn/onnx/models/gelu_approximation.onnx differ diff --git a/testdata/dnn/onnx/models/gemm_vector_bias.onnx b/testdata/dnn/onnx/models/gemm_vector_bias.onnx new file mode 100644 index 000000000..5b290d8cc --- /dev/null +++ b/testdata/dnn/onnx/models/gemm_vector_bias.onnx @@ -0,0 +1,21 @@ +gemm_vector_bias:„ + +A +B +CY"Gemmgemm_vector_bias*k"`H5G?¹^?»†z?¨•L?Gì>ÃÐG?Ý9ò=ÝÑ#?4Ë>ÒÕq?Ú—?’NÔ>Õs‡>.4F?‰Œé>ã„?í™<\?N²?cï?y™q?Æ‹.?k¸>§Âß>BB*"õ—2?ü®v=9±*?ì®+?BCZ +A +  + +Z +B +  + +Z +C +  + +b +Y +  + +B \ No newline at end of file diff --git a/testdata/dnn/onnx/models/gru_cell_batchsize_1_seqlen_50.onnx b/testdata/dnn/onnx/models/gru_cell_batchsize_1_seqlen_50.onnx new file mode 100644 index 000000000..aac3d943a Binary files /dev/null and b/testdata/dnn/onnx/models/gru_cell_batchsize_1_seqlen_50.onnx differ diff --git a/testdata/dnn/onnx/models/gru_cell_batchsize_50_seqlen_1.onnx b/testdata/dnn/onnx/models/gru_cell_batchsize_50_seqlen_1.onnx new file mode 100644 index 000000000..0397a2952 Binary files /dev/null and b/testdata/dnn/onnx/models/gru_cell_batchsize_50_seqlen_1.onnx differ diff --git a/testdata/dnn/onnx/models/gru_cell_batchsize_5_seqlen_5.onnx b/testdata/dnn/onnx/models/gru_cell_batchsize_5_seqlen_5.onnx new file mode 100644 index 000000000..e3e52265e Binary files /dev/null and b/testdata/dnn/onnx/models/gru_cell_batchsize_5_seqlen_5.onnx differ diff --git a/testdata/dnn/onnx/models/lstm_cell_batchsize_1_seqlen_50.onnx b/testdata/dnn/onnx/models/lstm_cell_batchsize_1_seqlen_50.onnx new file mode 100644 index 000000000..261989225 Binary files /dev/null and b/testdata/dnn/onnx/models/lstm_cell_batchsize_1_seqlen_50.onnx differ diff --git a/testdata/dnn/onnx/models/lstm_cell_batchsize_50_seqlen_1.onnx b/testdata/dnn/onnx/models/lstm_cell_batchsize_50_seqlen_1.onnx new file mode 100644 index 000000000..0397a2952 Binary files /dev/null and b/testdata/dnn/onnx/models/lstm_cell_batchsize_50_seqlen_1.onnx differ diff --git a/testdata/dnn/onnx/models/lstm_cell_batchsize_5_seqlen_5.onnx b/testdata/dnn/onnx/models/lstm_cell_batchsize_5_seqlen_5.onnx new file mode 100644 index 000000000..b79aa677b Binary files /dev/null and b/testdata/dnn/onnx/models/lstm_cell_batchsize_5_seqlen_5.onnx differ diff --git a/testdata/dnn/onnx/models/lstm_init_h0_c0.onnx b/testdata/dnn/onnx/models/lstm_init_h0_c0.onnx new file mode 100644 index 000000000..09b44aa62 Binary files /dev/null and b/testdata/dnn/onnx/models/lstm_init_h0_c0.onnx differ diff --git a/testdata/dnn/onnx/models/lstm_layout_0.onnx b/testdata/dnn/onnx/models/lstm_layout_0.onnx new file mode 100644 index 000000000..c1215afa9 Binary files /dev/null and b/testdata/dnn/onnx/models/lstm_layout_0.onnx differ diff --git a/testdata/dnn/onnx/models/lstm_layout_1.onnx b/testdata/dnn/onnx/models/lstm_layout_1.onnx new file mode 100644 index 000000000..be75494a4 Binary files /dev/null and b/testdata/dnn/onnx/models/lstm_layout_1.onnx differ diff --git a/testdata/dnn/onnx/models/qlinearsoftmax_v11.onnx b/testdata/dnn/onnx/models/qlinearsoftmax_v11.onnx new file mode 100644 index 000000000..59301a99d Binary files /dev/null and b/testdata/dnn/onnx/models/qlinearsoftmax_v11.onnx differ diff --git a/testdata/dnn/onnx/models/qlinearsoftmax_v13.onnx b/testdata/dnn/onnx/models/qlinearsoftmax_v13.onnx new file mode 100644 index 000000000..683f8993e Binary files /dev/null and b/testdata/dnn/onnx/models/qlinearsoftmax_v13.onnx differ diff --git a/testdata/dnn/onnx/models/split_5.onnx b/testdata/dnn/onnx/models/split_5.onnx new file mode 100644 index 000000000..9262967eb Binary files /dev/null and b/testdata/dnn/onnx/models/split_5.onnx differ diff --git a/testdata/dnn/onnx/models/split_6.onnx b/testdata/dnn/onnx/models/split_6.onnx new file mode 100644 index 000000000..8aa97dc7f Binary files /dev/null and b/testdata/dnn/onnx/models/split_6.onnx differ diff --git a/testdata/dnn/onnx/models/where_layer.onnx b/testdata/dnn/onnx/models/where_layer.onnx new file mode 100644 index 000000000..dee8437b1 Binary files /dev/null and b/testdata/dnn/onnx/models/where_layer.onnx differ diff --git a/testdata/dnn/tflite/face_detection_short_range_out_classificators.npy b/testdata/dnn/tflite/face_detection_short_range_out_classificators.npy new file mode 100644 index 000000000..ee262b54b Binary files /dev/null and b/testdata/dnn/tflite/face_detection_short_range_out_classificators.npy differ diff --git a/testdata/dnn/tflite/face_detection_short_range_out_regressors.npy b/testdata/dnn/tflite/face_detection_short_range_out_regressors.npy new file mode 100644 index 000000000..a4f506b10 Binary files /dev/null and b/testdata/dnn/tflite/face_detection_short_range_out_regressors.npy differ diff --git a/testdata/dnn/tflite/face_landmark_out_conv2d_20.npy b/testdata/dnn/tflite/face_landmark_out_conv2d_20.npy new file mode 100644 index 000000000..3749fe235 Binary files /dev/null and b/testdata/dnn/tflite/face_landmark_out_conv2d_20.npy differ diff --git a/testdata/dnn/tflite/face_landmark_out_conv2d_30.npy b/testdata/dnn/tflite/face_landmark_out_conv2d_30.npy new file mode 100644 index 000000000..410ceca83 Binary files /dev/null and b/testdata/dnn/tflite/face_landmark_out_conv2d_30.npy differ diff --git a/testdata/dnn/tflite/generate.py b/testdata/dnn/tflite/generate.py new file mode 100644 index 000000000..b1d5d9d67 --- /dev/null +++ b/testdata/dnn/tflite/generate.py @@ -0,0 +1,47 @@ +# Use this script to generate test data for dnn module and TFLite models +import os +import numpy as np +import tensorflow as tf +import mediapipe as mp + +import cv2 as cv + +testdata = os.environ['OPENCV_TEST_DATA_PATH'] + +image = cv.imread(os.path.join(testdata, "cv", "shared", "lena.png")) +image = cv.cvtColor(image, cv.COLOR_BGR2RGB) + +def run_tflite_model(model_name, inp_size): + interpreter = tf.lite.Interpreter(model_name + ".tflite", + experimental_preserve_all_tensors=True) + interpreter.allocate_tensors() + + # Get input and output tensors. + input_details = interpreter.get_input_details() + output_details = interpreter.get_output_details() + + # Run model + inp = cv.resize(image, inp_size) + inp = np.expand_dims(inp, 0) + inp = inp.astype(np.float32) / 255 # NHWC + + interpreter.set_tensor(input_details[0]['index'], inp) + + interpreter.invoke() + + for details in output_details: + out = interpreter.get_tensor(details['index']) # Or use an intermediate layer index + out_name = details['name'] + np.save(f"{model_name}_out_{out_name}.npy", out) + + +def run_mediapipe_solution(solution, inp_size): + with solution as selfie_segmentation: + inp = cv.resize(image, inp_size) + results = selfie_segmentation.process(inp) + np.save(f"selfie_segmentation_out_activation_10.npy", results.segmentation_mask) + +run_tflite_model("face_landmark", (192, 192)) +run_tflite_model("face_detection_short_range", (128, 128)) + +run_mediapipe_solution(mp.solutions.selfie_segmentation.SelfieSegmentation(model_selection=0), (256, 256)) diff --git a/testdata/dnn/tflite/selfie_segmentation_out_activation_10.npy b/testdata/dnn/tflite/selfie_segmentation_out_activation_10.npy new file mode 100644 index 000000000..e917e942c Binary files /dev/null and b/testdata/dnn/tflite/selfie_segmentation_out_activation_10.npy differ diff --git a/testdata/highgui/readwrite/test_rgba_scale.bmp b/testdata/highgui/readwrite/test_rgba_scale.bmp new file mode 100644 index 000000000..e900f4466 Binary files /dev/null and b/testdata/highgui/readwrite/test_rgba_scale.bmp differ diff --git a/testdata/highgui/video/big_buck_bunny_full_color_range.h264 b/testdata/highgui/video/big_buck_bunny_full_color_range.h264 new file mode 100644 index 000000000..bd802788d Binary files /dev/null and b/testdata/highgui/video/big_buck_bunny_full_color_range.h264 differ