Opencv实现张正友法相机标定
相机标定的目的:获取摄像机的内参和外参矩阵(同时也会得到每一幅标定图像的选择和平移矩阵),内参和外参系数可以对之后相机拍摄的图像就进行矫正,得到畸变相对很小的图像。
相机标定的输入:标定图像上所有内角点的图像坐标,标定板图像上所有内角点的空间三维坐标(一般情况下假定图像位于Z=0平面上)。
相机标定的输出:摄像机的内参、外参系数。
矫正原始图像的完整流程:
1. 准备标定图片
2. 对每一张标定图片,提取角点信息
3. 对每一张标定图片,进一步提取亚像素角点信息
4. 在棋盘标定图上绘制找到的内角点(非必须,仅为了显示)
5. 相机标定
6. 对标定结果进行评价
7. 查看标定效果——利用标定结果对棋盘图进行矫正
1. 准备标定图片
标定图片需要使用标定板在不同位置、不同角度、不同姿态下拍摄,最少需要3张,以10~20张为宜。标定板需要是黑白相间的矩形构成的棋盘图,制作精度要求较高
2.对每一张标定图片,提取角点信息
需要使用findChessboardCorners函数提取角点,这里的角点专指的是标定板上的内角点,这些角点与标定板的边缘不接触。
findChessboardCorners
CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize,
OutputArray corners,
int flags=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE );
第一个参数Image,传入拍摄的棋盘图Mat图像,必须是8位的灰度或者彩色图像;
第二个参数patternSize,每个棋盘图上内角点的行列数,一般情况下,行列数不要相同,便于后续标定程序识别标定板的方向;
第三个参数corners,用于存储检测到的内角点图像坐标位置,一般用元素是Point2f的向量来表示:vector<Point2f> image_points_buf;
第四个参数flage:用于定义棋盘图上内角点查找的不同处理方式,有默认值。
通过调用cvFindChessboardCorners实现
CvCBQuad用来存储棋盘上的方格信息,CvCBCorner用来存储棋盘方格的四个角点
标识符:CV_CALIB_CB_NORMALIZE_IMAGE 是否进行灰度直方图均衡化
CV_CALIB_CB_FAST_CHECK 检查是否有要找的棋盘格
CV_CALIB_CB_ADAPTIVE_THRESH 是否进行自适应阈值
CV_CALIB_CB_FILTER_QUADS 是否使用其他的准则(如轮廓面积,周长,方形形状)来去除在轮廓检测阶段检测到的错误方块。
1. 将图片从RGB转为GRAY,并进行灰度直方图均衡化cvEqualizeHist,并检查是否有要找的棋盘格cvCheckChessboard 要求:图像为8bit,3通道或单通道
对于下列的操作,如未找到角点,会重复进行6次,在每一次中,图像膨胀的核的大小会不断增大。
2. 根据标识符进行图像二值化,并进行图像膨胀,使用cvStartFindContours寻找轮廓,排除面积小于25的轮廓,并对每个轮廓多次进行多边形逼近cvApproxPoly,获取四边形。之后判断轮廓是否为凸边形cvCheckContourConvexity,最后通过面积、边长进一步筛选。
3. 寻找每个方格的相邻方格,并记相邻方格的个数,连同相邻方格的信息存在相应CvCBQuad结构体中。二值图像在膨胀后原本相邻的方格,分开了,原来相连部分有一个公共点,现在分开变成了两个点。找到相邻的方格之后,计算出原来的公共点,用公共点替代膨胀后分开的点。这主要由icvFindQuadNeighborhors函数完成。
4. 对所有“方格”(包括被误判的)分类,分类的原则是类内所有方格是相邻的。由icvFindConnectedQuads函数完成。
5. 根据已知所求的角点个数,判别每个类中方格是否为所求的棋盘方格,并对棋盘方格排序,即该方格位于哪行那列。在这个过程中,可以添加每类方格总缺少的方格,也可以删除每类方格中多余的方格。icvOrderFoundConnetedQuads函数完成该过程。
6. icvCleanFoundConnectedQuads函数、icvCheckQuadGroup函数根据已知棋盘的方格个数<