Merge pull request #12999 from fegorsch:improve-circle-detector

pull/13059/head^2
Alexander Alekhin 6 years ago
commit fa91e4ff27
  1. 37
      modules/calib3d/src/circlesgrid.cpp
  2. 2
      modules/calib3d/src/circlesgrid.hpp
  3. 19
      modules/calib3d/test/test_chesscorners.cpp

@ -178,7 +178,7 @@ void CirclesGridClusterFinder::findGrid(const std::vector<cv::Point2f> &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<cv::Point2f>
#endif
}
void CirclesGridClusterFinder::getSortedCorners(const std::vector<cv::Point2f> &hull2f, const std::vector<cv::Point2f> &corners, const std::vector<cv::Point2f> &outsideCorners, std::vector<cv::Point2f> &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<cv::Point2f> &hull2f, const std::vector<cv::Point2f> &patternPoints, const std::vector<cv::Point2f> &corners, const std::vector<cv::Point2f> &outsideCorners, std::vector<cv::Point2f> &sortedCorners)
{
Point2f firstCorner;
if(isAsymmetricGrid)
@ -341,10 +352,26 @@ void CirclesGridClusterFinder::getSortedCorners(const std::vector<cv::Point2f> &
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;
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++;
}
if((dist1 > dist2 && patternSize.height > patternSize.width) || (dist1 < dist2 && patternSize.height < patternSize.width))
// 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<sortedCorners.size()-1; i++)
{

@ -69,7 +69,7 @@ public:
private:
void findCorners(const std::vector<cv::Point2f> &hull2f, std::vector<cv::Point2f> &corners);
void findOutsideCorners(const std::vector<cv::Point2f> &corners, std::vector<cv::Point2f> &outsideCorners);
void getSortedCorners(const std::vector<cv::Point2f> &hull2f, const std::vector<cv::Point2f> &corners, const std::vector<cv::Point2f> &outsideCorners, std::vector<cv::Point2f> &sortedCorners);
void getSortedCorners(const std::vector<cv::Point2f> &hull2f, const std::vector<cv::Point2f> &patternPoints, const std::vector<cv::Point2f> &corners, const std::vector<cv::Point2f> &outsideCorners, std::vector<cv::Point2f> &sortedCorners);
void rectifyPatternPoints(const std::vector<cv::Point2f> &patternPoints, const std::vector<cv::Point2f> &sortedCorners, std::vector<cv::Point2f> &rectifiedPatternPoints);
void parsePatternPoints(const std::vector<cv::Point2f> &patternPoints, const std::vector<cv::Point2f> &rectifiedPatternPoints, std::vector<cv::Point2f> &centers);

@ -468,5 +468,24 @@ TEST(Calib3d_AsymmetricCirclesPatternDetector, accuracy) { CV_ChessboardDetector
TEST(Calib3d_AsymmetricCirclesPatternDetectorWithClustering, accuracy) { CV_ChessboardDetectorTest test( ASYMMETRIC_CIRCLES_GRID, CALIB_CB_CLUSTERING ); test.safe_run(); }
#endif
TEST(Calib3d_CirclesPatternDetectorWithClustering, accuracy)
{
cv::String dataDir = string(TS::ptr()->get_data_path()) + "cv/cameracalibration/circles/";
cv::Mat expected;
FileStorage fs(dataDir + "circles_corners15.dat", FileStorage::READ);
fs["corners"] >> expected;
fs.release();
cv::Mat image = cv::imread(dataDir + "circles15.png");
std::vector<Point2f> centers;
cv::findCirclesGrid(image, Size(10, 8), centers, CALIB_CB_SYMMETRIC_GRID | CALIB_CB_CLUSTERING);
ASSERT_EQ(expected.total(), centers.size());
double error = calcError(centers, expected);
ASSERT_LE(error, precise_success_error_level);
}
}} // namespace
/* End of file. */

Loading…
Cancel
Save