diff --git a/modules/calib3d/src/circlesgrid.cpp b/modules/calib3d/src/circlesgrid.cpp index 81693941de..c27604873c 100644 --- a/modules/calib3d/src/circlesgrid.cpp +++ b/modules/calib3d/src/circlesgrid.cpp @@ -178,7 +178,7 @@ void CirclesGridClusterFinder::findGrid(const std::vector &points, if(outsideCorners.size() != outsideCornersCount) return; } - getSortedCorners(hull2f, corners, outsideCorners, sortedCorners); + getSortedCorners(hull2f, patternPoints, corners, outsideCorners, sortedCorners); if(sortedCorners.size() != cornersCount) return; @@ -295,7 +295,18 @@ void CirclesGridClusterFinder::findOutsideCorners(const std::vector #endif } -void CirclesGridClusterFinder::getSortedCorners(const std::vector &hull2f, const std::vector &corners, const std::vector &outsideCorners, std::vector &sortedCorners) +namespace { +double pointLineDistance(const cv::Point2f &p, const cv::Vec4f &line) +{ + Vec3f pa( line[0], line[1], 1 ); + Vec3f pb( line[2], line[3], 1 ); + Vec3f l = pa.cross(pb); + return std::abs((p.x * l[0] + p.y * l[1] + l[2])) * 1.0 / + std::sqrt(double(l[0] * l[0] + l[1] * l[1])); +} +} + +void CirclesGridClusterFinder::getSortedCorners(const std::vector &hull2f, const std::vector &patternPoints, const std::vector &corners, const std::vector &outsideCorners, std::vector &sortedCorners) { Point2f firstCorner; if(isAsymmetricGrid) @@ -341,10 +352,26 @@ void CirclesGridClusterFinder::getSortedCorners(const std::vector & if(!isAsymmetricGrid) { - double dist1 = norm(sortedCorners[0] - sortedCorners[1]); - double dist2 = norm(sortedCorners[1] - sortedCorners[2]); + double dist01 = norm(sortedCorners[0] - sortedCorners[1]); + double dist12 = norm(sortedCorners[1] - sortedCorners[2]); + // Use half the average distance between circles on the shorter side as threshold for determining whether a point lies on an edge. + double thresh = min(dist01, dist12) / min(patternSize.width, patternSize.height) / 2; - if((dist1 > dist2 && patternSize.height > patternSize.width) || (dist1 < dist2 && patternSize.height < patternSize.width)) + size_t circleCount01 = 0; + size_t circleCount12 = 0; + Vec4f line01( sortedCorners[0].x, sortedCorners[0].y, sortedCorners[1].x, sortedCorners[1].y ); + Vec4f line12( sortedCorners[1].x, sortedCorners[1].y, sortedCorners[2].x, sortedCorners[2].y ); + // Count the circles along both edges. + for (size_t i = 0; i < patternPoints.size(); i++) + { + if (pointLineDistance(patternPoints[i], line01) < thresh) + circleCount01++; + if (pointLineDistance(patternPoints[i], line12) < thresh) + circleCount12++; + } + + // Ensure that the edge from sortedCorners[0] to sortedCorners[1] is the one with more circles (i.e. it is interpreted as the pattern's width). + if ((circleCount01 > circleCount12 && patternSize.height > patternSize.width) || (circleCount01 < circleCount12 && patternSize.height < patternSize.width)) { for(size_t i=0; i &hull2f, std::vector &corners); void findOutsideCorners(const std::vector &corners, std::vector &outsideCorners); - void getSortedCorners(const std::vector &hull2f, const std::vector &corners, const std::vector &outsideCorners, std::vector &sortedCorners); + void getSortedCorners(const std::vector &hull2f, const std::vector &patternPoints, const std::vector &corners, const std::vector &outsideCorners, std::vector &sortedCorners); void rectifyPatternPoints(const std::vector &patternPoints, const std::vector &sortedCorners, std::vector &rectifiedPatternPoints); void parsePatternPoints(const std::vector &patternPoints, const std::vector &rectifiedPatternPoints, std::vector ¢ers);