我会首先计算所有检测到的圆心的凸包,然后近似得到多边形(使其有 4 条边):
vector<Point> convex_hull;
vector<Point> poly_hull;
vector<Point> circle_centers;
// fill circle centers
...
// compute and approximate convex hull
convexHull( Mat( circle_centers ), convex_hull );
approxPolyDP( Mat( convex_hull ), poly_hull, 3, true );
下一步是找到离四个 poly_hull 点最近(以欧几里德距离计)的 4 个圆心:它们是四个角。首先以左上角顺时针方式重新排序它们,然后您可以对仿射变换进行初步估计:
vector<Point2f> dst_points;
vector<Point2f> src_points;
Rect canvas;
// fill in original canvas dimensions
...
// add source points
src_points.push_back( Point2f( canvas.tl() ) );
src_points.push_back( Point2f( canvas.width, 0 ) );
src_points.push_back( Point2f( canvas.br() ) );
src_points.push_back( Point2f( 0, canvas.height ) );
// add destination points
for ( int i = 0; i < poly_hull.size(); i++ )
dst_points.push_back( poly_hull[i] );
// estimate transformation
Mat transformation = estimateRigidTransform( src_points, dst_points, false );
if ( transformation.data != 0 )
{
cout << "+++ AFFINE TRANSFORMATION ESTIMATE +++++++++++++++++++++++++++"<< endl;
cout << " + homography matrix: " << endl;
cout << cv::format( " + [ %.3f %.3f %.3f ]", transformation.at<double>( 0, 0 ), transformation.at<double>( 0, 1 ), transformation.at<double>( 0, 2 ) ) << endl ;
cout << cv::format( " + [ %.3f %.3f %.3f ]", transformation.at<double>( 1, 0 ), transformation.at<double>( 1, 1 ), transformation.at<double>( 1, 2 ) ) << endl ;
cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"<< endl;
}
else
{
cout << "HOMOGRAPHY NO DATA" << endl;
}
之后,您可以通过使用第一次仿射变换将真实圆心投影到图像空间并寻找最近的点来找到更多对应点对,从而优化仿射估计。如果您怀疑的不仅仅是仿射,您还可以在这种情况下查看 cv::findHomography。