OpenCV标定函数总结

发布时间 2023-07-08 10:21:07作者: 小凉拖

findChessboardCorners

函数简介

在相机标定过程中,如采用棋盘格标定板进行标定,则需找到棋盘格内角点,根据棋盘格内角点在像面中的像素坐标和各点对应的棋盘世界坐标,拍摄多个位置下的棋盘格,多点求解相机内外参。OpenCV中的findChessboardCorners()函数即用于棋盘格角点检测。

1 findChessboardCorners(InputArray image,
2 Size patternSize,OutputArray corners,
3 int flags=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE)                                                                                                                                                                 

功能

找到标定板内角点位置(标定板是专用器具,需要有严格的规格控制,标定板的制作精度直接影响标定精度;角点是指黑白色相接的方块定点部分;内角点是不与标定板边缘接触的内部角点)

参数

  • 输入的图像矩阵,必须是8-bit灰度图或者彩色图像,在图像传入函数之前,一般经过灰度处理,还有滤波操作。
  • 内角点的size,表示方式是定义Size PatSize(m,n),将PatSize作为参数传入。这里是内角点的行列数,不包括边缘角点行列数;行数和列数不要相同,这样的话函数会辨别出标定板的方向,如果行列数相同,那么函数每次画出来的角点起始位置会变化,不利于标定。
  • 存储角点的数组,一般用 vector<vector<point2f>>
  • 标志位,有默认值。
  1. CV_CALIB_CB_ADAPTIVE_THRESH:函数默认方式,根据图像的平均亮度值进行图像二值化,设立此标志位的含义是采用变化的阈值进行自适应二值化;
  2. CV_CALIB_CB_NORMALIZE_IMAGE:在二值化之前,调用EqualizeHist()函数进行图像归一化处理(直方图均衡化);
  3. CV_CALIB_CB_FILTER_QUADS:二值化完成后,函数开始定位图像中的四边形(这里不应该称之为正方形,因为存在畸变),这个标志设立后,函数开始使用面积、周长等参数来筛选方块(过滤掉在轮廓检索阶段提取的假四边形),从而使得角点检测更准确更严格。(个人理解这个不常用,因为拍摄的时候肯定会出现畸变,如果加入这个标志位在,则可能滤掉一些棋盘格,那么角点检测的时候就不是一个完整的棋盘格)
  4. CALIB_CB_FAST_CHECK:快速检测选项,对于检测角点极可能不成功检测的情况,这个标志位可以使函数效率提升。(对图像运行一个快速检查机制以查找棋盘板的角点,如果没有找到角点则返回一个快捷提醒。当没有观察到棋盘时,可以极大地加快在退化条件下的调用)(该标志位的作用就是快速检测一下图像中是否有棋盘格)

注意:标志位可组合使用。CALIB_CB_FAST_CHECK一般用于快速检测,很有可能检测不成功,特别是棋盘光线不均匀时。总体来说,CV_CALIB_CB_ADAPTIVE_THRESH是最可能检测到棋盘格的方式,组合使用推荐CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_NORMALIZE_IMAGE(二值化处理|直方图均衡化)(如果想加入此功能,就将标志位写上去并和其他标志位相与,这样根据最终的flags值可以判断需要实现什么功能或则可以让flags与之与等:flags|=CV_CALIB_CB_ADAPTIVE_THRESH),如果默认方式或这个组合方式检测不到角点,基本就需要重新采图了。

总结

该函数的功能就是判断图像内是否包含完整的棋盘图,如果能够检测完全,就把他们的角点坐标按 顺序(逐行,从左到右)记录下来,并返回非0数,否则返回0。 这里对size参数要求非常严格,函数必须检测到相同的size才会返回非0,否则返回0,这里一定要注意。
该函数检测的角点的坐标是不精确的,获得角点精确坐标,可使用 cornerSubPix()函数,进行角点亚像素提取。

参考原文链接:

(99条消息) findChessboardCorners()角点检测详解_棋盘格角点检测_对望小秘的博客-CSDN博客

(99条消息) openCV函数用法之 findChessboardCorners_tiger&sheep的博客-CSDN博客

cornerSubPix()

函数参数

  • image:输入图像

  • corners:输入角点的初始坐标以及精准化后的坐标用于输出。

  • winSize:搜索窗口边长的一半,例如如果winSize=Size(5,5),则一个大小为(5*2+1)*(5*2+1)=11*11的搜索窗口将被使用。

  • zeroZone:搜索区域中间的dead region边长的一半,有时用于避免自相关矩阵的奇异性。如果值设为(-1,-1)则表示没有这个区域。

  • criteria:角点精准化迭代过程的终止条件。也就是当迭代次数超过criteria.maxCount,或者角点位置变化小于criteria.epsilon时,停止迭代过程。

参考原文链接:

(原理分析)

OpenCV亚像素角点cornerSubPixel()源代码分析 - 一度逍遥 - 博客园 (cnblogs.com)

drawChessboardCorners

函数原型

1     void cv::drawChessboardCorners(
2         cv::InputOutputArray image, // 棋盘格图像(8UC3)即是输入也是输出
3         cv::Size patternSize, // 棋盘格内部角点的行、列数
4         cv::InputArray corners, // findChessboardCorners()输出的角点
5         bool patternWasFound // findChessboardCorners()的返回值
6     );

函数参数

  • 第一个参数是棋盘格图像(8UC3)(检测到角点并且将角点显示在原图像上)

  • 第二个参数是棋盘格内部角点的行、列,和cv::findChessboardCorners()指定的相同

  • 第三个参数是检测到的棋盘格角点(角点的位置)

  • 第四个参数是cv::findChessboardCorners()的返回值(如果检测到角点则findChessboardCorners()返回true,然后将角点显示到原图像上)

