@@ -717,4 +717,71 @@ TEST(CV_ArucoDetectMarkers, regression_2492)
717717 }
718718}
719719
720+ TEST (CV_ArucoDetectMarkers, number_of_threads_does_not_change_results)
721+ {
722+ auto params = cv::aruco::DetectorParameters::create ();
723+ // We are not testing against different dictionaries
724+ // As we are interested mostly in small images, smaller
725+ // markers is better -> 4x4
726+ cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary (cv::aruco::DICT_4X4_50);
727+
728+ // Height of the test image can be chosen quite freely
729+ // We aim to test against small images as in those the
730+ // number of threads has most effect
731+ const auto height_img = 20 ;
732+ // Just to get nice white boarder
733+ const int shift = height_img > 10 ? 5 : 1 ;
734+ const auto height_marker = height_img-2 *shift;
735+
736+ // Create a test image
737+ cv::Mat img_marker;
738+ cv::aruco::drawMarker (dictionary, 23 , height_marker, img_marker, 1 );
739+
740+ // Copy to bigger image to get a white border
741+ cv::Mat img (height_img, height_img, CV_8UC1);
742+ img.setTo (255 );
743+ img_marker.copyTo (img (cv::Rect (shift, shift, height_marker, height_marker)));
744+
745+ // Remember original number of threads
746+ const auto original_num_th = cv::getNumThreads ();
747+ for (const auto refinement_method : {cv::aruco::CORNER_REFINE_NONE, cv::aruco::CORNER_REFINE_SUBPIX,
748+ cv::aruco::CORNER_REFINE_CONTOUR, cv::aruco::CORNER_REFINE_APRILTAG})
749+ {
750+ params->cornerRefinementMethod = refinement_method;
751+
752+ std::vector<std::vector<cv::Point2f>> original_corners;
753+ std::vector<int > original_ids;
754+ for (const auto num_threads : {1 , 2 , 8 , 16 , 32 , height_img-1 , height_img, height_img+1 }) {
755+ cv::setNumThreads (num_threads);
756+
757+ std::vector<std::vector<cv::Point2f>> corners;
758+ std::vector<int > ids;
759+ cv::aruco::detectMarkers (img, dictionary, corners, ids, params);
760+
761+ // If we don't find any markers, the test is broken
762+ ASSERT_GE (ids.size (), 1 );
763+
764+ if (original_corners.empty ()) {
765+ original_corners = std::move (corners);
766+ original_ids = std::move (ids);
767+ } else {
768+ // Make sure we got the same result as the first time
769+ ASSERT_EQ (corners.size (), original_corners.size ());
770+ ASSERT_EQ (ids.size (), original_ids.size ());
771+ ASSERT_EQ (ids.size (), corners.size ());
772+ for (size_t i = 0 ; i < corners.size (); ++i) {
773+ EXPECT_EQ (ids[i], original_ids[i]);
774+ for (size_t j = 0 ; j < corners[i].size (); ++j) {
775+ EXPECT_NEAR (corners[i][j].x , original_corners[i][j].x , 0 .1f );
776+ EXPECT_NEAR (corners[i][j].y , original_corners[i][j].y , 0 .1f );
777+ }
778+ }
779+ }
780+ }
781+ }
782+
783+ // Reset number of threads
784+ cv::setNumThreads (original_num_th);
785+ }
786+
720787}} // namespace
0 commit comments