@@ -210,6 +210,22 @@ static void _reorderCandidatesCorners(vector< vector< Point2f > > &candidates) {
210210 }
211211}
212212
213+ /* *
214+ * @brief to make sure that the corner's order of both candidates (default/white) is the same
215+ */
216+ static vector< Point2f > alignContourOrder ( Point2f corner, vector< Point2f > candidate){
217+ uint8_t r=0 ;
218+ double min = cv::norm ( Vec2f ( corner - candidate[0 ] ), NORM_L2SQR);
219+ for (uint8_t pos=1 ; pos < 4 ; pos++) {
220+ double nDiff = cv::norm ( Vec2f ( corner - candidate[pos] ), NORM_L2SQR);
221+ if (nDiff < min){
222+ r = pos;
223+ min =nDiff;
224+ }
225+ }
226+ std::rotate (candidate.begin (), candidate.begin () + r, candidate.end ());
227+ return candidate;
228+ }
213229
214230/* *
215231 * @brief Check candidates that are too close to each other, save the potential candidates
@@ -315,7 +331,7 @@ static void _filterTooCloseCandidates(const vector< vector< Point2f > > &candida
315331 biggerContours.push_back (contoursIn[biggerIdx]);
316332
317333 if ( detectInvertedMarker ){
318- smallerCandidates.push_back (candidatesIn[smallerIdx]);
334+ smallerCandidates.push_back (alignContourOrder ( candidatesIn[biggerIdx][ 0 ], candidatesIn[ smallerIdx]) );
319335 smallerContours.push_back (contoursIn[smallerIdx]);
320336 }
321337 }
@@ -509,7 +525,7 @@ static int _getBorderErrors(const Mat &bits, int markerSize, int borderSize) {
509525 */
510526static uint8_t _identifyOneCandidate (const Ptr<Dictionary>& dictionary, InputArray _image,
511527 vector<Point2f>& _corners, int & idx,
512- const Ptr<DetectorParameters>& params)
528+ const Ptr<DetectorParameters>& params, int & rotation )
513529{
514530 CV_Assert (_corners.size () == 4 );
515531 CV_Assert (_image.getMat ().total () != 0 );
@@ -549,14 +565,9 @@ static uint8_t _identifyOneCandidate(const Ptr<Dictionary>& dictionary, InputArr
549565 .colRange (params->markerBorderBits , candidateBits.rows - params->markerBorderBits );
550566
551567 // try to indentify the marker
552- int rotation;
553568 if (!dictionary->identify (onlyBits, idx, rotation, params->errorCorrectionRate ))
554569 return 0 ;
555570
556- // shift corner positions to the correct rotation
557- if (rotation != 0 ) {
558- std::rotate (_corners.begin (), _corners.begin () + 4 - rotation, _corners.end ());
559- }
560571 return typ;
561572}
562573
@@ -593,7 +604,12 @@ static void _copyVector2Output(vector< vector< Point2f > > &vec, OutputArrayOfAr
593604 }
594605}
595606
596-
607+ /* *
608+ * @brief rotate the initial corner to get to the right position
609+ */
610+ static void correctCornerPosition ( vector< Point2f >& _candidate, int rotate){
611+ std::rotate (_candidate.begin (), _candidate.begin () + 4 - rotate, _candidate.end ());
612+ }
597613
598614/* *
599615 * @brief Identify square candidates according to a marker dictionary
@@ -616,6 +632,7 @@ static void _identifyCandidates(InputArray _image, vector< vector< vector< Point
616632 _convertToGrey (_image.getMat (), grey);
617633
618634 vector< int > idsTmp (ncandidates, -1 );
635+ vector< int > rotated (ncandidates, 0 );
619636 vector< uint8_t > validCandidates (ncandidates, 0 );
620637
621638 // // Analyze each of the candidates
@@ -627,7 +644,7 @@ static void _identifyCandidates(InputArray _image, vector< vector< vector< Point
627644
628645 for (int i = begin; i < end; i++) {
629646 int currId;
630- validCandidates[i] = _identifyOneCandidate (_dictionary, grey, candidates[i], currId, params);
647+ validCandidates[i] = _identifyOneCandidate (_dictionary, grey, candidates[i], currId, params, rotated[i] );
631648
632649 if (validCandidates[i] > 0 )
633650 idsTmp[i] = currId;
@@ -636,19 +653,20 @@ static void _identifyCandidates(InputArray _image, vector< vector< vector< Point
636653
637654 for (int i = 0 ; i < ncandidates; i++) {
638655 if (validCandidates[i] > 0 ) {
639- // add the white valid candidate
640- if ( params->detectInvertedMarker && validCandidates[i] == 2 ){
641- accepted.push_back (_candidatesSet[1 ][i]);
642- ids.push_back (idsTmp[i]);
656+ // to choose the right set of candidates :: 0 for default, 1 for white markers
657+ uint8_t set = validCandidates[i]-1 ;
643658
644- contours.push_back (_contoursSet[1 ][i]);
659+ // shift corner positions to the correct rotation
660+ correctCornerPosition (_candidatesSet[set][i], rotated[i]);
661+
662+ if ( !params->detectInvertedMarker && validCandidates[i] == 2 )
645663 continue ;
646- }
647- // add the default (black) valid candidate
648- accepted.push_back (_candidatesSet[0 ][i]);
664+
665+ // add valid candidate
666+ accepted.push_back (_candidatesSet[set ][i]);
649667 ids.push_back (idsTmp[i]);
650668
651- contours.push_back (_contoursSet[0 ][i]);
669+ contours.push_back (_contoursSet[set ][i]);
652670
653671 } else {
654672 rejected.push_back (_candidatesSet[0 ][i]);
0 commit comments