咖啡公司网站建设策划书,手机制作ppt,网站服务设计,做建筑材料的网站有哪些重要说明#xff1a;本文从网上资料整理而来#xff0c;仅记录博主学习相关知识点的过程#xff0c;侵删。
一、参考资料
微信公众号#xff1a;计算机视觉life 专栏#xff1a;#相机标定
Camera Calibration
张正友标定法-完整学习笔记-从原理到实战
二、相机标定相…重要说明本文从网上资料整理而来仅记录博主学习相关知识点的过程侵删。
一、参考资料
微信公众号计算机视觉life 专栏#相机标定
Camera Calibration
张正友标定法-完整学习笔记-从原理到实战
二、相机标定相关介绍
1. 透视投影
用中心投影法将物体投射到投射面上从而获得一种较为接近视觉效果的单面投影图也就是我们看到景物近大远小的一种成像方式。
2. 相机标定的概念
简单来说摄像机标定Camera calibration就是从世界坐标系转换到像素坐标系的过程该过程包括两个阶段建立相机成像几何模型并矫正透镜畸变。
建立相机成像几何模型建立物体从三维世界映射到相机成像平面这一过程中的几何模型。最关键的部分是得到相机的内参和外参。
矫正透镜畸变由于透镜制造工艺产生多种形式的畸变。为了去除畸变计算并利用畸变系数来矫正像差使成像后的图像与真实世界的景象保持一致。
3. 四大坐标系
世界坐标系(world coordinate system)用户定义的三维世界的坐标系为了描述目标物在真实世界里的位置而被引入。单位为米坐标系为 ( X w , Y w , Z w ) (X_w,Y_w,Z_w) (Xw,Yw,Zw)。
相机坐标系(camera coordinate system)在相机上建立的坐标系为了从相机的角度描述物体位置而定义作为沟通世界坐标系和图像/像素坐标系的中间一环。单位为米一般取相机的光学轴为Z轴坐标系为 ( X c , Y c , Z c ) (X_c, Y_c,Z_c) (Xc,Yc,Zc)。
图像物理坐标系(image coordinate system)为了描述成像过程中物体从相机坐标系到图像坐标系的投影透射关系而引入方便进一步得到像素坐标系下的坐标。 单位为毫米坐标原点为相机光轴与图像物理坐标系交点的位置坐标系为 ( x , y ) (x,y) (x,y)。
图像像素坐标系(pixel coordinate system)为了描述物体成像后的像点在数字图像上相片的坐标而引入是我们真正从相机内读取到的信息所在的坐标系。单位为像素坐标原点在左上角坐标系为 ( u , v ) (u,v) (u,v)。
四个坐标系之间的关系如下图所示
其中相机坐标系的Z轴与光轴重合且垂直于图像坐标系平面并通过图像坐标系的原点相机坐标系与图像坐标系之间的距离为焦距f也即图像坐标系原点与焦点重合。像素坐标系平面u-v和图像坐标系平面x-y重合但像素坐标系原点位于图中左上角之所以这么定义目的是从存储信息的首地址开始读写。
4. 四大坐标系的转换 4.1 世界坐标系vs相机坐标系
世界坐标系转换到相机坐标系下这两个坐标系之间的转换属于刚体运动物体只改变两个坐标系中的空间位置平移和朝向旋转而不改变其形状。他们之间的转换关系可以用平移矩阵T和旋转矩阵R来完成这两个矩阵反映了世界坐标系与相机坐标系之间的转换关系合称为外参矩阵 L w L_w Lw。获得了外参矩阵已知世界坐标系中的一点通过转换关系就可以得到此点在相机坐标系中的位置。
变换矩阵由一个旋转矩阵和平移向量组合成的齐次坐标系来表示 [ x C y C z C 1 ] [ R t 0 3 T 1 ] [ x W y W z W 1 ] [ r 1 r 2 r 3 t ] [ x W y W 0 1 ] [ r 1 r 2 t ] [ x W y W 1 ] \left[\begin{array}{c}x_{C}\\y_{C}\\z_{C}\\1\end{array}\right]\left[\begin{array}{cc}Rt\\0_{3}^{T}1\end{array}\right]\left[\begin{array}{c}x_{W}\\y_{W}\\z_{W}\\1\end{array}\right]\left[\begin{array}{cc}r_{1}r_{2}r_{3}t\end{array}\right]\left[\begin{array}{c}x_{W}\\y_{W}\\0\\1\end{array}\right]\left[\begin{array}{cc}r_{1}r_{2}t\end{array}\right]\left[\begin{array}{c}x_{W}\\y_{W}\\1\end{array}\right] xCyCzC1 [R03Tt1] xWyWzW1 [r1r2r3t] xWyW01 [r1r2t] xWyW1 其中R为旋转矩阵t为平移向量。假定世界坐标系中物点所在平面过世界坐标系原点且与 Z w 0 Z_w0 Zw0 轴垂直即棋盘平面与 X w − Y w X_w - Y_w Xw−Yw 平面重合目的在于方便后续计算。其中变化矩阵为 [ R t 0 3 T 1 ] \begin{bmatrix}Rt\\0_3^T1\end{bmatrix} [R03Tt1] 下图表示用R、t将世界坐标系转换到相机坐标系的过程。
4.2 相机坐标系vs图像物理坐标系无畸变
相机坐标系转换到图像物理坐标系下就是将三维的坐标系转换为二维的坐标系也即投影透视过程。如下图所示小孔成像过程针孔面相机坐标系在图像平面图像物理坐标系和物点平面棋盘平面之间所成图像为倒立实像。
但是为了在数学上更方便描述将相机坐标系和图像物理坐标系位置对调没有实际的物理意义只是方便计算变成下图所示
假设相机坐标系中有一点M根据相似三角形原理则在图像物理坐标系下无畸变的成像点P的坐标为 x p f x M z M , y p f y M z M \mathrm{x}_{p}f\frac{x_{M}}{z_{M}},y_{p}f\frac{y_{M}}{z_{M}} xpfzMxM,ypfzMyM 将上式转化为齐次坐标表示形式为 z M [ x p y p 1 ] [ f 0 0 0 0 f 0 0 0 0 1 0 ] [ x M y M z M 1 ] [ f 0 0 0 f 0 0 0 1 ] [ 1 0 0 0 0 1 0 0 0 0 1 0 ] [ x M y M z M 1 ] z_{M}\left[\begin{array}{c}{x_{p}}\\{y_{p}}\\{1}\\\end{array}\right]\left[\begin{array}{ccc}{f}{0}{0}{0}\\{0}{f}{0}{0}\\{0}{0}{1}{0}\\\end{array}\right]\left[\begin{array}{c}{x_{\mathrm{M}}}\\{y_{\mathrm{M}}}\\{z_{\mathrm{M}}}\\{1}\\\end{array}\right]\left[\begin{array}{ccc}{f}{0}{0}\\{0}{f}{0}\\{0}{0}{1}\\\end{array}\right]\left[\begin{array}{ccc}{1}{0}{0}{0}\\{0}{1}{0}{0}\\{0}{0}{1}{0}\\\end{array}\right]\left[\begin{array}{cc}{x_{\mathrm{M}}}\\{y_{\mathrm{M}}}\\{z_{\mathrm{M}}}\\{1}\\\end{array}\right] zM xpyp1 f000f0001000 xMyMzM1 f000f0001 100010001000 xMyMzM1
4.3 相机坐标系vs图像物理坐标系有畸变
请参考章节相机畸变模型
4.4 图像物理坐标系vs图像像素坐标系
以一个形象的例子说明图像物理坐标系与图像像素坐标系之间的区别。物理坐标系是一个连续的概念它以毫米为单位就好比某一观众在电影院里的具体坐标值为(3.4, 5.9)而像素坐标系是一个离散的概念它是以像素为单位之鞥你是整数值坐标就好比某一观众在电影院里的位置是第三排第六列。另外需要注意的是这两个坐标系的原点位置不相同物理坐标系的原点是相机光轴与图像物理坐标系的交点通常称其为主点而像素坐标系则以像素图像的左上角为原点。
由于定义的图像像素坐标系原点与图像物理坐标系原点不重合假设图像物理坐标系原点在图像像素坐标系下的坐标为 ( u 0 , v 0 ) (u_0, v_0) (u0,v0)每个像素点在图像物理坐标系x轴、y轴方向的尺寸为 d x 、 d y d_x、d_y dx、dy且像点在图像物理坐标系下的坐标为 ( x c , y c ) (x_c,y_c) (xc,yc)可得想点在图像坐标系下的坐标为 u x c d x u 0 , v y c d y v 0 u\frac{x_{c}}{d_{x}}u_{0},\mathbf{v}\frac{y_{c}}{d_{y}}\mathbf{v}_{0} udxxcu0,vdyycv0 化为齐次坐标系的表现形式为 [ u ν 1 ] [ 1 / d x 0 u 0 0 1 / d y v 0 0 0 1 ] [ x c y c 1 ] \begin{bmatrix}u\\\nu\\1\end{bmatrix}\begin{bmatrix}1/d_x0u_0\\01/d_yv_0\\001\end{bmatrix}\begin{bmatrix}x_c\\y_c\\1\end{bmatrix} uν1 1/dx0001/dy0u0v01 xcyc1
5. 相机畸变模型
透镜的畸变主要分为径向畸变和切向畸变还有薄透镜畸变等但都没有径向畸变和切向畸变影响显著因此一般只考虑径向畸变k和切向畸变p。一共需要5个畸变参数k1、k2、k3、p1和p2来描述透镜畸变其中径向畸变有3个参数 k1、k2、k3切向畸变有2个参数 p1、p2。
5.1 径向畸变
径向畸变是由于透镜形状的制造工艺导致的越向透镜边缘移动径向畸变越严重。下图所示是径向畸变的两种类型桶型畸变(k0)和枕型畸变(k0)。
当k0时r越大点离中心越远畸变量越大r越小畸变量越小呈枕型。当k0时r越大点离中心越远畸变量越小r越小畸变量越大呈桶型。
实际情况中常用r0处的泰勒级数展开的前几项来近似描述径向畸变。矫正径向畸变前后的坐标关系为 { x d i s t o r t e d x p ( 1 k 1 r 2 k 2 r 4 k 3 r 6 ) y d i s t o r t e d y p ( 1 k 1 r 2 k 2 r 4 k 3 r 6 ) \begin{cases}\mathbf{x}_{distorted}x_p(1k_1r^2k_2r^4k_3r^6)\\y_{distorted}y_p(1k_1r^2k_2r^4k_3r^6)\end{cases} {xdistortedxp(1k1r2k2r4k3r6)ydistortedyp(1k1r2k2r4k3r6) 由此可知对于径向畸变有3个径向畸变参数k1、k2、K3需要求解。 研究表明径向畸变参数一般选择2或3个k值可以获得较好结果。如果k取得再多影响不会很大可以忽略也有可能导致效果不好。 5.2 切向畸变
切向畸变是由于透镜和CMOS或者CCD的安装位置误差导致。由此如果存在切向畸变一个矩形被投影到成像平面时很可能会变成一个梯形。切向畸变需要2个额外的畸变参数p1和p2来描述矫正前后的坐标关系为 { x d i s t o r t e d x p [ 2 p 1 x p y p p 2 ( r 2 2 x p 2 ) ] y d i s t o r t e d y p [ p 1 ( r 2 2 y p 2 ) 2 p 2 x p y p ] \begin{cases}\mathbf{x}_{distorted}x_{p}[2p_{1}x_{p}y_{p}p_{2}(r^{2}2{x_{p}}^{2})]\\\mathbf{y}_{distorted}y_{p}[p_{1}(r^{2}2{y_{p}}^{2})2p_{2}x_{p}y_{p}]\end{cases} {xdistortedxp[2p1xpypp2(r22xp2)]ydistortedyp[p1(r22yp2)2p2xpyp]
6. 相机标定参数
内参 焦距长度 f x 、 f y f_x、f_y fx、fy 主点光心像素坐标 c x 、 c y c_x、c_y cx、cy 畸变系数 k 1 , k 2 , k 3 , p 1 , p 2 k_{1},k_{2},k_{3},p_{1,}p_{2} k1,k2,k3,p1,p2 c a m e r a matri x [ f x 0 c x 0 f y c y 0 0 1 ] camera\textit{matri}x\begin{bmatrix}f_x0c_x\\0f_yc_y\\001\end{bmatrix} cameramatrix fx000fy0cxcy1 D i s t o r t i o n c o e f f i c i e n t s ( k 1 k 2 p 1 p 2 k 3 ) Distortion \ coefficients (k_1 \ k_2 \ p_1 \ p_2 \ k_3) Distortion coefficients(k1 k2 p1 p2 k3)
外参
旋转矩阵R平移矩阵T。
7. 单应矩阵
张正友标定算法原理详解
7.1 引言
图像像素坐标系与世界坐标系之间的坐标映射关系公式如下 [ u ν 1 ] s [ f x γ u 0 0 f y ν 0 0 0 1 ] [ r 1 r 2 t ] [ x W y W 1 ] \begin{bmatrix}u\\\nu\\1\end{bmatrix}s\begin{bmatrix}f_x\gammau_0\\0f_y\nu_0\\001\end{bmatrix}\begin{bmatrix}r_1r_2t\end{bmatrix}\begin{bmatrix}x_W\\y_W\\1\end{bmatrix} uν1 s fx00γfy0u0ν01 [r1r2t] xWyW1 其中u、v表示图像像素坐标系中的坐标s表示尺度因子 f x 、 f y 、 u 0 、 v 0 、 γ f_x、f_y、u_0、v_0、\gamma fx、fy、u0、v0、γ 表示5个相机内参R、t表示相机外参 X w 、 Y w 、 Z w X_w、Y_w、Z_w Xw、Yw、Zw 表示世界坐标系中的坐标棋盘平面位于世界坐标系中 Z w 0 Z_w0 Zw0 的平面。
7.2 单应性的概念
单应性Homography变换描述物体在世界坐标系和图像像素坐标系之间的位置映射关系这个变换矩阵称为单应性矩阵。在上述式子中单应性矩阵定义为 H s [ f x γ u 0 0 f y ν 0 0 0 1 ] [ r 1 r 2 t ] s M [ r 1 r 2 t ] Hs\begin{bmatrix}f_x\gammau_0\\0f_y\nu_0\\001\end{bmatrix}\begin{bmatrix}r_1r_2t\end{bmatrix}sM\begin{bmatrix}r_1r_2t\end{bmatrix} Hs fx00γfy0u0ν01 [r1r2t]sM[r1r2t] 其中M是相机内参矩阵 M [ f x γ u 0 0 f y ν 0 0 0 1 ] M\left[\begin{array}{ccc}f_x\gammau_0\\0f_y\nu_0\\001\end{array}\right] M fx00γfy0u0ν01 单应性矩阵同时包含了相机内参和外参。
7.3 单应性的应用
7.3.1 图像矫正
用单应性矩阵进行图像矫正最少需要四个对应点。
7.3.2 视角变换
单应性矩阵可以方便的将普通视图转换成鸟瞰图如下图所示左边是普通视图右边是鸟瞰图
7.3.3 图像拼接
既然单应性矩阵可以进行视角转换那么把不同角度拍摄的图像都转换到同一视角下就可以实现图像拼接了。如下图所示通过单应性矩阵H可以将image1和image2都变换到同一个平面。
7.3.4 增强现实AR
平面二维标图案marker经常用来做AR展示根据marker不同视角下的图像可以方便的得到虚拟物体的位置姿态并进行现实如下图所示
7.4 单应性矩阵的原理
假设两张图像中的对应点的齐次坐标为 ( x ′ , y ′ , 1 ) (x^{\prime},y^{\prime},1) (x′,y′,1)单应性矩阵H定义为 H [ h 11 h 12 h 13 h 21 h 22 h 23 h 31 h 32 h 33 ] H\left[\begin{array}{ccc}h_{_{11}}h_{_{12}}h_{_{13}}\\h_{_{21}}h_{_{22}}h_{_{23}}\\h_{_{31}}h_{_{32}}h_{_{33}}\end{array}\right] H h11h21h31h12h22h32h13h23h33 则有 [ x ′ y ′ 1 ] ∼ [ h 11 h 12 h 13 h 21 h 22 h 23 h 31 h 32 h 33 ] [ x y 1 ] \left[\begin{array}{c}x\\y\\1\end{array}\right]\sim\left[\begin{array}{ccc}h_{11}h_{12}h_{13}\\h_{21}h_{22}h_{23}\\h_{31}h_{32}h_{33}\end{array}\right] \begin{bmatrix}x\\y\\1\\\end{bmatrix} x′y′1 ∼ h11h21h31h12h22h32h13h23h33 xy1 矩阵展开后有3个等式将第三个等式带入前两个等式中可得 x ′ h 11 x h 12 y h 13 h 31 x h 32 y h 33 x\frac{h_{11}xh_{12}yh_{13}}{h_{31}xh_{32}yh_{33}} x′h31xh32yh33h11xh12yh13 y ′ h 21 x h 22 y h 23 h 31 x h 32 y h 33 y\frac{h_{21}xh_{22}yh_{23}}{h_{31}xh_{32}yh_{33}} y′h31xh32yh33h21xh22yh23
也就是一个点对对应两个等式。
将H添加约束条件使得H矩阵模变为1即 ∣ ∣ H ∣ ∣ 1 ||{H}||1 ∣∣H∣∣1如下 x ′ h 11 x h 12 y h 13 h 31 x h 32 y h 33 ( 1 ) x\frac{h_{11}xh_{12}yh_{13}}{h_{31}xh_{32}yh_{33}} \quad (1) x′h31xh32yh33h11xh12yh13(1) y ′ h 21 x h 22 y h 23 h 31 x h 32 y h 33 ( 2 ) y\frac{h_{21}xh_{22}yh_{23}}{h_{31}xh_{32}yh_{33}} \quad (2) y′h31xh32yh33h21xh22yh23(2) h 11 2 h 12 2 h 13 2 h 21 2 h 22 2 h 23 2 h 31 2 h 32 2 h 33 2 1 h_{11}^2h_{12}^2h_{13}^2h_{21}^2h_{22}^2h_{23}^2h_{31}^2h_{32}^2h_{33}^21 h112h122h132h212h222h232h312h322h3321
对上式(1)、(2)乘以分母展开得 ( h 31 x h 32 y h 33 ) x ′ h 11 x h 12 y h 13 \left(h_{31}xh_{32}yh_{33}\right)x^{\prime}h_{11}xh_{12}yh_{13} (h31xh32yh33)x′h11xh12yh13 ( h 31 x h 32 y h 33 ) y ′ h 21 x h 22 y h 23 \left(h_{31}xh_{32}yh_{33}\right)y^{\prime}h_{21}xh_{22}yh_{23} (h31xh32yh33)y′h21xh22yh23
整理得到 h 11 x h 12 y h 13 − h 31 x x ′ − h 32 y x ′ − h 33 x ′ 0 h_{11}xh_{12}yh_{13}-h_{31}xx^{\prime}-h_{32}yx^{\prime}-h_{33}x^{\prime}0 h11xh12yh13−h31xx′−h32yx′−h33x′0 h 21 x h 22 y h 23 − h 31 x y ′ − h 32 y y ′ − h 33 y ′ 0 h_{21}xh_{22}yh_{23}-h_{31}xy-h_{32}yy-h_{33}y0 h21xh22yh23−h31xy′−h32yy′−h33y′0
假设我们得到两幅图片中对应的N个点对特征点匹配对可以得到如下线性方程组
写成矩阵形式 2 N x 9 9 x 1 2 N x 1 A h 0 \begin{array}{cccc}\mathbf{2Nx9}\mathbf{9x1}\mathbf{2Nx1}\\\mathbf{A}\mathbf{h}\mathbf{0}\end{array} 2Nx9A9x1h2Nx10 在真实的应用场景中计算的点对中都会包含噪声。比如点的位置偏差几个像素甚至出现特征点对误匹配的现象如果只是用4个点对来计算单应性矩阵会出现很大的误差。因此为了使得计算更精确一般都会使用远大于4个点对来计算单应性矩阵。另外上述的线性方程组采用直接线性解法通常很难得到最优解所以实际使用中一般会使用其他优化方法如奇异值分解、Levenberg-MarquaratLM算法等进行求解。
7.5 单应性矩阵的计算流程
根据打印的棋盘标定图和拍摄的照片来计算单应性矩阵H。其大致流程如下 打印一张棋盘格标定图纸将其贴在平面物体的表面 拍摄一组不同方向棋盘格的图片可以通过移动相机来实现也可以移动标定图片来实现 对于每张拍摄的棋盘图片检测图片中所有的棋盘格的角点。 因为棋盘标定图纸中所有角点的世界坐标是已知的这些角点对应的图像像素坐标也是已知的。如果有N4个配对点对就可以根据LM等优化方法得到其单应性矩阵H匹配点对越多计算结果越鲁棒。计算单应性矩阵一般不需要自己写函数实现在OpenCV中有现成的函数可以调用对应的C函数是 Mat findHomography(InputArray srcPoints, InputArray dstPoints, int method0, double ransacReprojThreshold3, OutputArray masknoArray() )从函数来看只要输入匹配点对指定具体计算方法即可得到单应性矩阵。
三、张正友相机标定法
1. 引言
张正友博士在1999年发表在国际顶级会议ICCV的论文《Flexible Camera Calibration By Viewing a Plane From Unknown Orientations》提出一种利用平面棋盘格进行相机标定的实用方法。该方法介于摄影标定法和自标定法之间既客服了摄影标定法需要的高精度三维标定物的缺点又解决了自标定法鲁棒性差的难题。标定过程仅需要一个打印出来的棋盘格并从不同方向拍摄几组图像即可任何人都可以自己制作标图案。不仅实用灵活方便而且精度很高鲁棒性好。因此很快被全世界广泛采用极大的促进了三维计算机视觉从实验室走向真实世界的进程。
张正友标定法使用二维方格组成的标定板进行标定采集标定板不同位姿图片提取图片中角点像素坐标通过单应矩阵计算出相机的内外参数初始值利用非线性最小二乘法估计畸变系数最后使用极大似然估计法优化参数。该方法操作简单精度高满足大部分的场合。
2. 张正友简介
张正友博士是世界著名的计算机视觉和多媒体技术的专家ACM FellowIEEE Fellow。现任微软研究院视觉计算组高级研究员。他在立体视觉、三维重建、运动分析、图像配准、摄像机标定等方面都有开创性的贡献。
3. 棋盘格标定板
3.1 棋盘格标定板简介
棋盘格标定板是一块由黑白方块间隔组成的标定板用来作为相机标定的标定物从真实世界映射到数字图像内的对象。之所以使用棋盘作为标定物是因为相对于复杂的三维物体平面棋盘模式更容易处理。与此同时二维物体相对于三维物体会缺少一部分信息通过多次改变棋盘的方位来捕捉图像以获得更丰富的坐标信息。如下图所示是相机在不同方向下拍摄的同一个棋盘格标定板的图像。
3.2 获取棋盘格标定板
3.2.1 方格标定板 标定板的尺寸w9h6。 3.2.2 圆形标定板 标定板的尺寸w11h4。 标定板的尺寸w17h6。 3.2.3 ChAruco标定板
7X5 ChAruco boardsquare size: 30 mm marker size: 15 mmaruco dict: DICT_5X5_100page width: 210 mm, page height: 297 mm。
3.2.4 生成棋盘格标定板
Create calibration pattern
用python生成自定义的标定板下载python脚本文件gen_pattern.py
3.3 角点
角点就是黑白棋盘格交叉点如下图所示中间品红的圆圈内就是一个角点。
如下图所示X方向有8个角点Y方向有3个角点。
3.4 内角点
角点是指黑白色相接的方块定点部分内角点是不与标定板边缘接触的内部角点。
patternSize:(w,h)棋盘上每一排和每一列的内角数。w棋盘板一行上黑白块的数量-1h棋盘板一列上黑白块的数量-1例如9x4的棋盘板则(w,h)(8,3)
3.5 棋盘格标定板坐标系
棋盘格标定板坐标系默认采用平面标定模式即Z轴都为零。
定义棋盘格标定板位于世界坐标系 Z w 0 Z_w0 Zw0 的平面上世界坐标系的原点位于棋盘格标定板的固定一角比如下图中的黄色点。图像像素坐标系的原点位于图像左上角。
写坐标时要保证Z轴为0按照先X变化后Y变化从小到大的顺序写。如果棋盘标定板的网格尺寸为5cm世界坐标系下的坐标可以写为(0,0,0),(5,0,0), (10,0,0)…(0,5,0), (5,5,0), (10,5,0),…
4. 张正友标定法计算流程
采用棋盘格标定板进行标定需要找到棋盘格内角点根据棋盘格内角点在图像像素坐标系下的坐标和各点对应的世界坐标系下的坐标拍摄多个位置的棋盘格多点求解相机内外参。
使用OpenCV进行张正友标定法计算流程如下
准备标定图片理论上至少4张一般在多个角度采集20张左右提取标定板的角点并计算出标定板上角点的坐标一般将标定板当作 X-Y 平面Z为0相机标定通过张正友标定法计算出内参外参以及畸变参数对标定结果进行评价一般通过重投影误差进行评价查看标定效果利用标定结果对棋盘图进行矫正。
5. 核心函数
cornerSubPix()
OpenCV中feature2D学习——亚像素级角点检测cornerSubPix
OpenCV3 亚像素角点检测cornerSubPix() 功能亚像素级别的角点检测将内角点位置精确到亚像素级精度。 void cornerSubPix(InputArray image, InputOutputArray corners, Size winSize, Size zeroZone, TermCriteria criteria);参数解释 image 表示输入原始的棋盘标定板图像图像矩阵是输入参数。图像矩阵必须是8-bit灰度图或者彩色图像在图像传入函数之前一般经过灰度处理还有滤波操作 corners 表示内角点坐标既是输入参数也是输出参数。把 findChessboardCorners() 输出的内角点作为该函数的输入corners经过亚像素级别的内角点检测之后输出corners winSize 表示搜索窗口边长的一半。例如如果winSizeSize(5, 5)则一个大小为 ( 5 ∗ 2 1 ) ∗ ( 5 ∗ 2 1 ) 11 ∗ 11 (5*21)*(5 *21)11*11 (5∗21)∗(5∗21)11∗11 的搜索窗口将被使用 zeroZone 表示搜索区域中间的dead region边长的一半有时用于避免自相关矩阵的奇异性。如果值设为(-1,-1)则表示没有这个区域 criteria 表示角点亚像素级精准化迭代过程的终止条件。可选的值有 cv::TermCriteria::MAX_ITER 表示迭代次数达到最大次数时停止cv::TermCriteria::EPS 表示角点位置变化已经达到最小值时停止迭代。 二者均使用 cv::TermCriteria() 构造函数进行指定且可以组合使用。 //指定亚像素计算迭代条件
cv::TermCriteria criteria cv::TermCriteria(cv::TermCriteria::MAX_ITER cv::TermCriteria::EPS, // 终止条件40, // 最大次数0.01); // 最小值findChessboardCorners()
findChessboardCorners()角点检测详解 功能角点检测获取棋盘格标定板内角点位置。 返回值所有角点被检测出且以一定顺序排列返回非0数否则返回0。 // 函数原型
findChessboardCorners(InputArray image,Size patternSize,OutputArray corners,int flags);参数解释 image 表示输入原始的棋盘标定板图像图像矩阵是输入参数。图像矩阵必须是8-bit灰度图或者彩色图像在图像传入函数之前一般经过灰度处理还有滤波操作 patternSize 表示内角点的size是输入参数。 数据类型Size patternSize(w,h)w、h分别表示棋盘上每一排和每一列的内角数。 w棋盘格标定板一行上黑白块的总数-1h棋盘格标定板一列上黑白块的总数-1。 例如10x6的棋盘格标定板则(w,h)(9,5)。 注意根据内角点的尺寸确定标定板的方向。具体来说w和h不相同该函数可辨别标定板的方向如果w和h相同该函数每次画出的角点起始位置会发生变化不利于标定。 corners 表示检测到的内角点的输出数组输出参数。 数据类型vectorvectorpoint2f。 flags 标志位是输入参数有默认值。 CV_CALIB_CB_ADAPTIVE_THRESH函数默认方式使用自适应阈值法对图像进行二值化而不是使用一个固定的阈值CV_CALIB_CB_NORMALIZE_IMAGE在利用固定阈值或自适应阈值法二值化图像之前调用EqualizeHist()函数进行图像归一化处理利用直方图均衡化图像CV_CALIB_CB_FILTER_QUADS二值化完成后函数开始定位图像中的四边形这里不应该称之为正方形因为存在畸变。使用额外的标准(如轮廓面积周长正方形形状)来过滤掉在轮廓检索阶段提取的假四边形从而使得角点检测更准确更严格CALIB_CB_FAST_CHECK快速检测选项对图像进行一个快速检查机制以查找棋盘板的角点。对于检测角点极可能不成功检测的情况这个标志位可以使函数效率提升。 注意标志位可组合使用。CALIB_CB_FAST_CHECK一般用于快速检测很有可能检测不成功特别是棋盘光线不均匀时。总体来说CV_CALIB_CB_ADAPTIVE_THRESH是最可能检测到棋盘格的方式。组合使用推荐CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_NORMALIZE_IMAGE如果默认方式或这个组合方式检测不到角点基本就需要重新采图了。
该函数的功能是判断图像内是否包含完整的棋盘格如果能完全检测出来就把角点位置顺序从左到右从上到下记录下来并返回非0数否则返回0。这里对 patternSize 参数要求非常严格函数必须检测出相同的size才会返回非0否则返回0。
该函数检测的角点坐标是不准确的获得角点精确坐标可使用 cornerSubPix() 函数进行角点亚像素提取使用方法可参考博客角点检测及优化函数使用
drawChessboardCorners() 功能把检测到的角点在原图中画出来。 calibrateCamera()
OpenCV函数用法之calibrateCamera 功能相机标定。 double calibrateCamera(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints,Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags0);参数解释 objectPoints 表示世界坐标系下的点即3D points。 数据类型为std::vectorstd::vectorcv::Point3f objectPoints第一层vector表示每一个视角每一张图第二层vector表示每一个点。 imagePoints 表示其对应图像像素坐标系下的点即2D points。这个值可以通过 findChessboardCorners() 函数从图像中获得。 数据类型为std::vectorstd::vectorcv::Point2f imagePoints第一层vector表示每一个视角第二层vector表示每一个内角点。 imageSize 表示图像的大小在计算相机的内参和畸变矩阵需要用到 cameraMatrix 表示相机内参矩阵该矩阵大小为 3x3。该矩阵由相机标定输出的结果。 数据类型为cv::Mat cameraMatrix distCoeffs 表示畸变矩阵具体尺寸取决于参数 flags。该矩阵由相机标定输出的结果。 数据类型cv::Mat distCoeffs rvecs 表示旋转向量。每个 vectorPoint3f 会得到一个 rvecs每个 vec 为 3x1可以用 Rodrigues() 函数转换为3x3的旋转矩阵。 数据类型vectorcv::Mat rvecs tvecs 表示平移向量和rvecs 一样每个 vec 为3x1。 数据类型vectorcv::Mat tvecs 参数 rvecs 和 tvecs 是相机外参对于每一个视图都可以将其世界坐标系转成相机坐标系。 flags 表示标定时所采用的参数包括决定是否使用初始值、畸变矩阵的参数个数等。有如下参数 CV_CALIB_USE_INTRINSIC_GUESS使用该参数时在cameraMatrix矩阵中应该有fx,fy,cx,cy的估计值。否则的话将初始化图像的中心点(cx,cy并使用最小二乘估算出fxfyCV_CALIB_FIX_PRINCIPAL_POINT在进行优化时会固定光轴点。当CV_CALIB_USE_INTRINSIC_GUESS参数被设置光轴点将保持在中心或者某个输入的值CV_CALIB_FIX_ASPECT_RATIO固定fx/fy的比值只将fy作为可变量进行优化计算。当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_RATIONAL_MODEL计算k4k5k6三个畸变参数。如果没有设置则只计算其它5个畸变参数。
6. 示例代码
用OpenCV实现张正友标定流程。
6.1 C实现
张正友视觉标定算法学习笔记
示例一
对多张视图进行标定。
#include iostream
#include opencv2/opencv.hpp
#include boost/filesystem.hppstd::vectorstd::string get_all_image_file(std::string image_folder_path){boost::filesystem::path dirpath image_folder_path;boost::filesystem::directory_iterator end;std::vectorstd::string files;for (boost::filesystem::directory_iterator iter(dirpath); iter ! end; iter){boost::filesystem::path p *iter;files.push_back(dirpath.string() / p.leaf().string());}std::sort(files.begin(),files.end());return files;
}std::vectorcv::Mat get_all_iamge(std::string image_folder_path)
{std::vectorcv::Mat images;std::vectorstd::string image_files_path get_all_image_file(image_folder_path);for(int i0; i image_files_path.size() ;i){cv::Mat image;image cv::imread(image_files_path[i]);images.push_back(image);}return images;
}int find_chessboard(cv::Mat image, std::vectorcv::Point2f image_points, cv::Size board_size)
{if (0 findChessboardCorners(image, board_size, image_points)){std::coutcan not find chessboard corners!\n;return 0;}else{cv::Mat view_gray;cv::cvtColor(image,view_gray,cv::COLOR_RGB2GRAY);//对粗提取的角点进行亚像素精确化cv::find4QuadCornerSubpix(view_gray,image_points,cv::Size(11,11)); //int nChessBoardFlags cv::CALIB_CB_EXHAUSTIVE | cv::CALIB_CB_ACCURACY;//bool bFindResult findChessboardCornersSB(view_gray,board_size,image_points,nChessBoardFlags ); //Opencv4 识别棋盘格方法比opencv3有较大提升}return 1;
}int init_chessboard_3dpoints(cv::Size board_size, std::vectorcv::Point3f points, float point_size)
{cv::Size2f square_size cv::Size2f(point_size,point_size);for (int i0;iboard_size.height;i){for (int j0;jboard_size.width;j){cv::Point3f realPoint;realPoint.x j*square_size.width;realPoint.y i*square_size.height;realPoint.z 0;points.push_back(realPoint);}}return 0;
}void calib_monocular(std::vectorcv::Mat images){cv::Size image_size;cv::Size board_size(11,4);std::vectorcv::Mat images_tvecs_mat;std::vectorcv::Mat images_rvecs_mat;image_size.width images[0].cols;image_size.height images[0].rows;std::vectorstd::vectorcv::Point2f images_points;// 识别所有图片的棋盘格for(int i0;iimages.size();i){std::vectorcv::Point2f image_points;if(find_chessboard(images[i],image_points,board_size)0){images_points.push_back(image_points);}}std::vectorcv::Point3f image_points_in3d;// 计算棋盘格角点在棋盘格坐标系中的位置init_chessboard_3dpoints(board_size,image_points_in3d,0.045); // 0.045为棋盘格一个格子的大小std::vectorstd::vectorcv::Point3f images_points_in3d;// 生成所有识别出的标定板对应在各自棋盘格坐标系中的位置for(int i0;iimages_points.size();i){images_points_in3d.push_back(image_points_in3d);}cv::Mat intrinsic,distortion;// 使用张正友标定法计算内参畸变以及外参cv::calibrateCamera(images_points_in3d,images_points,image_size,intrinsic,distortion,images_rvecs_mat,images_tvecs_mat);
}int main(int argc, char *argv[])
{std::string image_file_path argv[1];std::vectorcv::Mat images get_all_iamge(image_file_path);calib_monocular(images);return 0;
}示例二
对单张视图进行标定。
int cols 10;
int rows 7;
float distance 30; //间距30mmcv::Size patternSize(cols,rows);
std::vectorcv::Point2f corners;
std::vectorstd::vectorcv::Point2f cornersVect;
std::vectorcv::Point3f worldPoints;
std::vectorstd::vectorcv::Point3f worldPointsVect;for (int i0;icols;i)
{for (int j0;jrows;j){worldPoints.push_back(cv::Point3f(i*distance,j*distance,0));}
}bool findcv::findChessboardCorners(image,patternSize,corners);
cv::drawChessboardCorners(image,patternSize,corners,find);
cv::Mat cameraMatirx,distCoeffs;
std::vectorcv::Mat rvecs,tvecs,rvecs2,tvecs2;
if (find)
{ cornersVect.push_back(corners);worldPointsVect.push_back(worldPoints);cv::calibrateCamera(worldPointsVect,cornersVect,image.size(),cameraMatirx,distCoeffs,rvecs,tvecs);
}6.2 Python实现
[学习笔记]python-Opencv cv2.findChessboardCorners() 的基本使用
示例一
对单张视图进行标定。
import numpy as np
import cv2
import matplotlib.pyplot as plt
import matplotlib.image as mpimgfnamecalibration_test.pngimagecv2.imread(fname)
# plt.imshow(image)
# plt.show()graycv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
plt.imshow(gray,cmapgray)
plt.show()# Find the chessboard corners
nx8
ny6
ret, corners cv2.findChessboardCorners(gray, (nx, ny), None)print(ret:,ret)
# print(len(corners))# If found, draw corners
if ret True:# Draw and display the cornerscv2.drawChessboardCorners(image, (nx, ny), corners, ret)plt.imshow(image)如下图所示9x7的棋盘格标定板一行棋盘格为9一列棋盘格为7则内角点 patternSize(w,h) 中的w8,h6。
示例二
对单张视图进行标定。
import numpy as np
import cv2 as cv
import glob# termination criteria
#
criteria (cv.TERM_CRITERIA_MAX_ITER cv.TERM_CRITERIA_EPS, 30, 0.001)# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)objp
[[0 0 0],
[0 0 0],
...,
[0 0 0]], (42, 3)objp np.zeros((6*7,3), np.float32)
np.mgrid[0:7,0:6] array([
[[0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6]],[[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5]]]), (2, 7, 6)objp array([
[0 0 0],
[1 0 0],
[2 0 0],
...,
[6 5 0]], (42, 3)objp[:,:2] np.mgrid[0:7,0:6].T.reshape(-1,2)# Arrays to store object points and image points from all the images.
objpoints [] # 3d point in real world space
imgpoints [] # 2d points in image plane.images glob.glob(*.jpg)
for fname in images:img cv.imread(fname)gray cv.cvtColor(img, cv.COLOR_BGR2GRAY)# Find the chess board cornersret, corners cv.findChessboardCorners(gray, (7,6), None)# If found, add object points, image points (after refining them)if ret True:objpoints.append(objp)corners2 cv.cornerSubPix(gray,corners, (11,11), (-1,-1), criteria)imgpoints.append(corners2)# Draw and display the cornerscv.drawChessboardCorners(img, (7,6), corners2, ret)cv.imshow(img, img)cv.waitKey(500)
cv.destroyAllWindows()# Calibrationcamera matrix: mtx
distortion coefficients: dist
rotation vectors: rvecs
translation vectors: tvecsret, mtx, dist, rvecs, tvecs cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)if ret True:# Re-projection Errormean_error 0for i in range(len(objpoints)):imgpoints2, _ cv.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)error cv.norm(imgpoints[i], imgpoints2, cv.NORM_L2)/len(imgpoints2)mean_error errorprint( total error: {}.format(mean_error/len(objpoints)) )如下图所示8x7的棋盘格标定板一行棋盘格为9一列棋盘格为7则内角点 patternSize(w,h) 中的w7,h6。
四、相关经验
opencv标定实现总结(圆点棋盘格和非对称圆点)