Skip to content

Commit 798c005

Browse files
Alexander PanovAleksandrPanov
Alexander Panov
authored andcommitted
Merge pull request opencv#3201 from AleksandrPanov:fix_filterTooCloseCandidates
* fix search for one contour in _filterTooCloseCandidates() * add regression_3192 test * add regression_2492 test (cherry picked from commit ef5a7e8)
1 parent 36bc2af commit 798c005

File tree

3 files changed

+86
-4
lines changed

3 files changed

+86
-4
lines changed

modules/aruco/src/aruco.cpp

+10-2
Original file line numberDiff line numberDiff line change
@@ -295,11 +295,11 @@ static void _filterTooCloseCandidates(const vector< vector< Point2f > > &candida
295295
double minMarkerDistanceRate, bool detectInvertedMarker) {
296296

297297
CV_Assert(minMarkerDistanceRate >= 0);
298-
299298
vector<int> candGroup;
300299
candGroup.resize(candidatesIn.size(), -1);
301300
vector< vector<unsigned int> > groupedCandidates;
302301
for(unsigned int i = 0; i < candidatesIn.size(); i++) {
302+
bool isSingleContour = true;
303303
for(unsigned int j = i + 1; j < candidatesIn.size(); j++) {
304304

305305
int minimumPerimeter = min((int)contoursIn[i].size(), (int)contoursIn[j].size() );
@@ -320,7 +320,7 @@ static void _filterTooCloseCandidates(const vector< vector< Point2f > > &candida
320320
// if mean square distance is too low, remove the smaller one of the two markers
321321
double minMarkerDistancePixels = double(minimumPerimeter) * minMarkerDistanceRate;
322322
if(distSq < minMarkerDistancePixels * minMarkerDistancePixels) {
323-
323+
isSingleContour = false;
324324
// i and j are not related to a group
325325
if(candGroup[i]<0 && candGroup[j]<0){
326326
// mark candidates with their corresponding group number
@@ -351,6 +351,14 @@ static void _filterTooCloseCandidates(const vector< vector< Point2f > > &candida
351351
}
352352
}
353353
}
354+
if (isSingleContour && candGroup[i] < 0)
355+
{
356+
candGroup[i] = (int)groupedCandidates.size();
357+
vector<unsigned int> grouped;
358+
grouped.push_back(i);
359+
grouped.push_back(i); // step "save possible candidates" require minimum 2 elements
360+
groupedCandidates.push_back(grouped);
361+
}
354362
}
355363

356364
// save possible candidates

modules/aruco/test/test_arucodetection.cpp

+73
Original file line numberDiff line numberDiff line change
@@ -655,4 +655,77 @@ TEST(CV_ArucoTutorial, can_find_gboriginal)
655655
}
656656
}
657657

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

modules/aruco/test/test_charucodetection.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -801,15 +801,16 @@ TEST(Charuco, issue_14014)
801801
ASSERT_EQ(corners.size(), 19ull);
802802
EXPECT_EQ(Size(4, 1), corners[0].size()); // check dimension of detected corners
803803

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

807808
aruco::refineDetectedMarkers(img, board, corners, ids, rejectedPoints);
808809

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

812-
ASSERT_EQ(rejectedPoints.size(), 20ull);
813+
ASSERT_EQ(rejectedPoints.size() + 1, numRejPoints);
813814
EXPECT_EQ(Size(4, 1), rejectedPoints[0].size()); // check dimension of rejected corners after successfully refine
814815
}
815816

0 commit comments

Comments
 (0)