mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
Merge pull request #28121 from abhishek-gola:loop_layer_add
Add Loop layer to new DNN engine #28121 Addition of loop layer in 5.x for issue: https://github.com/opencv/opencv/issues/26179 and https://github.com/opencv/opencv/issues/26141 and https://github.com/opencv/opencv/issues/25200 OpenCV Extra: https://github.com/opencv/opencv_extra/pull/1335 ### 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:
@@ -978,4 +978,117 @@ TEST_P(Reproducibility_ResNet50_QDQ_ONNX, Accuracy)
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Reproducibility_ResNet50_QDQ_ONNX,
|
||||
testing::ValuesIn(getAvailableTargets(DNN_BACKEND_OPENCV)));
|
||||
|
||||
typedef testing::TestWithParam<Target> Reproducibility_MobileNetSSD_ONNX;
|
||||
TEST_P(Reproducibility_MobileNetSSD_ONNX, Accuracy)
|
||||
{
|
||||
Target targetId = GetParam();
|
||||
auto engine_forced = static_cast<EngineType>(
|
||||
cv::utils::getConfigurationParameterSizeT("OPENCV_FORCE_DNN_ENGINE", ENGINE_AUTO));
|
||||
if (engine_forced == ENGINE_CLASSIC)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_PARSER);
|
||||
return;
|
||||
}
|
||||
|
||||
applyTestTag(targetId == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB);
|
||||
ASSERT_TRUE(ocl::useOpenCL() || targetId == DNN_TARGET_CPU || targetId == DNN_TARGET_CPU_FP16);
|
||||
|
||||
std::string modelname = _tf("onnx/models/ssd_mobilenet_v1_12.onnx", false);
|
||||
Net net = readNetFromONNX(modelname);
|
||||
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
if (targetId == DNN_TARGET_CPU_FP16)
|
||||
net.enableWinograd(false);
|
||||
|
||||
std::string imgname = _tf("dog_orig_size.png");
|
||||
Mat image = imread(imgname);
|
||||
ASSERT_TRUE(!image.empty());
|
||||
Mat input;
|
||||
resize(image, input, Size(300, 300));
|
||||
int imsize[] = {1, input.rows, input.cols, 3};
|
||||
Mat input8dim4(4, imsize, CV_8U, input.data);
|
||||
|
||||
std::vector<String> outNames = net.getUnconnectedOutLayersNames();
|
||||
std::vector<Mat> outs;
|
||||
double min_t = 0;
|
||||
const int niters =
|
||||
#ifdef _DEBUG
|
||||
1;
|
||||
#else
|
||||
30;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < niters; i++) {
|
||||
double t = (double)getTickCount();
|
||||
net.setInput(input8dim4);
|
||||
net.forward(outs, outNames);
|
||||
t = (double)getTickCount() - t;
|
||||
min_t = i == 0 ? t : std::min(min_t, t);
|
||||
}
|
||||
printf("run time = %.2fms\n", min_t*1000./getTickFrequency());
|
||||
|
||||
// Model outputs: detection_boxes [1,N,4], detection_classes [1,N],
|
||||
// detection_scores [1,N], num_detections [1]
|
||||
ASSERT_EQ(outs.size(), (size_t)4);
|
||||
|
||||
Mat boxes, classes, scores, numDet;
|
||||
for (size_t i = 0; i < outs.size(); i++) {
|
||||
if (outs[i].dims == 3 && outs[i].size[2] == 4)
|
||||
boxes = outs[i];
|
||||
else if (outs[i].total() == 1)
|
||||
numDet = outs[i];
|
||||
else if (outs[i].dims == 2) {
|
||||
float first = outs[i].at<float>(0, 0);
|
||||
if (first == std::round(first) && first > 0)
|
||||
classes = outs[i];
|
||||
else
|
||||
scores = outs[i];
|
||||
}
|
||||
}
|
||||
ASSERT_FALSE(boxes.empty());
|
||||
ASSERT_FALSE(scores.empty());
|
||||
ASSERT_FALSE(classes.empty());
|
||||
ASSERT_FALSE(numDet.empty());
|
||||
|
||||
int ndet = (int)numDet.at<float>(0);
|
||||
printf("num_detections = %d\n", ndet);
|
||||
ASSERT_GT(ndet, 0);
|
||||
|
||||
// Build test detection vectors from model outputs
|
||||
// Model boxes are normalized (y1, x1, y2, x2) — convert to Rect2d(x, y, w, h)
|
||||
std::vector<int> testClassIds;
|
||||
std::vector<float> testScores;
|
||||
std::vector<Rect2d> testBoxes;
|
||||
for (int j = 0; j < ndet; j++) {
|
||||
testClassIds.push_back((int)classes.at<float>(0, j));
|
||||
testScores.push_back(scores.at<float>(0, j));
|
||||
float y1 = boxes.at<float>(0, j, 0);
|
||||
float x1 = boxes.at<float>(0, j, 1);
|
||||
float y2 = boxes.at<float>(0, j, 2);
|
||||
float x2 = boxes.at<float>(0, j, 3);
|
||||
testBoxes.push_back(Rect2d(x1, y1, x2 - x1, y2 - y1));
|
||||
}
|
||||
|
||||
// Reference detections for dog_orig_size.png
|
||||
// COCO 1-indexed: 2=bicycle, 3=car, 18=dog
|
||||
std::vector<int> refClassIds = {2, 18, 3};
|
||||
std::vector<float> refScores = {0.944377f, 0.877805f, 0.787824f};
|
||||
std::vector<Rect2d> refBoxes = {
|
||||
Rect2d(0.157917, 0.219984, 0.742909 - 0.157917, 0.739280 - 0.219984), // bicycle
|
||||
Rect2d(0.168082, 0.360803, 0.426304 - 0.168082, 0.919625 - 0.360803), // dog
|
||||
Rect2d(0.600506, 0.114612, 0.899101 - 0.600506, 0.298757 - 0.114612), // car
|
||||
};
|
||||
|
||||
float confThreshold = 0.5f;
|
||||
double scoreDiff = 0.1;
|
||||
double iouDiff = 0.05;
|
||||
normAssertDetections(refClassIds, refScores, refBoxes,
|
||||
testClassIds, testScores, testBoxes,
|
||||
"", confThreshold, scoreDiff, iouDiff);
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Reproducibility_MobileNetSSD_ONNX,
|
||||
testing::ValuesIn(getAvailableTargets(DNN_BACKEND_OPENCV)));
|
||||
|
||||
}} // namespace
|
||||
|
||||
Reference in New Issue
Block a user