@@ -210,6 +210,22 @@ static void _reorderCandidatesCorners(vector< vector< Point2f > > &candidates) {
210
210
}
211
211
}
212
212
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
+ }
213
229
214
230
/* *
215
231
* @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
315
331
biggerContours.push_back (contoursIn[biggerIdx]);
316
332
317
333
if ( detectInvertedMarker ){
318
- smallerCandidates.push_back (candidatesIn[smallerIdx]);
334
+ smallerCandidates.push_back (alignContourOrder ( candidatesIn[biggerIdx][ 0 ], candidatesIn[ smallerIdx]) );
319
335
smallerContours.push_back (contoursIn[smallerIdx]);
320
336
}
321
337
}
@@ -550,7 +566,7 @@ static int _getBorderErrors(const Mat &bits, int markerSize, int borderSize) {
550
566
*/
551
567
static uint8_t _identifyOneCandidate (const Ptr<Dictionary>& dictionary, InputArray _image,
552
568
vector<Point2f>& _corners, int & idx,
553
- const Ptr<DetectorParameters>& params)
569
+ const Ptr<DetectorParameters>& params, int & rotation )
554
570
{
555
571
CV_Assert (_corners.size () == 4 );
556
572
CV_Assert (_image.getMat ().total () != 0 );
@@ -590,14 +606,9 @@ static uint8_t _identifyOneCandidate(const Ptr<Dictionary>& dictionary, InputArr
590
606
.colRange (params->markerBorderBits , candidateBits.rows - params->markerBorderBits );
591
607
592
608
// try to indentify the marker
593
- int rotation;
594
609
if (!dictionary->identify (onlyBits, idx, rotation, params->errorCorrectionRate ))
595
610
return 0 ;
596
611
597
- // shift corner positions to the correct rotation
598
- if (rotation != 0 ) {
599
- std::rotate (_corners.begin (), _corners.begin () + 4 - rotation, _corners.end ());
600
- }
601
612
return typ;
602
613
}
603
614
@@ -611,9 +622,10 @@ class IdentifyCandidatesParallel : public ParallelLoopBody {
611
622
IdentifyCandidatesParallel (const Mat& _grey, vector< vector< Point2f > >& _candidates,
612
623
const Ptr<Dictionary> &_dictionary,
613
624
vector< int >& _idsTmp, vector< uint8_t >& _validCandidates,
614
- const Ptr<DetectorParameters> &_params)
625
+ const Ptr<DetectorParameters> &_params,
626
+ vector< int > &_rotated)
615
627
: grey(_grey), candidates(_candidates), dictionary(_dictionary),
616
- idsTmp (_idsTmp), validCandidates(_validCandidates), params(_params) {}
628
+ idsTmp (_idsTmp), validCandidates(_validCandidates), params(_params), rotated(_rotated) {}
617
629
618
630
void operator ()(const Range &range) const CV_OVERRIDE
619
631
{
@@ -622,7 +634,7 @@ class IdentifyCandidatesParallel : public ParallelLoopBody {
622
634
623
635
for (int i = begin; i < end; i++) {
624
636
int currId;
625
- validCandidates[i] = _identifyOneCandidate (dictionary, grey, candidates[i], currId, params);
637
+ validCandidates[i] = _identifyOneCandidate (dictionary, grey, candidates[i], currId, params, rotated[i] );
626
638
627
639
if (validCandidates[i] > 0 )
628
640
idsTmp[i] = currId;
@@ -639,6 +651,7 @@ class IdentifyCandidatesParallel : public ParallelLoopBody {
639
651
vector< int > &idsTmp;
640
652
vector< uint8_t > &validCandidates;
641
653
const Ptr<DetectorParameters> ¶ms;
654
+ vector< int > &rotated;
642
655
};
643
656
644
657
@@ -676,7 +689,12 @@ static void _copyVector2Output(vector< vector< Point2f > > &vec, OutputArrayOfAr
676
689
}
677
690
}
678
691
679
-
692
+ /* *
693
+ * @brief rotate the initial corner to get to the right position
694
+ */
695
+ static void correctCornerPosition ( vector< Point2f >& _candidate, int rotate){
696
+ std::rotate (_candidate.begin (), _candidate.begin () + 4 - rotate, _candidate.end ());
697
+ }
680
698
681
699
/* *
682
700
* @brief Identify square candidates according to a marker dictionary
@@ -699,30 +717,32 @@ static void _identifyCandidates(InputArray _image, vector< vector< vector< Point
699
717
_convertToGrey (_image.getMat (), grey);
700
718
701
719
vector< int > idsTmp (ncandidates, -1 );
720
+ vector< int > rotated (ncandidates, 0 );
702
721
vector< uint8_t > validCandidates (ncandidates, 0 );
703
722
704
723
// // Analyze each of the candidates
705
724
parallel_for_ (Range (0 , ncandidates),
706
725
IdentifyCandidatesParallel (grey,
707
726
params->detectInvertedMarker ? _candidatesSet[1 ] : _candidatesSet[0 ],
708
727
_dictionary, idsTmp,
709
- validCandidates, params));
728
+ validCandidates, params, rotated ));
710
729
711
730
for (int i = 0 ; i < ncandidates; i++) {
712
731
if (validCandidates[i] > 0 ) {
713
- // add the white valid candidate
714
- if ( params->detectInvertedMarker && validCandidates[i] == 2 ){
715
- accepted.push_back (_candidatesSet[1 ][i]);
716
- ids.push_back (idsTmp[i]);
732
+ // to choose the right set of candidates :: 0 for default, 1 for white markers
733
+ uint8_t set = validCandidates[i]-1 ;
717
734
718
- contours.push_back (_contoursSet[1 ][i]);
735
+ // shift corner positions to the correct rotation
736
+ correctCornerPosition (_candidatesSet[set][i], rotated[i]);
737
+
738
+ if ( !params->detectInvertedMarker && validCandidates[i] == 2 )
719
739
continue ;
720
- }
721
- // add the default (black) valid candidate
722
- accepted.push_back (_candidatesSet[0 ][i]);
740
+
741
+ // add valid candidate
742
+ accepted.push_back (_candidatesSet[set ][i]);
723
743
ids.push_back (idsTmp[i]);
724
744
725
- contours.push_back (_contoursSet[0 ][i]);
745
+ contours.push_back (_contoursSet[set ][i]);
726
746
727
747
} else {
728
748
rejected.push_back (_candidatesSet[0 ][i]);
0 commit comments