利用对称的园盘格标定相机一般就会用到findCirclesGrid这个函数。如下图
虽然从找点到标定opencv都提供了现成的函数,但是参数的设置上还是得注意。
findCirclesGrid一般这么调用
std::vector<cv::Point2f> p;
cv::Size s;
s.height = 6;
s.width = 9;
found1 = findCirclesGrid(img, s, p, CALIB_CB_SYMMETRIC_GRID | CALIB_CB_CLUSTERING, detector);
CALIB_CB_SYMMETRIC_GRID //对称圆盘
CALIB_CB_ASYMMETRIC_GRID//非对称圆盘
CALIB_CB_CLUSTERING//可以使用or逻辑符与图案标识符一起设置,此时函数会以稍微不同的算法来寻找圆圈,这个替代算法对透视畸变具有较高的鲁棒性,但对背景的干扰也更加敏感,适合标定具有非常宽视野的相机。
对于对称的圆盘,一般先使用CALIB_CB_SYMMETRIC_GRID | CALIB_CB_CLUSTERING若是发现很多错点,就使用CALIB_CB_SYMMETRIC_GRID 即可。
函数中的detector是自定义的斑点检测器
SimpleBlobDetector::Params params;
cv::Ptr<cv::SimpleBlobDetector> detector = cv::SimpleBlobDetector::create(params);
这是默认的检测器,params可以设置很多的参数来改变检测器
thresholdStep = 10; //二值化的阈值步长,即公式1的t
minThreshold = 50; //二值化的起始阈值,即公式1的T1
maxThreshold = 220; //二值化的终止阈值,即公式1的T2
//重复的最小次数,只有属于灰度图像斑点的那些二值图像斑点数量大于该值时,该灰度图像斑点才被认为是特征点
minRepeatability = 2;
//最小的斑点距离,不同二值图像的斑点间距离小于该值时,被认为是同一个位置的斑点,否则是不同位置上的斑点
minDistBetweenBlobs = 10;
filterByColor = true; //斑点颜色的限制变量
blobColor = 0; //表示只提取黑色斑点;如果该变量为255,表示只提取白色斑点
filterByArea = true; //斑点面积的限制变量
minArea = 25; //斑点的最小面积
maxArea = 5000; //斑点的最大面积
filterByCircularity = false; //斑点圆度的限制变量,默认是不限制
minCircularity = 0.8f; //斑点的最小圆度
//斑点的最大圆度,所能表示的float类型的最大值
maxCircularity = std::numeric_limits<float>::max();
filterByInertia = true; //斑点惯性率的限制变量
//minInertiaRatio = 0.6;
minInertiaRatio = 0.1f; //斑点的最小惯性率
maxInertiaRatio = std::numeric_limits<float>::max(); //斑点的最大惯性率
filterByConvexity = true; //斑点凸度的限制变量
//minConvexity = 0.8;
minConvexity = 0.95f; //斑点的最小凸度
maxConvexity = std::numeric_limits<float>::max(); //斑点的最大凸度
如我们想告诉检测器最小的斑点的面积:
params.filterByArea = true;
params.minArea = 10;
在实际标定的过程中遇到了图片较小,斑点间间隔比较小,用默认的检测器会存在有斑点检测不出来,修改下面代码后顺利检出
params.minDistBetweenBlobs = 0;//两个斑点间最小的距离为0
总结
在标定时:
1、若检测的点混乱、重复,试着不用CALIB_CB_SYMMETRIC_GRID | CALIB_CB_CLUSTERING只用CALIB_CB_SYMMETRIC_GRID
2、对于图片小、点密的情况改变检测的最小间隔params.minDistBetweenBlobs = 0;