From 848dd12a1f9741c4411ece19f86470ab426347bf Mon Sep 17 00:00:00 2001 From: skycat8 <39569266+skycat8@users.noreply.github.com> Date: Fri, 24 Nov 2023 10:36:06 +0300 Subject: [PATCH] Merge pull request #24553 from skycat8:yolov5 Add yolov5n to tests #24553 ### 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 --- modules/dnn/test/test_onnx_importer.cpp | 103 ++++++++++++++---------- 1 file changed, 62 insertions(+), 41 deletions(-) diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index 8246ff7dec..042ad1e87c 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -2605,28 +2605,15 @@ TEST_P(Test_ONNX_layers, CumSum) testONNXModels("cumsum_3d_dim_2"); } -// This test is mainly to test: -// 1. identity node with constant input -// 2. limited support to range operator (all inputs are constant) -// 3. parseExpand with multiple broadcast axes -// 4. 1D mat dimension issue with the output of range operator -TEST_P(Test_ONNX_layers, YOLOv7) +static void testYOLO(const std::string& weightPath, const std::vector& refClassIds, + const std::vector& refScores, const std::vector& refBoxes) { - std::string weightPath = _tf("models/yolov7_not_simplified.onnx", false); std::string imgPath = _tf("../dog_orig_size.png"); Size targetSize{640, 640}; float conf_threshold = 0.3; float iou_threshold = 0.5; - // Reference, which is collected with input size of 640x640 - std::vector refClassIds{1, 16, 7}; - std::vector refScores{0.9614331f, 0.9589417f, 0.8679074f}; - // [x1, y1, x2, y2] x 3 - std::vector refBoxes{Rect2d(105.973236f, 150.16716f, 472.59012f, 466.48834f), - Rect2d(109.97953f, 246.17862f, 259.83676f, 600.76624f), - Rect2d(385.96185f, 83.02809f, 576.07355f, 189.82793f)}; - Mat img = imread(imgPath); Mat inp = blobFromImage(img, 1/255.0, targetSize, Scalar(0, 0, 0), true, false); @@ -2636,40 +2623,42 @@ TEST_P(Test_ONNX_layers, YOLOv7) std::vector outs; net.forward(outs, net.getUnconnectedOutLayersNames()); - Mat preds = outs[3].reshape(1, outs[3].size[1]); // [1, 25200, 85] - // Retrieve std::vector classIds; std::vector confidences; std::vector boxes; // each row is [cx, cy, w, h, conf_obj, conf_class1, ..., conf_class80] - for (int i = 0; i < preds.rows; ++i) + for (auto preds : outs) { - // filter out non objects - float obj_conf = preds.row(i).at(4); - if (obj_conf < conf_threshold) - continue; + preds = preds.reshape(1, preds.size[1]); + for (int i = 0; i < preds.rows; ++i) + { + // filter out non objects + float obj_conf = preds.row(i).at(4); + if (obj_conf < conf_threshold) + continue; - // get class id and conf - Mat scores = preds.row(i).colRange(5, preds.cols); - double conf; - Point maxLoc; - minMaxLoc(scores, 0, &conf, 0, &maxLoc); - conf *= obj_conf; - if (conf < conf_threshold) - continue; + // get class id and conf + Mat scores = preds.row(i).colRange(5, preds.cols); + double conf; + Point maxLoc; + minMaxLoc(scores, 0, &conf, 0, &maxLoc); + conf *= obj_conf; + if (conf < conf_threshold) + continue; - // get bbox coords - float* det = preds.ptr(i); - double cx = det[0]; - double cy = det[1]; - double w = det[2]; - double h = det[3]; - // [x1, y1, x2, y2] - boxes.push_back(Rect2d(cx - 0.5 * w, cy - 0.5 * h, - cx + 0.5 * w, cy + 0.5 * h)); - classIds.push_back(maxLoc.x); - confidences.push_back(conf); + // get bbox coords + float* det = preds.ptr(i); + double cx = det[0]; + double cy = det[1]; + double w = det[2]; + double h = det[3]; + // [x1, y1, x2, y2] + boxes.push_back(Rect2d(cx - 0.5 * w, cy - 0.5 * h, + cx + 0.5 * w, cy + 0.5 * h)); + classIds.push_back(maxLoc.x); + confidences.push_back(conf); + } } // NMS @@ -2689,6 +2678,38 @@ TEST_P(Test_ONNX_layers, YOLOv7) normAssertDetections(refClassIds, refScores, refBoxes, keep_classIds, keep_confidences, keep_boxes); } +// This test is mainly to test: +// 1. identity node with constant input +// 2. limited support to range operator (all inputs are constant) +// 3. parseExpand with multiple broadcast axes +// 4. 1D mat dimension issue with the output of range operator +TEST_P(Test_ONNX_nets, YOLOv7) +{ + std::string weightPath = _tf("models/yolov7_not_simplified.onnx", false); + // Reference, which is collected with input size of 640x640 + std::vector refClassIds{1, 16, 7}; + std::vector refScores{0.9614331f, 0.9589417f, 0.8679074f}; + // [x1, y1, x2, y2] x 3 + std::vector refBoxes{Rect2d(105.973236f, 150.16716f, 472.59012f, 466.48834f), + Rect2d(109.97953f, 246.17862f, 259.83676f, 600.76624f), + Rect2d(385.96185f, 83.02809f, 576.07355f, 189.82793f)}; + testYOLO(weightPath, refClassIds, refScores, refBoxes); +} + +TEST_P(Test_ONNX_nets, YOLOv5n) +{ + std::string weightPath = findDataFile("dnn/yolov5n.onnx", false); + // Reference, which is collected with input size of 640x640 + std::vector refClassIds{16, 2, 1}; + std::vector refScores{0.749053f, 0.616853f, 0.32506f}; + // [x1, y1, x2, y2] x 4 + + std::vector refBoxes{Rect2d(108.088f, 239.293f, 266.196f, 607.658f), + Rect2d(392.028f, 89.9233f, 579.152f, 190.447f), + Rect2d(120.278f, 159.76, 214.481f, 241.473f)}; + testYOLO(weightPath, refClassIds, refScores, refBoxes); +} + TEST_P(Test_ONNX_layers, Tile) { testONNXModels("tile", pb);