@@ -182,12 +182,29 @@ static void getSyntheticRT(double yaw, double pitch, double distance, Mat &rvec,
182182 */  
183183static  Mat projectMarker (Ptr<aruco::Dictionary> &dictionary, int  id, Mat cameraMatrix, double  yaw,
184184                         double  pitch, double  distance, Size imageSize, int  markerBorder,
185-                          vector< Point2f > &corners) {
185+                          vector< Point2f > &corners,  int  encloseMarker= 0 ) {
186186
187187    //  canonical image
188-     Mat markerImg;
188+     Mat marker,  markerImg;
189189    const  int  markerSizePixels = 100 ;
190-     aruco::drawMarker (dictionary, id, markerSizePixels, markerImg, markerBorder);
190+ 
191+     aruco::drawMarker (dictionary, id, markerSizePixels, marker, markerBorder);
192+     marker.copyTo (markerImg);
193+ 
194+     if (encloseMarker){ // to enclose the marker
195+         int  enclose = int (marker.rows /4 );
196+         markerImg = Mat::zeros (marker.rows +(2 *enclose), marker.cols +(enclose*2 ), CV_8UC1);
197+ 
198+         Mat field= markerImg.rowRange (int (enclose), int (markerImg.rows -enclose))
199+                             .colRange (int (0 ), int (markerImg.cols ));
200+         field.setTo (255 );
201+         field= markerImg.rowRange (int (0 ), int (markerImg.rows ))
202+                             .colRange (int (enclose), int (markerImg.cols -enclose));
203+         field.setTo (255 );
204+ 
205+         field = markerImg (Rect (enclose,enclose,marker.rows ,marker.cols ));
206+         marker.copyTo (field);
207+     }
191208
192209    //  get rvec and tvec for the perspective
193210    Mat rvec, tvec;
@@ -205,10 +222,10 @@ static Mat projectMarker(Ptr<aruco::Dictionary> &dictionary, int id, Mat cameraM
205222    projectPoints (markerObjPoints, rvec, tvec, cameraMatrix, distCoeffs, corners);
206223
207224    vector< Point2f > originalCorners;
208-     originalCorners.push_back (Point2f (0 , 0 ));
209-     originalCorners.push_back (Point2f ((float )markerSizePixels, 0 ));
210-     originalCorners.push_back (Point2f ((float )markerSizePixels, (float )markerSizePixels));
211-     originalCorners.push_back (Point2f (0 , (float )markerSizePixels));
225+     originalCorners.push_back (Point2f (0 + float (encloseMarker*markerSizePixels/ 4 ) , 0 + float (encloseMarker*markerSizePixels/ 4 ) ));
226+     originalCorners.push_back (originalCorners[ 0 ]+ Point2f ((float )markerSizePixels, 0 ));
227+     originalCorners.push_back (originalCorners[ 0 ]+ Point2f ((float )markerSizePixels, (float )markerSizePixels));
228+     originalCorners.push_back (originalCorners[ 0 ]+ Point2f (0 , (float )markerSizePixels));
212229
213230    Mat transformation = getPerspectiveTransform (originalCorners, corners);
214231
@@ -238,6 +255,11 @@ class CV_ArucoDetectionPerspective : public cvtest::BaseTest {
238255    public: 
239256    CV_ArucoDetectionPerspective ();
240257
258+     enum  checkWithParameter{
259+         USE_APRILTAG=1 ,             // / Detect marker candidates :: using AprilTag
260+         DETECT_INVERTED_MARKER,     // / Check if there is a white marker
261+     };
262+ 
241263    protected: 
242264    void  run (int );
243265};
@@ -246,9 +268,10 @@ class CV_ArucoDetectionPerspective : public cvtest::BaseTest {
246268CV_ArucoDetectionPerspective::CV_ArucoDetectionPerspective () {}
247269
248270
249- void  CV_ArucoDetectionPerspective::run (int  aprilDecimate ) {
271+ void  CV_ArucoDetectionPerspective::run (int  tryWith ) {
250272
251273    int  iter = 0 ;
274+     int  szEnclosed = 0 ;
252275    Mat cameraMatrix = Mat::eye (3 , 3 , CV_64FC1);
253276    Size imgSize (500 , 500 );
254277    cameraMatrix.at < double  >(0 , 0 ) = cameraMatrix.at < double  >(1 , 1 ) = 650 ;
@@ -257,29 +280,35 @@ void CV_ArucoDetectionPerspective::run(int aprilDecimate) {
257280    Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary (aruco::DICT_6X6_250);
258281
259282    //  detect from different positions
260-     for (double  distance = 0.1 ; distance <=  0.5  ; distance += 0.2 ) {
261-         for (int  pitch = 0 ; pitch < 360 ; pitch += 60 ) {
262-             for (int  yaw = 30 ; yaw <= 90 ; yaw += 50 )  {
283+     for (double  distance = 0.1 ; distance < 0.7  ; distance += 0.2 ) {
284+         for (int  pitch = 0 ; pitch < 360 ; pitch += (distance ==  0.1 ?  60 : 180 ) ) {
285+             for (int  yaw = 70 ; yaw <= 120 ; yaw += 40 ) {
263286                int  currentId = iter % 250 ;
264287                int  markerBorder = iter % 2  + 1 ;
265288                iter++;
266289                vector< Point2f > groundTruthCorners;
267-                 //  create synthetic image
268-                 Mat img =
269-                     projectMarker (dictionary, currentId, cameraMatrix, deg2rad (yaw), deg2rad (pitch),
270-                                   distance, imgSize, markerBorder, groundTruthCorners);
271290
272-                 //  detect markers
273-                 vector< vector< Point2f > > corners;
274-                 vector< int  > ids;
275291                Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create ();
276292                params->minDistanceToBorder  = 1 ;
277293                params->markerBorderBits  = markerBorder;
278294
279-                 if (aprilDecimate == 1 ){
280-                         params->cornerRefinementMethod  = cv::aruco::CORNER_REFINE_APRILTAG;
295+                 // / create synthetic image
296+                 Mat img=
297+                     projectMarker (dictionary, currentId, cameraMatrix, deg2rad (yaw), deg2rad (pitch),
298+                                       distance, imgSize, markerBorder, groundTruthCorners, szEnclosed);
299+                 //  marker :: Inverted
300+                 if (CV_ArucoDetectionPerspective::DETECT_INVERTED_MARKER == tryWith){
301+                     img = ~img;
302+                     params->detectInvertedMarker  = true ;
303+                 }
304+ 
305+                 if (CV_ArucoDetectionPerspective::USE_APRILTAG == tryWith){
306+                     params->cornerRefinementMethod  = cv::aruco::CORNER_REFINE_APRILTAG;
281307                }
282308
309+                 //  detect markers
310+                 vector< vector< Point2f > > corners;
311+                 vector< int  > ids;
283312                aruco::detectMarkers (img, dictionary, corners, ids, params);
284313
285314                //  check results
@@ -293,14 +322,33 @@ void CV_ArucoDetectionPerspective::run(int aprilDecimate) {
293322                }
294323                for (int  c = 0 ; c < 4 ; c++) {
295324                    double  dist = cv::norm (groundTruthCorners[c] - corners[0 ][c]);  //  TODO cvtest
296-                     if (dist > 5 ) {
297-                         ts->printf (cvtest::TS::LOG, " Incorrect marker corners position" 
298-                         ts->set_failed_test_info (cvtest::TS::FAIL_BAD_ACCURACY);
299-                         return ;
325+                     if (CV_ArucoDetectionPerspective::DETECT_INVERTED_MARKER == tryWith){
326+                         if (szEnclosed && dist > 3 ){
327+                             ts->printf (cvtest::TS::LOG, " Incorrect marker corners position" 
328+                             ts->set_failed_test_info (cvtest::TS::FAIL_BAD_ACCURACY);
329+                             return ;
330+                         }
331+                         if (!szEnclosed && dist >15 ){
332+                             ts->printf (cvtest::TS::LOG, " Incorrect marker corners position" 
333+                             ts->set_failed_test_info (cvtest::TS::FAIL_BAD_ACCURACY);
334+                             return ;
335+                         }
336+                     }
337+                     else {
338+                         if (dist > 5 ) {
339+                             ts->printf (cvtest::TS::LOG, " Incorrect marker corners position" 
340+                             ts->set_failed_test_info (cvtest::TS::FAIL_BAD_ACCURACY);
341+                             return ;
342+                         }
300343                    }
301344                }
302345            }
303346        }
347+         //  change the state :: to detect an enclosed inverted marker
348+         if ( CV_ArucoDetectionPerspective::DETECT_INVERTED_MARKER == tryWith && distance == 0.1  ){
349+             distance -= 0.1 ;
350+             szEnclosed++;
351+         }
304352    }
305353}
306354
@@ -488,10 +536,16 @@ void CV_ArucoBitCorrection::run(int) {
488536}
489537
490538typedef  CV_ArucoDetectionPerspective CV_AprilTagDetectionPerspective;
539+ typedef  CV_ArucoDetectionPerspective CV_InvertedArucoDetectionPerspective;
540+ 
541+ TEST (CV_InvertedArucoDetectionPerspective, algorithmic) {
542+     CV_InvertedArucoDetectionPerspective test;
543+     test.safe_run (CV_ArucoDetectionPerspective::DETECT_INVERTED_MARKER);
544+ }
491545
492546TEST (CV_AprilTagDetectionPerspective, algorithmic) {
493547    CV_AprilTagDetectionPerspective test;
494-     test.safe_run (1 );
548+     test.safe_run (CV_ArucoDetectionPerspective::USE_APRILTAG );
495549}
496550
497551TEST (CV_ArucoDetectionSimple, algorithmic) {
0 commit comments