参考原文链接:

(99条消息) 【OpenCV3】棋盘格角点检测与绘制——cv::findChessboardCorners()与cv::drawChessboardCorners()详解_PHILOS_THU的博客-CSDN博客

calibrateCamera

根据校准模式的几个视图(也就是相机拍的几张不同的图片),求解摄像机的内在参数和外在参数。

在每个视图中,必须指定三维物体点及其相应的二维投影的坐标。这可以通过使用已知几何形状和易于检测特征点的对象来实现。这样的对象称为标定或校准模式,而且OpenCV有对棋盘标定的内置支持(见findchessboardcorners)。目前,固有参数的初始化(当cv_calib_use_intrinsic_guess未设置)只实现平面校准模式(对象点的z坐标,必须全部为零)

只要提供初始相机内参矩阵cameramatrix,也可以用于三维标定装置。

该算法执行以下步骤:

  • 计算初始的内在参数(只能用于平面校准模式的选项)或从输入参数中读取它们。畸变系数都为零开始,除非有cv_calib_fix_k指定。
  • 估计初始相机的姿态,就像内在参数已经已知一样。这是通过使用solvepnp。
  • 运行的全局Levenberg Marquardt优化算法来最小化投影误差,投影误差等于所提取到的图像上的特征点坐标和三维点根据使用相机的参数和姿态计算得到的图像上的投影坐标的距离的之和。

函数参数

objectPoints :世界坐标系中的点。在使用时,应该输入vector< vector< Point3f > >。

 

imagePoints :其对应的图像点。和objectPoints一样,应该输入vector< vector< Point2f > >型的变量。

 

imageSize :图像的大小,在计算相机的内参数和畸变矩阵需要用到;

 

cameraMatrix :内参数矩阵。输入一个Mat cameraMatrix即可。

 

distCoeffs :畸变矩阵。输入一个Mat distCoeffs即可。

 

rvecs :旋转向量;应该输入一个Mat的vector,即vector< Mat > rvecs因为每个vector< Point3f >会得到一个rvecs。

 

tvecs :位移向量;和rvecs一样,也应该为vector tvecs。

 

stdDeviationsIntrinsics :内参数的输出向量。输出顺序为: (fx,fy,cx,cy,k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4,τx,τy) ,如果不估计其中某一个参数,值等于0

 

stdDeviationsExtrinsics :外参数的输出向量。输出顺序: (R1,T1,…,RM,TM) ,M是标定图片的个数, Ri,Ti 是1x3的向量 。

 

perViewErrors 每个标定图片的重投影均方根误差的输出向量。

 

criteria: 迭代优化算法的终止准则

 

flags :标定函数是所采用的模型(重点)”。

可输入如下某个或者某几个参数:

  • CV_CALIB_USE_INTRINSIC_GUESS:使用该参数时,将包含有效的fx,fy,cx,cy的估计值的内参矩阵cameraMatrix,作为初始值输入(已经有标定结果,对结果进行优化),然后函数对其做进一步优化。如果不使用这个参数,用图像的中心点初始化光轴点坐标(cx, cy),使用最小二乘估算出fx,fy(这种求法好像和张正友的论文不一样,不知道为何要这样处理)。注意,如果已知内部参数(内参矩阵和畸变系数),就不需要使用这个函数来估计外参,可以使用solvepnp()函数计算外参数矩阵。
  • CV_CALIB_FIX_PRINCIPAL_POINT:在进行优化时会固定光轴点,光轴点将保持为图像的中心点。当CV_CALIB_USE_INTRINSIC_GUESS参数被设置,保持为输入的值。
  • CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只将fy作为可变量(比值不变,因此fx也同时会变),进行优化计算。当CV_CALIB_USE_INTRINSIC_GUESS没有被设置,fx和fy的实际输入值将会被忽略,只有fx/fy的比值被计算和使用(同时比值也不会被改变)。
  • CV_CALIB_ZERO_TANGENT_DIST:切向畸变系数(P1,P2)被设置为零并保持为零。
  • CV_CALIB_FIX_K1,…,CV_CALIB_FIX_K6:对应的径向畸变系数在优化中保持不变。如果设置了CV_CALIB_USE_INTRINSIC_GUESS参数,就从提供的畸变系数矩阵中得到。否则,设置为0(初次获取内参矩阵可能会把它设置为0)。
  • CV_CALIB_RATIONAL_MODEL(理想模型):启用畸变k4,k5,k6三个畸变参数。使标定函数使用有理模型,返回8个系数。如果没有设置,则只计算其它5个畸变参数。
  • CALIB_THIN_PRISM_MODEL (薄棱镜畸变模型):启用畸变系数S1、S2、S3和S4。使标定函数使用薄棱柱模型并返回12个系数。如果不设置标志,则函数计算并返回只有5个失真系数。
  • CALIB_FIX_S1_S2_S3_S4 :优化过程中不改变薄棱镜畸变系数S1、S2、S3、S4。如果cv_calib_use_intrinsic_guess设置,使用提供的畸变系数矩阵中的值。否则,设置为0。
  • CALIB_TILTED_MODEL (倾斜模型):启用畸变系数tauX and tauY。标定函数使用倾斜传感器模型并返回14个系数。如果不设置标志,则函数计算并返回只有5个失真系数。
  • CALIB_FIX_TAUX_TAUY :在优化过程中,倾斜传感器模型的系数不被改变。如果cv_calib_use_intrinsic_guess设置,从提供的畸变系数矩阵中得到。否则,设置为0。

函数返回

重投影的总的均方根误差。

 

参考原文链接:

(99条消息) 【OpenCV3学习笔记 】相机标定函数 calibrateCamera( ) 使用详解(附相机标定程序和数据)_cv::calibratecamera_ZealCV的博客-CSDN博客