Skip to content

Commit ef5a7e8

Browse files
author
Alexander Panov
authored
Merge pull request opencv#3201 from AleksandrPanov:fix_filterTooCloseCandidates
* fix search for one contour in _filterTooCloseCandidates() * add regression_3192 test * add regression_2492 test
1 parent 56d492c commit ef5a7e8

File tree

3 files changed

+86
-4
lines changed

3 files changed

+86
-4
lines changed

modules/aruco/src/aruco.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,11 +280,11 @@ static void _filterTooCloseCandidates(const vector< vector< Point2f > > &candida
280280
double minMarkerDistanceRate, bool detectInvertedMarker) {
281281

282282
CV_Assert(minMarkerDistanceRate >= 0);
283-
284283
vector<int> candGroup;
285284
candGroup.resize(candidatesIn.size(), -1);
286285
vector< vector<unsigned int> > groupedCandidates;
287286
for(unsigned int i = 0; i < candidatesIn.size(); i++) {
287+
bool isSingleContour = true;
288288
for(unsigned int j = i + 1; j < candidatesIn.size(); j++) {
289289

290290
int minimumPerimeter = min((int)contoursIn[i].size(), (int)contoursIn[j].size() );
@@ -305,7 +305,7 @@ static void _filterTooCloseCandidates(const vector< vector< Point2f > > &candida
305305
// if mean square distance is too low, remove the smaller one of the two markers
306306
double minMarkerDistancePixels = double(minimumPerimeter) * minMarkerDistanceRate;
307307
if(distSq < minMarkerDistancePixels * minMarkerDistancePixels) {
308-
308+
isSingleContour = false;
309309
// i and j are not related to a group
310310
if(candGroup[i]<0 && candGroup[j]<0){
311311
// mark candidates with their corresponding group number
@@ -336,6 +336,14 @@ static void _filterTooCloseCandidates(const vector< vector< Point2f > > &candida
336336
}
337337
}
338338
}
339+
if (isSingleContour && candGroup[i] < 0)
340+
{
341+
candGroup[i] = (int)groupedCandidates.size();
342+
vector<unsigned int> grouped;
343+
grouped.push_back(i);
344+
grouped.push_back(i); // step "save possible candidates" require minimum 2 elements
345+
groupedCandidates.push_back(grouped);
346+
}
339347
}
340348

341349
// save possible candidates

modules/aruco/test/test_arucodetection.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,4 +644,77 @@ TEST(CV_ArucoTutorial, can_find_gboriginal)
644644
}
645645
}
646646

647+
TEST(CV_ArucoDetectMarkers, regression_3192)
648+
{
649+
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_4X4_50);
650+
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
651+
vector< int > markerIds;
652+
vector<vector<Point2f> > markerCorners;
653+
string imgPath = cvtest::findDataFile("aruco/regression_3192.png");
654+
Mat image = imread(imgPath);
655+
const size_t N = 2ull;
656+
const int goldCorners[N][8] = { {345,120, 520,120, 520,295, 345,295}, {101,114, 270,112, 276,287, 101,287} };
657+
const int goldCornersIds[N] = { 6, 4 };
658+
map<int, const int*> mapGoldCorners;
659+
for (size_t i = 0; i < N; i++)
660+
mapGoldCorners[goldCornersIds[i]] = goldCorners[i];
661+
662+
aruco::detectMarkers(image, dictionary, markerCorners, markerIds, detectorParams);
663+
664+
ASSERT_EQ(N, markerIds.size());
665+
for (size_t i = 0; i < N; i++)
666+
{
667+
int arucoId = markerIds[i];
668+
ASSERT_EQ(4ull, markerCorners[i].size());
669+
ASSERT_TRUE(mapGoldCorners.find(arucoId) != mapGoldCorners.end());
670+
for (int j = 0; j < 4; j++)
671+
{
672+
EXPECT_NEAR(static_cast<float>(mapGoldCorners[arucoId][j * 2]), markerCorners[i][j].x, 1.f);
673+
EXPECT_NEAR(static_cast<float>(mapGoldCorners[arucoId][j * 2 + 1]), markerCorners[i][j].y, 1.f);
674+
}
675+
}
676+
}
677+
678+
TEST(CV_ArucoDetectMarkers, regression_2492)
679+
{
680+
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_5X5_50);
681+
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
682+
detectorParams->minMarkerDistanceRate = 0.026;
683+
vector< int > markerIds;
684+
vector<vector<Point2f> > markerCorners;
685+
string imgPath = cvtest::findDataFile("aruco/regression_2492.png");
686+
Mat image = imread(imgPath);
687+
const size_t N = 8ull;
688+
const int goldCorners[N][8] = { {179,139, 179,95, 223,95, 223,139}, {99,139, 99,95, 143,95, 143,139},
689+
{19,139, 19,95, 63,95, 63,139}, {256,140, 256,93, 303,93, 303,140},
690+
{256,62, 259,21, 300,23, 297,64}, {99,21, 143,17, 147,60, 103,64},
691+
{69,61, 28,61, 14,21, 58,17}, {174,62, 182,13, 230,19, 223,68} };
692+
const int goldCornersIds[N] = {13, 13, 13, 13, 1, 15, 14, 4};
693+
map<int, vector<const int*> > mapGoldCorners;
694+
for (size_t i = 0; i < N; i++)
695+
mapGoldCorners[goldCornersIds[i]].push_back(goldCorners[i]);
696+
697+
aruco::detectMarkers(image, dictionary, markerCorners, markerIds, detectorParams);
698+
699+
ASSERT_EQ(N, markerIds.size());
700+
for (size_t i = 0; i < N; i++)
701+
{
702+
int arucoId = markerIds[i];
703+
ASSERT_EQ(4ull, markerCorners[i].size());
704+
ASSERT_TRUE(mapGoldCorners.find(arucoId) != mapGoldCorners.end());
705+
float totalDist = 8.f;
706+
for (size_t k = 0ull; k < mapGoldCorners[arucoId].size(); k++)
707+
{
708+
float dist = 0.f;
709+
for (int j = 0; j < 4; j++) // total distance up to 4 points
710+
{
711+
dist += abs(mapGoldCorners[arucoId][k][j * 2] - markerCorners[i][j].x);
712+
dist += abs(mapGoldCorners[arucoId][k][j * 2 + 1] - markerCorners[i][j].y);
713+
}
714+
totalDist = min(totalDist, dist);
715+
}
716+
EXPECT_LT(totalDist, 8.f);
717+
}
718+
}
719+
647720
}} // namespace

modules/aruco/test/test_charucodetection.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -745,15 +745,16 @@ TEST(Charuco, issue_14014)
745745
ASSERT_EQ(corners.size(), 19ull);
746746
EXPECT_EQ(Size(4, 1), corners[0].size()); // check dimension of detected corners
747747

748-
ASSERT_EQ(rejectedPoints.size(), 21ull);
748+
size_t numRejPoints = rejectedPoints.size();
749+
ASSERT_EQ(rejectedPoints.size(), 26ull); // optional check to track regressions
749750
EXPECT_EQ(Size(4, 1), rejectedPoints[0].size()); // check dimension of detected corners
750751

751752
aruco::refineDetectedMarkers(img, board, corners, ids, rejectedPoints);
752753

753754
ASSERT_EQ(corners.size(), 20ull);
754755
EXPECT_EQ(Size(4, 1), corners[0].size()); // check dimension of rejected corners after successfully refine
755756

756-
ASSERT_EQ(rejectedPoints.size(), 20ull);
757+
ASSERT_EQ(rejectedPoints.size() + 1, numRejPoints);
757758
EXPECT_EQ(Size(4, 1), rejectedPoints[0].size()); // check dimension of rejected corners after successfully refine
758759
}
759760

0 commit comments

Comments
 (0)