一、cornerSubPix()函数
调用格式:
void cv::cornerSubPix | ( | InputArray | image, |
InputOutputArray | corners, | ||
Size | winSize, | ||
Size | zeroZone, | ||
TermCriteria | criteria | ||
) |
image | Input single-channel, 8-bit or float image. |
corners | Initial coordinates of the input corners and refined coordinates provided for output. |
winSize | Half of the side length of the search window. For example, if winSize=Size(5,5) , then a (5∗2+1)×(5∗2+1)=11×11 search window is used. |
zeroZone | Half of the size of the dead region in the middle of the search zone over which the summation in the formula below is not done. It is used sometimes to avoid possible singularities of the autocorrelation matrix. The value of (-1,-1) indicates that there is no such a size. |
criteria | Criteria for termination of the iterative process of corner refinement. That is, the process of corner position refinement stops either after criteria.maxCount iterations or when the corner position moves by less than criteria.epsilon on some iteration. |
头文件:
#include <opencv2/imgproc.hpp>
作用:
优化角点位置,获得棋盘格上的亚像素角点。
该函数进行迭代以查找角或径向鞍点的亚像素精确位置,如下图所示。
二、find4QuadCornerSubpix()函数
格式:
bool cv::find4QuadCornerSubpix | ( | InputArray | img, |
InputOutputArray | corners, | ||
Size | region_size | ||
) |
第一个参数img,为输入的Mat矩阵,最好是8位灰度图像,检测效率更高;
第二个参数corners,初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要是浮点型数据,一般用元素是Pointf2f/Point2d的向量来表示:vector<Point2f/Point2d> iamgePointsBuf;
第三个参数region_size,角点搜索窗口的尺寸;
头文件:
#include <opencv2/calib3d.hpp>
作用:
查找棋盘角的亚像素精确位置。尝试近似分隔棋盘格字段(“四边形”)的线并返回这些线的交叉点。
对每个角点进行如下操作:
1. 根据输入的搜索窗口的尺寸,确定以该角点为中心的ROI区域,并计算该区域的直方图
2. 找出直方图中最大的一段segment_hist_max,据此进行图像二值化,之后进行腐蚀操作,共进行两次
3. 对两幅图使用findContours进行轮廓提取,对于轮廓根据到该角点的最小距离排序
4. 以每幅图最小的两个轮廓为研究对象,先进行多边形逼近approxPolyDP,并使用findCorner找到轮廓中到该角点最近的点
5. 对找到的四个点使用findLinesCrossPoint,获取精确的角点位置
三、总结
虽然二者的作用都是获得棋盘格上的亚像素角点,但可以明显看出二者实现的原理不同。
cornerSubPix()函数作为一个较为经典的函数,效果已经得到检验,事实上在使用 findChessboardCorners 时,就会自动使用一个 2x2 的小窗口执行cornerSubPix ,因此您已经获得了一些亚像素精度的坐标。
find4QuadCornerSubpix()函数函数作为新版本添加的函数,效果理应得到升级,但事实上,根据
opencv - find4QuadCornerSubpix vs cornerSubPix - Stack Overflow
这个问题下面的回答可以看到,find4QuadCornerSubpix的精度似乎还不如cornerSubPix。
而我的建议是,既然这是两种原理不同的方法,自然有各自的适用场景。但我也并无意探究究竟各自适合哪种场景,毕竟这仅仅是换一个函数的事,在使用时分别试试,看哪个函数得到的结果更好,即可。
四、实操
自己也试了试,运行代码如下:
提取角点:
findChessboardCorners(imageInput, board_size, image_points_buf)
Mat view_gray;
cvtColor(imageInput, view_gray, COLOR_BGR2GRAY);
find4QuadCornerSubpix() 参数如下:
find4QuadCornerSubpix(view_gray, image_points_buf, Size(5, 5));
cornerSubPix() 参数如下:
cornerSubPix(view_gray, image_points_buf, Size(5, 5), Size(-1, -1), TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, 0.1));
projectPoints() 重投影结果如下:
1、findChessboardCorners结果
每幅图像的标定误差:
第1幅图像的平均误差:0.0233192像素
第2幅图像的平均误差:0.0215262像素
第3幅图像的平均误差:0.0240675像素
第4幅图像的平均误差:0.0235293像素
第5幅图像的平均误差:0.027864像素
第6幅图像的平均误差:0.0261229像素
第7幅图像的平均误差:0.0240523像素
第8幅图像的平均误差:0.0237376像素
第9幅图像的平均误差:0.0231385像素
第10幅图像的平均误差:0.0239434像素
第11幅图像的平均误差:0.0230342像素
第12幅图像的平均误差:0.0199533像素
第13幅图像的平均误差:0.0305514像素
第14幅图像的平均误差:0.0211515像素
第15幅图像的平均误差:0.0282532像素
第16幅图像的平均误差:0.0230023像素
第17幅图像的平均误差:0.0251575像素
第18幅图像的平均误差:0.0227478像素
第19幅图像的平均误差:0.0208485像素
第20幅图像的平均误差:0.0239624像素
总体平均误差:0.0239981像素
2、cornerSubPix结果
每幅图像的标定误差:
第1幅图像的平均误差:0.0205961像素
第2幅图像的平均误差:0.0167655像素
第3幅图像的平均误差:0.0198881像素
第4幅图像的平均误差:0.0217979像素
第5幅图像的平均误差:0.0254504像素
第6幅图像的平均误差:0.0229617像素
第7幅图像的平均误差:0.0219139像素
第8幅图像的平均误差:0.0203488像素
第9幅图像的平均误差:0.0174941像素
第10幅图像的平均误差:0.0216017像素
第11幅图像的平均误差:0.0206446像素
第12幅图像的平均误差:0.0186505像素
第13幅图像的平均误差:0.0299463像素
第14幅图像的平均误差:0.019161像素
第15幅图像的平均误差:0.026709像素
第16幅图像的平均误差:0.0213648像素
第17幅图像的平均误差:0.0219541像素
第18幅图像的平均误差:0.0193053像素
第19幅图像的平均误差:0.019192像素
第20幅图像的平均误差:0.0224608像素
总体平均误差:0.0214103像素
3、find4QuadCornerSubpix结果
每幅图像的标定误差:
第1幅图像的平均误差:0.0431348像素
第2幅图像的平均误差:0.0437477像素
第3幅图像的平均误差:0.0461382像素
第4幅图像的平均误差:0.0461999像素
第5幅图像的平均误差:0.0491188像素
第6幅图像的平均误差:0.0451074像素
第7幅图像的平均误差:0.0496093像素
第8幅图像的平均误差:0.0388985像素
第9幅图像的平均误差:0.0455664像素
第10幅图像的平均误差:0.0462306像素
第11幅图像的平均误差:0.043354像素
第12幅图像的平均误差:0.0454551像素
第13幅图像的平均误差:0.0444246像素
第14幅图像的平均误差:0.0408052像素
第15幅图像的平均误差:0.0453343像素
第16幅图像的平均误差:0.0403672像素
第17幅图像的平均误差:0.0443846像素
第18幅图像的平均误差:0.0488975像素
第19幅图像的平均误差:0.0452479像素
第20幅图像的平均误差:0.0450223像素
总体平均误差:0.0448522像素
和链接里帖子得到的结论相仿,使用find4QuadCornerSubpix进行亚像素精确化的重投影结果竟然还不如不用。晕~