近期使用OpenCV的库函数findCirclesGrid()
做圆点标定中的特征点提取时,发现对于部分存在较大透视畸变的标定图片,findCirclesGrid()
可能会出现提取不到圆点的情况
bool cv::findCirclesGrid ( InputArray image, Size patternSize, OutputArray centers, int flags = CALIB_CB_SYMMETRIC_GRID, const Ptr< FeatureDetector > & blobDetector = SimpleBlobDetector::create() )
CALIB_CB_SYMMETRIC_GRID
or 非对称圆点CALIB_CB_ASYMMETRIC_GRID
)以及相关的算法参数由于只有部分标定图片无法被提取到特征点,故怀疑是提取点时候的算法鲁棒性较差导致,通过查阅资料,在OpenCV的相关书籍中有这么一段话
flags的选项中有一个是
CALIB_CB_CLUSTERING
,可以使用or逻辑符与图案标识符一起设置,此时函数会以稍微不同的算法来寻找圆圈,这个替代算法对透视畸变具有较高的鲁棒性,但对背景的干扰也更加敏感,适合标定具有非常宽视野的相机。
修改函数后,可以提取到正确的圆心
#include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; int main() {
// Blob算子参数 SimpleBlobDetector::Params params; /*params.minThreshold = 10; params.maxThreshold = 200;*/ params.maxArea = 10e4; params.minArea = 10; params.filterByArea = true; /*params.minDistBetweenBlobs = 5; params.filterByInertia = false; params.minInertiaRatio = 0.5;*/ Ptr<FeatureDetector> blobDetector = SimpleBlobDetector::create(params); Mat img = imread("right01_circulars.jpg", 0); vector<Point2f> centers; Size patternSize(9, 6); // 提取圆点特征的圆心 // 无法提取到圆心 //bool found = findCirclesGrid(img, patternSize, centers, CALIB_CB_SYMMETRIC_GRID, blobDetector); bool found = findCirclesGrid(img, patternSize, centers, CALIB_CB_SYMMETRIC_GRID | CALIB_CB_CLUSTERING, blobDetector); Mat cimg; cvtColor(img, cimg, COLOR_GRAY2BGR); drawChessboardCorners(cimg, patternSize, centers, found); double sf = 960. / MAX(img.rows, img.cols); resize(img, img, Size(), sf, sf, INTER_LINEAR_EXACT); resize(cimg, cimg, Size(), sf, sf, INTER_LINEAR_EXACT); imshow("原始图像", img); imshow("corners", cimg); waitKey(); return 0; }