From 14a475aa0b37c54fd6136524a1ea228a0434a22d Mon Sep 17 00:00:00 2001 From: omrope79 Date: Sat, 30 May 2026 19:37:34 +0530 Subject: [PATCH] Merge pull request #28746 from omrope79:wechat-fix WeChatQR-fix conversion Caffe to ONNX #28746 ### 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 --- .../dnn/src/layers/nary_eltwise_layers.cpp | 45 ++++++++++++++++++- modules/dnn/src/layers/prior_box_layer.cpp | 8 ++++ modules/dnn/src/layers/reshape2_layer.cpp | 6 ++- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/modules/dnn/src/layers/nary_eltwise_layers.cpp b/modules/dnn/src/layers/nary_eltwise_layers.cpp index d244fd6f81..dce9b75bc5 100644 --- a/modules/dnn/src/layers/nary_eltwise_layers.cpp +++ b/modules/dnn/src/layers/nary_eltwise_layers.cpp @@ -322,8 +322,13 @@ public: for (int j = 0; j < maxdims; j++) { int inpsz = j < delta ? 1 : inpShape[j - delta]; int outsz = outShape[j]; - CV_Assert(inpsz == outsz || inpsz == 1 || outsz == 1); - outShape[j] = inpsz != 1 ? inpsz : outsz; + if (inpsz == outsz || inpsz == 1 || outsz == 1) { + outShape[j] = inpsz != 1 ? inpsz : outsz; + } else { + // Clamp to minimum to tolerate off-by-1 spatial mismatches from Caffe→ONNX export. + CV_LOG_WARNING(NULL, "NaryEltwiseLayer: Shape mismatch detected at dimension " << j << " (" << inpsz << " vs " << outsz << "). Clamping to " << std::min(inpsz, outsz) << "."); + outShape[j] = std::min(inpsz, outsz); + } } } @@ -928,6 +933,42 @@ public: } std::vector used_inputs = inputs; + + const Mat& out0 = outputs[0]; + bool needsCrop = false; + for (const auto& inp : used_inputs) { + int delta = out0.dims - inp.dims; + for (int d = 0; d < inp.dims; d++) { + int od = d + delta; + if (od >= 0 && inp.size[d] > 1 && out0.size[od] > 1 && + inp.size[d] != out0.size[od]) { + needsCrop = true; break; + } + } + if (needsCrop) break; + } + if (needsCrop) { + std::vector ranges; + for (size_t k = 0; k < used_inputs.size(); k++) { + Mat& inp = used_inputs[k]; + int delta = out0.dims - inp.dims; + bool modified = false; + ranges.assign(inp.dims, Range::all()); + for (int d = 0; d < inp.dims; d++) { + int od = d + delta; + if (od >= 0 && inp.size[d] > out0.size[od] && + inp.size[d] > 1 && out0.size[od] > 1) { + ranges[d] = Range(0, out0.size[od]); + modified = true; + } + } + if (modified) + inp = inp(ranges).clone(); + } + helper.init(used_inputs, outputs); + CV_CheckTrue(helper.prepare_for_broadcast_op(), "NaryEltwiseLayer: Preparation for broadcasting failed"); + } + if (op == OPERATION::POW) { CV_Assert(used_inputs.size() == 2); const int out_type = outputs[0].type(); diff --git a/modules/dnn/src/layers/prior_box_layer.cpp b/modules/dnn/src/layers/prior_box_layer.cpp index 4341bfa1df..c10d33a64a 100644 --- a/modules/dnn/src/layers/prior_box_layer.cpp +++ b/modules/dnn/src/layers/prior_box_layer.cpp @@ -203,6 +203,14 @@ public: remap("min_sizes", "min_size"); remap("max_sizes", "max_size"); remap("aspect_ratios", "aspect_ratio"); + + if (p.has("steps") && !p.has("step_h") && !p.has("step_w")) { + DictValue steps = p.get("steps"); + if (steps.size() == 2) { + p.set("step_h", steps.get(0)); + p.set("step_w", steps.get(1)); + } + } return p; } diff --git a/modules/dnn/src/layers/reshape2_layer.cpp b/modules/dnn/src/layers/reshape2_layer.cpp index 904d5c558b..8667d2dd8c 100644 --- a/modules/dnn/src/layers/reshape2_layer.cpp +++ b/modules/dnn/src/layers/reshape2_layer.cpp @@ -171,7 +171,11 @@ public: int64_t autoSize = inpTotal/outTotal; CV_Assert(autoSize <= INT_MAX && autoSize*outTotal == inpTotal); outShape[m1idx] = (int)autoSize; - } else { + } + else if (outTotal != inpTotal && ndims == 2 && outShape[0] == 1 && outShape[1] > 0) { + outShape[1] = (int)(inpTotal / outShape[0]); + } + else { CV_Assert(outTotal == inpTotal); }