From 69fc0acd1ad30ef584ed11baf83fac538cb8bf71 Mon Sep 17 00:00:00 2001 From: Maxim Pashchenkov Date: Wed, 31 Mar 2021 00:08:43 +0300 Subject: [PATCH] Merge pull request #19752 from mpashchenkov:mp/onnx-int64-to-32 G-API: ONNX. Adding INT64-32 conversion for output. * Added int64 to 32 conversion * Added warning * Added type checks for all toCV * Added type checks for tests * Small fixes * Const for fixture in test * std::tuple if retutn value for toCV * Mistake * Changed toCV for tests * Added Assert * Fix for comments * One conversion for ONNX and IE * Clean up * One more fix * Added copyFromONNX * Removed warning * Apply review comments --- modules/gapi/src/backends/common/gbackend.hpp | 6 + modules/gapi/src/backends/ie/giebackend.cpp | 16 +- .../gapi/src/backends/onnx/gonnxbackend.cpp | 54 ++++-- .../gapi/test/infer/gapi_infer_onnx_test.cpp | 157 ++++++++++++++---- 4 files changed, 182 insertions(+), 51 deletions(-) diff --git a/modules/gapi/src/backends/common/gbackend.hpp b/modules/gapi/src/backends/common/gbackend.hpp index 790d7650d9..b22ec5e177 100644 --- a/modules/gapi/src/backends/common/gbackend.hpp +++ b/modules/gapi/src/backends/common/gbackend.hpp @@ -209,6 +209,12 @@ inline cv::util::optional getCompileArg(const cv::GCompileArgs &args) void GAPI_EXPORTS createMat(const cv::GMatDesc& desc, cv::Mat& mat); +inline void convertInt64ToInt32(const int64_t* src, int* dst, size_t size) +{ + std::transform(src, src + size, dst, + [](int64_t el) { return static_cast(el); }); +} + }} // cv::gimpl #endif // OPENCV_GAPI_GBACKEND_HPP diff --git a/modules/gapi/src/backends/ie/giebackend.cpp b/modules/gapi/src/backends/ie/giebackend.cpp index 6cf77acac3..13daf5d6df 100644 --- a/modules/gapi/src/backends/ie/giebackend.cpp +++ b/modules/gapi/src/backends/ie/giebackend.cpp @@ -106,7 +106,7 @@ inline IE::Precision toIE(int depth) { case CV_8U: return IE::Precision::U8; case CV_32S: return IE::Precision::I32; case CV_32F: return IE::Precision::FP32; - default: GAPI_Assert(false && "Unsupported data type"); + default: GAPI_Assert(false && "IE. Unsupported data type"); } return IE::Precision::UNSPECIFIED; } @@ -115,7 +115,8 @@ inline int toCV(IE::Precision prec) { case IE::Precision::U8: return CV_8U; case IE::Precision::FP32: return CV_32F; case IE::Precision::I32: return CV_32S; - default: GAPI_Assert(false && "Unsupported data type"); + case IE::Precision::I64: return CV_32S; + default: GAPI_Assert(false && "IE. Unsupported data type"); } return -1; } @@ -158,7 +159,7 @@ inline IE::Blob::Ptr wrapIE(const cv::Mat &mat, cv::gapi::ie::TraitAs hint) { HANDLE(32F, float); HANDLE(32S, int); #undef HANDLE - default: GAPI_Assert(false && "Unsupported data type"); + default: GAPI_Assert(false && "IE. Unsupported data type"); } return IE::Blob::Ptr{}; } @@ -194,7 +195,14 @@ inline void copyFromIE(const IE::Blob::Ptr &blob, MatType &mat) { HANDLE(FP32, float); HANDLE(I32, int); #undef HANDLE - default: GAPI_Assert(false && "Unsupported data type"); + case IE::Precision::I64: { + GAPI_LOG_WARNING(NULL, "INT64 isn't supported for cv::Mat. Conversion to INT32 is used."); + cv::gimpl::convertInt64ToInt32(blob->buffer().as(), + reinterpret_cast(mat.data), + mat.total()); + break; + } + default: GAPI_Assert(false && "IE. Unsupported data type"); } } diff --git a/modules/gapi/src/backends/onnx/gonnxbackend.cpp b/modules/gapi/src/backends/onnx/gonnxbackend.cpp index 2b7f40a92d..d5a8a1f6ed 100644 --- a/modules/gapi/src/backends/onnx/gonnxbackend.cpp +++ b/modules/gapi/src/backends/onnx/gonnxbackend.cpp @@ -170,7 +170,8 @@ inline int toCV(ONNXTensorElementDataType prec) { case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: return CV_8U; case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: return CV_32F; case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: return CV_32S; - default: GAPI_Assert(false && "Unsupported data type"); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: return CV_32S; + default: GAPI_Assert(false && "ONNX. Unsupported data type"); } return -1; } @@ -184,11 +185,30 @@ inline std::vector toCV(const std::vector &vsz) { return result; } -inline cv::Mat toCV(Ort::Value &v) { - auto info = v.GetTensorTypeAndShapeInfo(); - return cv::Mat(toCV(info.GetShape()), - toCV(info.GetElementType()), - reinterpret_cast(v.GetTensorMutableData())); +inline void copyFromONNX(Ort::Value &v, cv::Mat& mat) { + const auto info = v.GetTensorTypeAndShapeInfo(); + const auto prec = info.GetElementType(); + const auto shape = toCV(info.GetShape()); + mat.create(shape, toCV(prec)); + switch (prec) { +#define HANDLE(E,T) \ + case E: std::copy_n(v.GetTensorMutableData(), \ + mat.total(), \ + reinterpret_cast(mat.data)); \ + break; + HANDLE(ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8, uint8_t); + HANDLE(ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, float); + HANDLE(ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32, int); +#undef HANDLE + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: { + GAPI_LOG_WARNING(NULL, "INT64 isn't supported for cv::Mat. Conversion to INT32 is used."); + cv::gimpl::convertInt64ToInt32(v.GetTensorMutableData(), + reinterpret_cast(mat.data), + mat.total()); + break; + } + default: GAPI_Assert(false && "ONNX. Unsupported data type"); + } } inline std::vector toORT(const cv::MatSize &sz) { @@ -199,12 +219,13 @@ inline void preprocess(const cv::Mat& src, const cv::gimpl::onnx::TensorInfo& ti, cv::Mat& dst) { GAPI_Assert(src.depth() == CV_32F || src.depth() == CV_8U); - + // CNN input type + const auto type = toCV(ti.type); if (src.depth() == CV_32F) { // Just pass the tensor as-is. // No layout or dimension transformations done here! // TODO: This needs to be aligned across all NN backends. - GAPI_Assert(toCV(ti.type) == CV_32F && "Only 32F model input is supported for 32F data"); + GAPI_Assert(type == CV_32F && "Only 32F model input is supported for 32F input data"); const auto tensor_dims = toORT(src.size); if (tensor_dims.size() == ti.dims.size()) { for (size_t i = 0; i < ti.dims.size(); ++i) { @@ -218,16 +239,15 @@ inline void preprocess(const cv::Mat& src, dst = src; } else { // 8U input: full preprocessing path - GAPI_Assert(src.depth() == CV_8U && "Only 8U data type is supported for preproc"); + GAPI_Assert(src.depth() == CV_8U && "Only 8U data type is supported for preproc"); GAPI_Assert((ti.dims.size() == 4u || ti.dims.size() == 3u) && "Only NCHW/NHWC/CHW/HWC layouts are supported for preproc"); const bool with_batch = ti.dims.size() == 4u ? true : false; const int shift = with_batch ? 0 : 1; - const auto ddepth = toCV(ti.type); - GAPI_Assert((ddepth == CV_8U || ddepth == CV_32F) - && "Only 8U and 32F model input is supported for 8U data"); + GAPI_Assert((type == CV_8U || type == CV_32F) + && "Only 8U and 32F model input is supported for 8U input data"); // Assess the expected input layout const bool is_hwc = [&](int ch) { @@ -261,8 +281,8 @@ inline void preprocess(const cv::Mat& src, cv::Mat rsz, pp; cv::resize(csc, rsz, cv::Size(new_w, new_h)); - if (src.depth() == CV_8U && ddepth == CV_32F) { - rsz.convertTo(pp, ddepth, ti.normalize ? 1.f / 255 : 1.f); + if (src.depth() == CV_8U && type == CV_32F) { + rsz.convertTo(pp, type, ti.normalize ? 1.f / 255 : 1.f); if (ti.mstd.has_value()) { pp -= ti.mstd->mean; pp /= ti.mstd->stdev; @@ -273,7 +293,7 @@ inline void preprocess(const cv::Mat& src, if (!is_hwc && new_c > 1) { // Convert to CHW - dst.create(cv::Size(new_w, new_h * new_c), ddepth); + dst.create(cv::Size(new_w, new_h * new_c), type); std::vector planes(new_c); for (int ch = 0; ch < new_c; ++ch) { planes[ch] = dst.rowRange(ch * new_h, (ch + 1) * new_h); @@ -347,7 +367,7 @@ inline Ort::Value createTensor(const Ort::MemoryInfo& memory_info, case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: return createTensor(memory_info, tensor_params, data); default: - GAPI_Assert(false && "Unsupported data type"); + GAPI_Assert(false && "ONNX. Unsupported data type"); } return Ort::Value{nullptr}; } @@ -796,7 +816,7 @@ void ONNXCompiled::Run(const std::vector& ins, ade::util::toRange(outputs))) { const auto &out_name = std::get<0>(iter).name; auto &out_tensor = std::get<1>(iter); - onnx_outputs[out_name] = toCV(out_tensor); + copyFromONNX(out_tensor, onnx_outputs[out_name]); } // Fill in G-API outputs diff --git a/modules/gapi/test/infer/gapi_infer_onnx_test.cpp b/modules/gapi/test/infer/gapi_infer_onnx_test.cpp index 5dc127bfa5..804f731b47 100644 --- a/modules/gapi/test/infer/gapi_infer_onnx_test.cpp +++ b/modules/gapi/test/infer/gapi_infer_onnx_test.cpp @@ -122,16 +122,44 @@ inline void toCHW(const cv::Mat& src, cv::Mat& dst) { cv::split(src, planes); } -inline int toCV(const ONNXTensorElementDataType prec) { +inline int toCV(ONNXTensorElementDataType prec) { switch (prec) { case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: return CV_8U; case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: return CV_32F; case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: return CV_32S; + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: return CV_32S; default: GAPI_Assert(false && "Unsupported data type"); } return -1; } +void copyFromONNX(Ort::Value &v, cv::Mat& mat) { + const auto info = v.GetTensorTypeAndShapeInfo(); + const auto prec = info.GetElementType(); + const auto shape = info.GetShape(); + const std::vector dims(shape.begin(), shape.end()); + mat.create(dims, toCV(prec)); + switch (prec) { +#define HANDLE(E,T) \ + case E: std::copy_n(v.GetTensorMutableData(), \ + mat.total(), \ + reinterpret_cast(mat.data)); \ + break; + HANDLE(ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8, uint8_t); + HANDLE(ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, float); + HANDLE(ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32, int); +#undef HANDLE + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: { + const auto o_ptr = v.GetTensorMutableData(); + const auto g_ptr = reinterpret_cast(mat.data); + std::transform(o_ptr, o_ptr + mat.total(), g_ptr, + [](int64_t el) { return static_cast(el); }); + break; + } + default: GAPI_Assert(false && "ONNX. Unsupported data type"); + } +} + inline std::vector toORT(const cv::MatSize &sz) { return cv::to_own(sz); } @@ -237,6 +265,26 @@ void remapSSDPorts(const std::unordered_map &onnx, remapToIESSDOut({num_detections, detection_boxes, detection_scores, detection_classes}, ssd_output); } +void remapRCNNPorts(const std::unordered_map &onnx, + std::unordered_map &gapi) { + // Simple copy for outputs + const cv::Mat& in_boxes = onnx.at("6379"); + const cv::Mat& in_labels = onnx.at("6381"); + const cv::Mat& in_scores = onnx.at("6383"); + + GAPI_Assert(in_boxes.depth() == CV_32F); + GAPI_Assert(in_labels.depth() == CV_32S); + GAPI_Assert(in_scores.depth() == CV_32F); + + cv::Mat& out_boxes = gapi.at("out1"); + cv::Mat& out_labels = gapi.at("out2"); + cv::Mat& out_scores = gapi.at("out3"); + + copyToOut(in_boxes, out_boxes); + copyToOut(in_labels, out_labels); + copyToOut(in_scores, out_scores); +} + class ONNXtest : public ::testing::Test { public: std::string model_path; @@ -250,7 +298,6 @@ public: env = Ort::Env(ORT_LOGGING_LEVEL_WARNING, "test"); memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault); out_gapi.resize(1); - out_onnx.resize(1); // FIXME: It should be an image from own (gapi) directory in opencv extra in_mat1 = cv::imread(findDataFile("cv/dpm/cat.png")); } @@ -301,14 +348,13 @@ public: num_out); // Copy outputs GAPI_Assert(result.size() == num_out); - outs.resize(num_out); for (size_t i = 0; i < num_out; ++i) { const auto info = result[i].GetTensorTypeAndShapeInfo(); const auto shape = info.GetShape(); - const auto type = info.GetElementType(); - cv::Mat mt(std::vector(shape.begin(), shape.end()), toCV(type), - reinterpret_cast(result[i].GetTensorMutableData())); - mt.copyTo(outs[i]); + const auto type = toCV(info.GetElementType()); + const std::vector dims(shape.begin(), shape.end()); + outs.emplace_back(dims, type); + copyFromONNX(result[i], outs.back()); } } // One input/output overload @@ -357,7 +403,7 @@ public: // Rois for InferList, InferList2 const std::vector rois = { cv::Rect(cv::Point{ 0, 0}, cv::Size{80, 120}), - cv::Rect(cv::Point{50, 100}, cv::Size{250, 360}), + cv::Rect(cv::Point{50, 100}, cv::Size{250, 360}) }; void preprocess(const cv::Mat& src, cv::Mat& dst) { @@ -426,6 +472,37 @@ public: } }; +class ONNXRCNN : public ONNXWithRemap { +private: + const cv::Scalar rcnn_mean = { 102.9801, 115.9465, 122.7717 }; + const float range_max = 1333; + const float range_min = 800; +public: + void preprocess(const cv::Mat& src, cv::Mat& dst) { + cv::Mat rsz, cvt, chw, mn; + const auto get_ratio = [&](const int dim) -> float { + return ((dim > range_max) || (dim < range_min)) + ? dim > range_max + ? range_max / dim + : range_min / dim + : 1.f; + }; + const auto ratio_h = get_ratio(src.rows); + const auto ratio_w = get_ratio(src.cols); + const auto new_h = static_cast(ratio_h * src.rows); + const auto new_w = static_cast(ratio_w * src.cols); + cv::resize(src, rsz, cv::Size(new_w, new_h)); + rsz.convertTo(cvt, CV_32F, 1.f); + toCHW(cvt, chw); + mn = chw - rcnn_mean; + const int padded_h = std::ceil(new_h / 32.f) * 32; + const int padded_w = std::ceil(new_w / 32.f) * 32; + cv::Mat pad_im(cv::Size(padded_w, 3 * padded_h), CV_32F, 0.f); + pad_im(cv::Rect(0, 0, mn.cols, mn.rows)) += mn; + dst = pad_im.reshape(1, {3, padded_h, padded_w}); + } +}; + class ONNXYoloV3MultiInput : public ONNXWithRemap { public: std::vector ins; @@ -459,7 +536,7 @@ TEST_F(ONNXClassificationTest, Infer) // ONNX_API code cv::Mat processed_mat; preprocess(in_mat1, processed_mat); - infer(processed_mat, out_onnx.front()); + infer(processed_mat, out_onnx); // G_API code G_API_NET(SqueezNet, , "squeeznet"); cv::GMat in; @@ -482,7 +559,7 @@ TEST_F(ONNXClassificationTest, InferTensor) cv::Mat tensor; preprocess(in_mat1, tensor); // ONNX_API code - infer(tensor, out_onnx.front()); + infer(tensor, out_onnx); // G_API code G_API_NET(SqueezNet, , "squeeznet"); cv::GMat in; @@ -499,11 +576,11 @@ TEST_F(ONNXClassificationTest, InferTensor) TEST_F(ONNXClassificationTest, InferROI) { useModel("classification/squeezenet/model/squeezenet1.0-9"); - const auto ROI = rois.at(1); + const auto ROI = rois.at(0); // ONNX_API code cv::Mat roi_mat; preprocess(in_mat1(ROI), roi_mat); - infer(roi_mat, out_onnx.front()); + infer(roi_mat, out_onnx); // G_API code G_API_NET(SqueezNet, , "squeeznet"); cv::GMat in; @@ -524,11 +601,10 @@ TEST_F(ONNXClassificationTest, InferROIList) { useModel("classification/squeezenet/model/squeezenet1.0-9"); // ONNX_API code - out_onnx.resize(rois.size()); for (size_t i = 0; i < rois.size(); ++i) { cv::Mat roi_mat; preprocess(in_mat1(rois[i]), roi_mat); - infer(roi_mat, out_onnx[i]); + infer(roi_mat, out_onnx); } // G_API code G_API_NET(SqueezNet, , "squeeznet"); @@ -550,11 +626,10 @@ TEST_F(ONNXClassificationTest, Infer2ROIList) { useModel("classification/squeezenet/model/squeezenet1.0-9"); // ONNX_API code - out_onnx.resize(rois.size()); for (size_t i = 0; i < rois.size(); ++i) { cv::Mat roi_mat; preprocess(in_mat1(rois[i]), roi_mat); - infer(roi_mat, out_onnx[i]); + infer(roi_mat, out_onnx); } // G_API code G_API_NET(SqueezNet, , "squeeznet"); @@ -582,7 +657,7 @@ TEST_F(ONNXWithRemap, InferDynamicInputTensor) toCHW(cvt, tensor); tensor = tensor.reshape(1, {1, 3, 416, 416}); // ONNX_API code - infer(tensor, out_onnx.front()); + infer(tensor, out_onnx); // G_API code G_API_NET(YoloNet, , "YoloNet"); cv::GMat in; @@ -604,7 +679,7 @@ TEST_F(ONNXGRayScaleTest, InferImage) // ONNX_API code cv::Mat prep_mat; preprocess(in_mat1, prep_mat); - infer(prep_mat, out_onnx.front()); + infer(prep_mat, out_onnx); // G_API code G_API_NET(EmotionNet, , "emotion-ferplus"); cv::GMat in; @@ -650,7 +725,7 @@ TEST_F(ONNXMediaFrameTest, InferBGR) // ONNX_API code cv::Mat processed_mat; preprocess(in_mat1, processed_mat); - infer(processed_mat, out_onnx.front()); + infer(processed_mat, out_onnx); // G_API code auto frame = MediaFrame::Create(in_mat1); G_API_NET(SqueezNet, , "squeeznet"); @@ -676,7 +751,7 @@ TEST_F(ONNXMediaFrameTest, InferYUV) cvtColorTwoPlane(m_in_y, m_in_uv, pp, cv::COLOR_YUV2BGR_NV12); cv::Mat processed_mat; preprocess(pp, processed_mat); - infer(processed_mat, out_onnx.front()); + infer(processed_mat, out_onnx); // G_API code G_API_NET(SqueezNet, , "squeeznet"); cv::GFrame in; @@ -699,7 +774,7 @@ TEST_F(ONNXMediaFrameTest, InferROIBGR) // ONNX_API code cv::Mat roi_mat; preprocess(in_mat1(rois.front()), roi_mat); - infer(roi_mat, out_onnx.front()); + infer(roi_mat, out_onnx); // G_API code G_API_NET(SqueezNet, , "squeeznet"); cv::GFrame in; @@ -725,7 +800,7 @@ TEST_F(ONNXMediaFrameTest, InferROIYUV) cvtColorTwoPlane(m_in_y, m_in_uv, pp, cv::COLOR_YUV2BGR_NV12); cv::Mat roi_mat; preprocess(pp(rois.front()), roi_mat); - infer(roi_mat, out_onnx.front()); + infer(roi_mat, out_onnx); // G_API code G_API_NET(SqueezNet, , "squeeznet"); cv::GFrame in; @@ -747,11 +822,10 @@ TEST_F(ONNXMediaFrameTest, InferListBGR) useModel("classification/squeezenet/model/squeezenet1.0-9"); const auto frame = MediaFrame::Create(in_mat1); // ONNX_API code - out_onnx.resize(rois.size()); for (size_t i = 0; i < rois.size(); ++i) { cv::Mat roi_mat; preprocess(in_mat1(rois[i]), roi_mat); - infer(roi_mat, out_onnx[i]); + infer(roi_mat, out_onnx); } // G_API code G_API_NET(SqueezNet, , "squeeznet"); @@ -776,11 +850,10 @@ TEST_F(ONNXMediaFrameTest, InferListYUV) // ONNX_API code cv::Mat pp; cvtColorTwoPlane(m_in_y, m_in_uv, pp, cv::COLOR_YUV2BGR_NV12); - out_onnx.resize(rois.size()); for (size_t i = 0; i < rois.size(); ++i) { cv::Mat roi_mat; preprocess(pp(rois[i]), roi_mat); - infer(roi_mat, out_onnx[i]); + infer(roi_mat, out_onnx); } // G_API code G_API_NET(SqueezNet, , "squeeznet"); @@ -803,11 +876,10 @@ TEST_F(ONNXMediaFrameTest, InferList2BGR) useModel("classification/squeezenet/model/squeezenet1.0-9"); const auto frame = MediaFrame::Create(in_mat1); // ONNX_API code - out_onnx.resize(rois.size()); for (size_t i = 0; i < rois.size(); ++i) { cv::Mat roi_mat; preprocess(in_mat1(rois[i]), roi_mat); - infer(roi_mat, out_onnx[i]); + infer(roi_mat, out_onnx); } // G_API code G_API_NET(SqueezNet, , "squeeznet"); @@ -832,11 +904,10 @@ TEST_F(ONNXMediaFrameTest, InferList2YUV) // ONNX_API code cv::Mat pp; cvtColorTwoPlane(m_in_y, m_in_uv, pp, cv::COLOR_YUV2BGR_NV12); - out_onnx.resize(rois.size()); for (size_t i = 0; i < rois.size(); ++i) { cv::Mat roi_mat; preprocess(pp(rois[i]), roi_mat); - infer(roi_mat, out_onnx[i]); + infer(roi_mat, out_onnx); } // G_API code G_API_NET(SqueezNet, , "squeeznet"); @@ -917,6 +988,32 @@ TEST_F(ONNXYoloV3MultiInput, InferBSConstInput) // Validate validate(); } + +TEST_F(ONNXRCNN, ConversionInt64to32) +{ + useModel("object_detection_segmentation/faster-rcnn/model/FasterRCNN-10"); + cv::Mat dst; + preprocess(in_mat1, dst); + // ONNX_API code + infer(dst, out_onnx); + // G_API code + using FRCNNOUT = std::tuple; + G_API_NET(FasterRCNN, , "FasterRCNN"); + auto net = cv::gapi::onnx::Params{model_path} + .cfgOutputLayers({"out1", "out2", "out3"}) + .cfgPostProc({cv::GMatDesc{CV_32F, {7,4}}, + cv::GMatDesc{CV_32S, {7}}, + cv::GMatDesc{CV_32F, {7}}}, remapRCNNPorts); + cv::GMat in, out1, out2, out3; + std::tie(out1, out2, out3) = cv::gapi::infer(in); + cv::GComputation comp(cv::GIn(in), cv::GOut(out1, out2, out3)); + out_gapi.resize(num_out); + comp.apply(cv::gin(dst), + cv::gout(out_gapi[0], out_gapi[1], out_gapi[2]), + cv::compile_args(cv::gapi::networks(net))); + // Validate + validate(); +} } // namespace opencv_test #endif // HAVE_ONNX