mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
Merge pull request #28749 from Prasadayus:NMS-empty-detection-fix
Nms empty detection fix #28749 Requires opencv_extra: https://github.com/opencv/opencv_extra/pull/1330 ### 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:
committed by
GitHub
parent
e59506bbf5
commit
47ac80995f
@@ -867,6 +867,8 @@ void broadcast(InputArray _src, InputArray _shape, OutputArray _dst) {
|
||||
// impl
|
||||
_dst.create(dims_shape, shape.ptr<int>(), src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
if (dst.total() == 0)
|
||||
return;
|
||||
std::vector<int> is_same_shape(dims_shape, 0);
|
||||
for (int i = 0; i < static_cast<int>(shape_src.size()); ++i) {
|
||||
if (shape_src[i] == ptr_shape[i]) {
|
||||
|
||||
@@ -311,20 +311,30 @@ void reshapeAndCopyFirst(InputArrayOfArrays inputs,
|
||||
int inpType = inputs.type(0);
|
||||
if (inpKind == _InputArray::STD_VECTOR_MAT) {
|
||||
Mat inp = inputs.getMat(0);
|
||||
MatShape inpShape = inp.shape();
|
||||
const size_t inpTotal = inpShape.total();
|
||||
const size_t outTotal = shape.total();
|
||||
std::vector<Mat>& outref = outputs.getMatVecRef();
|
||||
outref.resize(1);
|
||||
outref[0].fit(shape, inpType);
|
||||
CV_Assert(outref[0].isContinuous());
|
||||
if (inpTotal == 0 && outTotal == 0)
|
||||
return;
|
||||
Mat inp_ = inp.reshape(0, shape);
|
||||
if (inp_.data != outref[0].data)
|
||||
inp_.copyTo(outref[0]);
|
||||
}
|
||||
else {
|
||||
UMat inp = inputs.getUMat(0);
|
||||
MatShape inpShape = inputs.shape(0);
|
||||
const size_t inpTotal = inpShape.total();
|
||||
const size_t outTotal = shape.total();
|
||||
std::vector<UMat>& outref = outputs.getUMatVecRef();
|
||||
outref.resize(1);
|
||||
outref[0].fit(shape, inpType);
|
||||
CV_Assert(outref[0].isContinuous());
|
||||
if (inpTotal == 0 && outTotal == 0)
|
||||
return;
|
||||
UMat inp_ = inp.reshape(0, shape);
|
||||
inp_.copyTo(outref[0]);
|
||||
}
|
||||
|
||||
@@ -129,6 +129,11 @@ public:
|
||||
outMat = outputs_arr.getMatRef(0);
|
||||
}
|
||||
|
||||
if (K == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto* out = outMat.ptr<int64_t>();
|
||||
std::vector<int> offsets(tasks + 1, 0);
|
||||
for (int t = 0; t < tasks; ++t)
|
||||
|
||||
@@ -1147,7 +1147,7 @@ void Net::Impl::forwardGraph(Ptr<Graph>& graph, InputArrayOfArrays inputs_,
|
||||
buf.type() == m.type(),
|
||||
(!m.u || m.u->data == outOrigData[i].first),
|
||||
(!m.u || m.u->size == outOrigData[i].second));
|
||||
} else if (!buf.u || m.u->size > buf.u->size) {
|
||||
} else if (!buf.u || (m.u && m.u->size > buf.u->size)) {
|
||||
buf = m;
|
||||
} else {
|
||||
// this branch means that the layer still calls
|
||||
|
||||
@@ -2641,6 +2641,10 @@ void ONNXImporter2::parseAttentionOnnxAi(LayerParams& params, const opencv_onnx:
|
||||
void ONNXImporter2::parseRoiAlign(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "RoiAlign";
|
||||
if (!layerParams.has("coordinate_transformation_mode")) {
|
||||
int onnx_opset = onnx_opset_map.count(str_domain_ai_onnx) ? onnx_opset_map.at(str_domain_ai_onnx) : 16;
|
||||
layerParams.set("coordinate_transformation_mode", onnx_opset < 16 ? "output_half_pixel" : "half_pixel");
|
||||
}
|
||||
addLayer(layerParams, node_proto, 3);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include "npy_blob.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
@@ -104,4 +105,32 @@ TEST(SoftNMS, Accuracy)
|
||||
}
|
||||
}
|
||||
|
||||
// Test NMS -> Reshape with zero detections using ONNX model.
|
||||
// NMS with dynamic output shapes is only supported by the new engine.
|
||||
TEST(NMS, ZeroDetections_Reshape)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
std::string onnxmodel = findDataFile("dnn/onnx/models/nms_reshape_empty.onnx");
|
||||
cv::dnn::Net net = cv::dnn::readNetFromONNX(onnxmodel);
|
||||
ASSERT_FALSE(net.empty());
|
||||
|
||||
Mat boxes = blobFromNPY(findDataFile("dnn/onnx/data/input_nms_reshape_empty_0.npy"));
|
||||
Mat scores = blobFromNPY(findDataFile("dnn/onnx/data/input_nms_reshape_empty_1.npy"));
|
||||
net.setInput(boxes, "boxes");
|
||||
net.setInput(scores, "scores");
|
||||
|
||||
std::vector<Mat> outs;
|
||||
net.forward(outs, std::vector<String>{"output"});
|
||||
ASSERT_EQ(outs.size(), (size_t)1);
|
||||
Mat ref = blobFromNPY(findDataFile("dnn/onnx/data/output_nms_reshape_empty.npy"));
|
||||
normAssert(ref, outs[0], "NMS_ZeroDetections_Reshape");
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
Reference in New Issue
Block a user