mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 07:43:03 +04:00
Merge pull request #27656 from abhishek-gola:size_layer_add
Added Size layer to new DNN engine #27656 Merge with https://github.com/opencv/opencv_extra/pull/1274 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -1245,6 +1245,12 @@ CV__DNN_INLINE_NS_BEGIN
|
||||
static Ptr<ResizeLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS SizeLayer : public Layer
|
||||
{
|
||||
public:
|
||||
static Ptr<SizeLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Bilinear resize layer from https://github.com/cdmh/deeplab-public-ver2
|
||||
*
|
||||
|
||||
@@ -99,6 +99,7 @@ void initializeLayerFactory()
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Reshape, ReshapeLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Reshape2, Reshape2Layer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Resize, ResizeLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Size, SizeLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Shape, ShapeLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Slice, SliceLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Slice2, Slice2Layer);
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
// Copyright (C) 2025, BigVision LLC, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
|
||||
class SizeLayerImpl CV_FINAL : public SizeLayer
|
||||
{
|
||||
public:
|
||||
SizeLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId) CV_OVERRIDE
|
||||
{
|
||||
return backendId == DNN_BACKEND_OPENCV;
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape>& inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape>& outputs,
|
||||
std::vector<MatShape>& internals) const CV_OVERRIDE
|
||||
{
|
||||
outputs.assign(1, MatShape({1}));
|
||||
return false;
|
||||
}
|
||||
|
||||
void getTypes(const std::vector<MatType>& /*inputs*/,
|
||||
const int requiredOutputs,
|
||||
const int requiredInternals,
|
||||
std::vector<MatType>& outputs,
|
||||
std::vector<MatType>& internals) const CV_OVERRIDE
|
||||
{
|
||||
outputs.assign(requiredOutputs, MatType(CV_64S));
|
||||
internals.assign(requiredInternals, MatType(CV_64S));
|
||||
}
|
||||
|
||||
void forward(InputArrayOfArrays inputs_arr,
|
||||
OutputArrayOfArrays outputs_arr,
|
||||
OutputArrayOfArrays /*internals_arr*/) CV_OVERRIDE
|
||||
{
|
||||
std::vector<Mat> inputs, outputs;
|
||||
inputs_arr.getMatVector(inputs);
|
||||
outputs_arr.getMatVector(outputs);
|
||||
|
||||
CV_Assert(inputs.size() == 1);
|
||||
const Mat& x = inputs[0];
|
||||
|
||||
const MatShape xShape = shape(x);
|
||||
int64_t totalElems = static_cast<int64_t>(total(xShape));
|
||||
|
||||
outputs[0].create(1, 1, CV_64S);
|
||||
outputs[0].at<int64_t>(0) = totalElems;
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<SizeLayer> SizeLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<SizeLayer>(new SizeLayerImpl(params));
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -211,6 +211,7 @@ protected:
|
||||
void parseRelu (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseTrilu (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseResize (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseSize (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseReshape (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseScatter (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseShape (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
@@ -1595,6 +1596,12 @@ void ONNXImporter2::parseResize(LayerParams& layerParams, const opencv_onnx::Nod
|
||||
addLayer(layerParams, node_proto, ninputs);
|
||||
}
|
||||
|
||||
void ONNXImporter2::parseSize(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "Size";
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
|
||||
void ONNXImporter2::parseTrilu(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
int ninputs = node_proto.input_size();
|
||||
@@ -2431,6 +2438,7 @@ void ONNXImporter2::buildDispatchMap_ONNX_AI(int opset_version)
|
||||
dispatch["Concat"] = &ONNXImporter2::parseConcat;
|
||||
dispatch["If"] = &ONNXImporter2::parseIf;
|
||||
dispatch["Resize"] = &ONNXImporter2::parseResize;
|
||||
dispatch["Size"] = &ONNXImporter2::parseSize;
|
||||
dispatch["Trilu"] = &ONNXImporter2::parseTrilu;
|
||||
dispatch["Upsample"] = &ONNXImporter2::parseUpsample;
|
||||
dispatch["SoftMax"] = dispatch["Softmax"] = dispatch["LogSoftmax"] = &ONNXImporter2::parseSoftMax;
|
||||
|
||||
@@ -2853,4 +2853,57 @@ TEST(Layer_If, resize)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Layer_Size, onnx_1d)
|
||||
{
|
||||
auto engine_forced = static_cast<cv::dnn::EngineType>(
|
||||
cv::utils::getConfigurationParameterSizeT("OPENCV_FORCE_DNN_ENGINE", cv::dnn::ENGINE_AUTO));
|
||||
if (engine_forced == cv::dnn::ENGINE_CLASSIC)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_PARSER);
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string modelname = findDataFile("dnn/onnx/models/test_size_1d_model.onnx", true);
|
||||
cv::dnn::Net net = cv::dnn::readNetFromONNX(modelname, ENGINE_NEW);
|
||||
|
||||
int sz1d[1] = {7};
|
||||
cv::Mat x(1, sz1d, CV_32F);
|
||||
cv::randu(x, 0, 1);
|
||||
net.setInput(x);
|
||||
|
||||
std::vector<cv::Mat> outs;
|
||||
net.forward(outs);
|
||||
|
||||
ASSERT_EQ(outs.size(), 1u);
|
||||
EXPECT_EQ(outs[0].total(), (size_t)1);
|
||||
EXPECT_EQ(outs[0].type(), CV_64S);
|
||||
EXPECT_EQ(outs[0].at<int64_t>(0), static_cast<int64_t>(sz1d[0]));
|
||||
}
|
||||
|
||||
TEST(Layer_Size, onnx_0d_scalar)
|
||||
{
|
||||
auto engine_forced = static_cast<cv::dnn::EngineType>(
|
||||
cv::utils::getConfigurationParameterSizeT("OPENCV_FORCE_DNN_ENGINE", cv::dnn::ENGINE_AUTO));
|
||||
if (engine_forced == cv::dnn::ENGINE_CLASSIC)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_PARSER);
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string modelname = findDataFile("dnn/onnx/models/test_size_0d_model.onnx", true);
|
||||
cv::dnn::Net net = cv::dnn::readNetFromONNX(modelname, ENGINE_NEW);
|
||||
|
||||
cv::Mat x(1, 1, CV_32F);
|
||||
x.at<float>(0, 0) = 3.14f;
|
||||
net.setInput(x);
|
||||
|
||||
std::vector<cv::Mat> outs;
|
||||
net.forward(outs);
|
||||
|
||||
ASSERT_EQ(outs.size(), 1u);
|
||||
EXPECT_EQ(outs[0].total(), (size_t)1);
|
||||
EXPECT_EQ(outs[0].type(), CV_64S);
|
||||
EXPECT_EQ(outs[0].at<int64_t>(0), 1);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -1021,11 +1021,11 @@ CASE(test_maxunpool_export_without_output_shape)
|
||||
SKIP;
|
||||
#endif
|
||||
CASE(test_mean_example)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_mean_one_input)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_mean_two_inputs)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_min_example)
|
||||
// no filter
|
||||
CASE(test_min_float16)
|
||||
@@ -1868,9 +1868,9 @@ CASE(test_sinh)
|
||||
CASE(test_sinh_example)
|
||||
// no filter
|
||||
CASE(test_size)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_size_example)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_slice)
|
||||
SKIP;
|
||||
CASE(test_slice_default_axes)
|
||||
|
||||
@@ -66,3 +66,8 @@
|
||||
"test_clip_inbounds",
|
||||
"test_clip_outbounds",
|
||||
"test_clip_splitbounds",
|
||||
"test_size",
|
||||
"test_size_example",
|
||||
"test_mean_example",
|
||||
"test_mean_one_input",
|
||||
"test_mean_two_inputs",
|
||||
|
||||
@@ -123,9 +123,6 @@
|
||||
"test_max_uint16", // Issue:: Unsupported data type
|
||||
"test_max_uint32", // Issue:: Unsupported data type
|
||||
"test_max_uint64", // Issue:: Unsupported data type
|
||||
"test_mean_example", // Issues::Layer does not exist. Can't create layer "onnx_node_output_0!result" of type "Mean" in function 'getLayerInstance'
|
||||
"test_mean_one_input", // ---- same as above ---
|
||||
"test_mean_two_inputs", // ---- same as above ---
|
||||
"test_min_int16", // Issue:: Unsupported data type
|
||||
"test_min_uint16", // Issue:: Unsupported data type
|
||||
"test_min_uint32", // Issue:: Unkonwn error
|
||||
@@ -320,8 +317,6 @@
|
||||
"test_simple_rnn_batchwise", // Issue:: Parser: Can't create layer "onnx_node_output_1!Y_h" of type "RNN" in function 'getLayerInstance'
|
||||
"test_simple_rnn_defaults", // ---- same as above ---
|
||||
"test_simple_rnn_with_initial_bias", // ---- same as above ---
|
||||
"test_size", // Issue:: Parser: Can't create layer "onnx_node_output_0!y" of type "Size" in function 'getLayerInstance'
|
||||
"test_size_example", // ---- same as above ---
|
||||
"test_slice_start_out_of_bounds",
|
||||
"test_split_zero_size_splits", // ---- incompatible type of input tensor #0 'input': CV_8UC1 given, CV_32FC1 expected in function 'setGraphInput' ---
|
||||
"test_strnormalizer_export_monday_casesensintive_lower", // 'Strings' (1) are not supported in function 'getLayerParams'
|
||||
|
||||
Reference in New Issue
Block a user