mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 07:43:03 +04:00
Merge pull request #27586 from abhishek-gola:resize_layer_add
Added fully functional resize layer to new DNN engine #27586 ### 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:
@@ -1281,6 +1281,12 @@ CV__DNN_INLINE_NS_BEGIN
|
||||
static Ptr<DetLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS Resize2Layer : public Layer
|
||||
{
|
||||
public:
|
||||
static Ptr<Resize2Layer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Bilinear resize layer from https://github.com/cdmh/deeplab-public-ver2
|
||||
*
|
||||
|
||||
@@ -101,6 +101,7 @@ void initializeLayerFactory()
|
||||
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(Resize2, Resize2Layer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Shape, ShapeLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Slice, SliceLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Slice2, Slice2Layer);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -213,11 +213,12 @@ protected:
|
||||
void parseTrilu (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseIsNaN (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseIsInf (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseDet (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseDet (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseGridSample (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 parseUnique (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseResize2 (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);
|
||||
@@ -1538,13 +1539,12 @@ void ONNXImporter2::parseIf(LayerParams& layerParams,
|
||||
}
|
||||
|
||||
// https://github.com/onnx/onnx/blob/master/docs/Operators.md#Resize
|
||||
void ONNXImporter2::parseResize(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
void ONNXImporter2::parseResize2(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
int ninputs = node_proto.input_size();
|
||||
layerParams.type = "Resize";
|
||||
layerParams.type = "Resize2";
|
||||
String interp_mode = layerParams.get<String>("coordinate_transformation_mode", "half_pixel");
|
||||
|
||||
CV_Assert(interp_mode != "tf_crop_and_resize");
|
||||
bool halfPixel = interp_mode == "tf_half_pixel_for_nn" || interp_mode == "half_pixel" || interp_mode == "pytorch_half_pixel";
|
||||
|
||||
layerParams.set("align_corners", interp_mode == "align_corners");
|
||||
@@ -1566,16 +1566,39 @@ void ONNXImporter2::parseResize(LayerParams& layerParams, const opencv_onnx::Nod
|
||||
if(scalesArg.idx > 0 && netimpl->isConstArg(scalesArg))
|
||||
scales = netimpl->argTensor(scalesArg);
|
||||
|
||||
if (ninputs >= 3 && interp_mode == "tf_crop_and_resize") {
|
||||
int roiInputId = 1;
|
||||
Arg roiArg = node_inputs[roiInputId];
|
||||
if (!netimpl->isConstArg(roiArg)) {
|
||||
CV_Error(Error::StsNotImplemented, "ONNX/Resize: only empty ROI is supported");
|
||||
}
|
||||
Mat roi = netimpl->argTensor(roiArg);
|
||||
if (!roi.empty()) {
|
||||
CV_Error(Error::StsNotImplemented, "ONNX/Resize: only empty ROI is supported");
|
||||
if (interp_mode == "tf_crop_and_resize")
|
||||
{
|
||||
CV_Assert(ninputs >= 3);
|
||||
Arg roiArg = node_inputs[1];
|
||||
bool hasSizes = (ninputs >= 4);
|
||||
Arg sizesArg = hasSizes ? node_inputs[3] : Arg();
|
||||
|
||||
bool staticRoi = netimpl->isConstArg(roiArg);
|
||||
bool staticSizes = hasSizes && netimpl->isConstArg(sizesArg);
|
||||
|
||||
if (staticRoi && (!hasSizes || staticSizes))
|
||||
{
|
||||
Mat roiMat = netimpl->argTensor(roiArg), roiF;
|
||||
CV_CheckEQ(roiMat.total(), (size_t)4,
|
||||
"ONNX/Resize: ROI must have 4 values [y1,x1,y2,x2]");
|
||||
roiMat.convertTo(roiF, CV_32F);
|
||||
layerParams.set("y1", roiF.at<float>(0));
|
||||
layerParams.set("x1", roiF.at<float>(1));
|
||||
layerParams.set("y2", roiF.at<float>(2));
|
||||
layerParams.set("x2", roiF.at<float>(3));
|
||||
|
||||
if (hasSizes && staticSizes)
|
||||
{
|
||||
Mat szMat = netimpl->argTensor(sizesArg), sz;
|
||||
CV_CheckEQ(szMat.total(), (size_t)4,
|
||||
"ONNX/Resize: sizes must have 4 values [N,C,H,W]");
|
||||
szMat.convertTo(sz, CV_32S);
|
||||
layerParams.set("height", sz.at<int>(2));
|
||||
layerParams.set("width", sz.at<int>(3));
|
||||
}
|
||||
layerParams.set("dynamic_roi", false);
|
||||
}
|
||||
else layerParams.set("dynamic_roi", true);
|
||||
}
|
||||
|
||||
if (scales.total() == 4)
|
||||
@@ -1599,6 +1622,20 @@ void ONNXImporter2::parseResize(LayerParams& layerParams, const opencv_onnx::Nod
|
||||
ninputs = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i_attr = 0; i_attr < node_proto.attribute_size(); ++i_attr)
|
||||
{
|
||||
const auto& a = node_proto.attribute(i_attr);
|
||||
if (a.name() == "nearest_mode" && a.has_s())
|
||||
layerParams.set("nearest_mode", String(a.s()));
|
||||
else if (a.name() == "exclude_outside" && a.has_i())
|
||||
layerParams.set("exclude_outside", static_cast<int>(a.i()) != 0);
|
||||
else if (a.name() == "cubic_coeff_a" && a.has_f())
|
||||
layerParams.set("cubic_coeff_a", static_cast<float>(a.f()));
|
||||
else if (a.name() == "extrapolation_value" && a.has_f())
|
||||
layerParams.set("extrapolation_value", static_cast<float>(a.f()));
|
||||
}
|
||||
|
||||
replaceLayerParam(layerParams, "mode", "interpolation");
|
||||
addLayer(layerParams, node_proto, ninputs);
|
||||
}
|
||||
@@ -2501,7 +2538,7 @@ void ONNXImporter2::buildDispatchMap_ONNX_AI(int opset_version)
|
||||
dispatch["GatherElements"] = &ONNXImporter2::parseGatherElements;
|
||||
dispatch["Concat"] = &ONNXImporter2::parseConcat;
|
||||
dispatch["If"] = &ONNXImporter2::parseIf;
|
||||
dispatch["Resize"] = &ONNXImporter2::parseResize;
|
||||
dispatch["Resize"] = &ONNXImporter2::parseResize2;
|
||||
dispatch["Size"] = &ONNXImporter2::parseSize;
|
||||
dispatch["Unique"] = &ONNXImporter2::parseUnique;
|
||||
dispatch["Trilu"] = &ONNXImporter2::parseTrilu;
|
||||
|
||||
@@ -1584,51 +1584,51 @@ CASE(test_reshape_zero_and_negative_dim)
|
||||
CASE(test_reshape_zero_dim)
|
||||
SKIP;
|
||||
CASE(test_resize_downsample_scales_cubic)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_downsample_scales_cubic_A_n0p5_exclude_outside)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_downsample_scales_cubic_align_corners)
|
||||
// no filter
|
||||
CASE(test_resize_downsample_scales_linear)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_downsample_scales_linear_align_corners)
|
||||
// no filter
|
||||
CASE(test_resize_downsample_scales_nearest)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_downsample_sizes_cubic)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_downsample_sizes_linear_pytorch_half_pixel)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_downsample_sizes_nearest)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_downsample_sizes_nearest_tf_half_pixel_for_nn)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_tf_crop_and_resize)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_upsample_scales_cubic)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_upsample_scales_cubic_A_n0p5_exclude_outside)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_upsample_scales_cubic_align_corners)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_upsample_scales_cubic_asymmetric)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_upsample_scales_linear)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_upsample_scales_linear_align_corners)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_upsample_scales_nearest)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_upsample_sizes_cubic)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_upsample_sizes_nearest)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_upsample_sizes_nearest_ceil_half_pixel)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_upsample_sizes_nearest_floor_align_corners)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_resize_upsample_sizes_nearest_round_prefer_ceil_asymmetric)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_reversesequence_batch)
|
||||
// no filter
|
||||
CASE(test_reversesequence_time)
|
||||
|
||||
@@ -145,3 +145,24 @@
|
||||
"test_unique_sorted_with_axis_3d",
|
||||
"test_unique_sorted_with_negative_axis",
|
||||
"test_unique_sorted_without_axis",
|
||||
"test_resize_downsample_scales_nearest",
|
||||
"test_resize_downsample_sizes_cubic",
|
||||
"test_resize_downsample_sizes_nearest",
|
||||
"test_resize_upsample_scales_cubic",
|
||||
"test_resize_upsample_scales_cubic_A_n0p5_exclude_outside",
|
||||
"test_resize_upsample_scales_cubic_align_corners",
|
||||
"test_resize_upsample_scales_cubic_asymmetric",
|
||||
"test_resize_upsample_scales_linear",
|
||||
"test_resize_upsample_scales_linear_align_corners",
|
||||
"test_resize_upsample_scales_nearest",
|
||||
"test_resize_upsample_sizes_cubic",
|
||||
"test_resize_upsample_sizes_nearest",
|
||||
"test_resize_upsample_sizes_nearest_ceil_half_pixel",
|
||||
"test_resize_upsample_sizes_nearest_floor_align_corners",
|
||||
"test_resize_upsample_sizes_nearest_round_prefer_ceil_asymmetric",
|
||||
"test_resize_downsample_scales_cubic",
|
||||
"test_resize_downsample_scales_cubic_A_n0p5_exclude_outside",
|
||||
"test_resize_downsample_scales_linear",
|
||||
"test_resize_downsample_sizes_linear_pytorch_half_pixel",
|
||||
"test_resize_downsample_sizes_nearest_tf_half_pixel_for_nn",
|
||||
"test_resize_tf_crop_and_resize",
|
||||
|
||||
@@ -158,29 +158,8 @@
|
||||
"test_reduce_sum_negative_axes_keepdims_example",
|
||||
"test_reduce_sum_negative_axes_keepdims_random", // ---- same as above ---
|
||||
"test_reshape_allowzero_reordered", // incompatible type of input tensor #0 'data': CV_8UC1 given, CV_32FC1 expected in function 'setGraphInput'
|
||||
"test_resize_downsample_scales_cubic", // Issue:: Parser: layer_id.find(node_proto.input(i)) == layer_id.end() in function 'parseResize'
|
||||
"test_resize_downsample_scales_cubic_A_n0p5_exclude_outside", // ---- same as above ---
|
||||
"test_resize_downsample_scales_cubic_align_corners", // ---- same as above ---
|
||||
"test_resize_downsample_scales_linear", // ---- same as above ---
|
||||
"test_resize_downsample_scales_linear_align_corners", // ---- same as above ---
|
||||
"test_resize_downsample_scales_nearest", // ---- same as above ---
|
||||
"test_resize_downsample_sizes_cubic", // ---- same as above ---
|
||||
"test_resize_downsample_sizes_linear_pytorch_half_pixel", // ---- same as above ---
|
||||
"test_resize_downsample_sizes_nearest", // ---- same as above ---
|
||||
"test_resize_downsample_sizes_nearest_tf_half_pixel_for_nn", // ---- same as above ---
|
||||
"test_resize_tf_crop_and_resize", // ---- same as above ---
|
||||
"test_resize_upsample_scales_cubic", // Issue:: Parser: layer_id.find(node_proto.input(i)) == layer_id.end() in function 'parseResize'
|
||||
"test_resize_upsample_scales_cubic_A_n0p5_exclude_outside", // ---- same as above ---
|
||||
"test_resize_upsample_scales_cubic_align_corners", // ---- same as above ---
|
||||
"test_resize_upsample_scales_cubic_asymmetric", // ---- same as above ---
|
||||
"test_resize_upsample_scales_linear", // ---- same as above ---
|
||||
"test_resize_upsample_scales_linear_align_corners", // ---- same as above ---
|
||||
"test_resize_upsample_scales_nearest", // ---- same as above ---
|
||||
"test_resize_upsample_sizes_cubic", // ---- same as above ---
|
||||
"test_resize_upsample_sizes_nearest", // ---- same as above ---
|
||||
"test_resize_upsample_sizes_nearest_ceil_half_pixel", // ---- same as above ---
|
||||
"test_resize_upsample_sizes_nearest_floor_align_corners", // ---- same as above ---
|
||||
"test_resize_upsample_sizes_nearest_round_prefer_ceil_asymmetric", // ---- same as above ---
|
||||
"test_reversesequence_batch", // Issue:: Parser: Can't create layer "onnx_node_output_0!y" of type "ReverseSequence" in function 'getLayerInstance'
|
||||
"test_reversesequence_time", // ---- same as above ---
|
||||
"test_rnn_seq_length", // Issue:: Parser: Can't create layer "onnx_node_output_1!Y_h" of type "RNN" in function 'getLayerInstance'
|
||||
|
||||
Reference in New Issue
Block a user