针孔相机的标定原理与实现

1. 什么是相机标定?

为了确定空间物体表面上的某点位置和图像中对应点像素坐标位置之间的关系,必须建立转换的模型。这个模型也就是相机参数。计算相机参数的过程称为相机标定。

2. 相机标定的方法分类?

相机标定方法可分成以下三类:

  1. 传统的相机标定
  2. 自标定
  3. 基于主动视觉的标定

3. 针孔相机的模型是怎样的?

在物体和平面之间放一块带着小孔的障碍物,光线通过小孔后会在平面上呈现一个倒立的像。这个简单的模型就是针孔相机模型。如下图所示:
在这里插入图片描述
将上面的模型更加规范化。
针孔被称为相机中心: O O O
平面被称为成像平面(image plane): Π \Pi Π
成像平面和针孔之间的距离被称为焦距(focal length): f f f
从针孔出发垂直于成像平面的轴被称为光轴
相机坐标系(camera coordinate) [ i j k ] [i j k] [ijk],原点位于镜头光心处,k轴为光轴。
有时,为了方便计算,将成像平面放在针孔和物体之间,称为虚拟成像平面。
在这里插入图片描述
假设 P P P的坐标为 ( x , y , z ) (x,y,z) (x,y,z) P ′ P' P P P P的投影,坐标为 ( x ′ , y ′ ) (x',y') (x,y),那么根据相似三角形对边成比例原则。有
x x ′ = z f \frac{x}{x'}=\frac{z}{f} xx=fz以及 y y ′ = z f \frac{y}{y'}=\frac{z}{f} yy=fz
在这里插入图片描述
P ′ = ( x ′ , y ′ ) = ( f x z , f y z ) P'=(x',y')=(f\frac{x}{z}, f\frac{y}{z}) P=(x,y)=(fzx,fzy)

4. 相机矩阵的参数介绍

4.1 内参矩阵 K K K

K = [ α 0 c x 0 β c y 0 0 1 ] K=\begin{bmatrix} \alpha&0&c_x\\ 0&\beta&cy\\ 0&0&1\\ \end{bmatrix} K=α000β0cxcy1

  1. 参数 ( c x , c y ) (c_x,c_y) (cx,cy)是平移向量,如上图所示,成像平面的中心点是 C ′ C' C,而数字图像的坐标原点通常是在成像平面上图像的左上角。所以 C ′ C' C在数字图像上位于图像的中心。
    P ′ = ( x ′ , y ′ ) = ( f x z + c x , f y z + c y ) P'=(x',y')=(f\frac{x}{z}+c_x, f\frac{y}{z}+c_y) P=(x,y)=(fzx+cx,fzy+cy)
    在这里插入图片描述

  2. 数字图像使用像素表示的,成像平面上的像大小是用物理长度度量的。我们用单位长度(厘米)包含的像素个数来描述像素的密度(pixels/cm)。记 k k k表示水平方向的像素密度, l l l表示垂直方向的像素密度。如果 k = l k=l k=l则表示像素是个方形像素。
    像素密度 × \times ×物理位置=像素位置
    所以 P ′ = ( x ′ , y ′ ) = ( k f x z + c x , l f y z + c y ) P'=(x',y')=(kf\frac{x}{z}+c_x,lf\frac{y}{z}+c_y) P=(x,y)=(kfzx+cx,lfzy+cy) α = k f , β = l f \alpha=kf,\beta=lf α=kf,β=lf
    P ′ = ( x ′ , y ′ ) = ( α x z + c x , β y z + c y ) P'=(x',y')=(\alpha \frac{x}{z}+c_x,\beta \frac{y}{z}+c_y) P=(x,y)=(αzx+cx,βzy+cy)
    以齐次坐标的形式进行表示:
    P ′ = ( x ′ y ′ 1 ) = ( α x z + c x β y z + c y 1 ) = ( α x + z c x β y + z c y z ) = ( α 0 c x 0 0 β c y 0 0 0 1 0 ) ( x y z 1 ) = K [ I 0 ] P P'=\begin{pmatrix}x'\\y'\\1\\\end{pmatrix}=\begin{pmatrix}\alpha \frac{x}{z}+c_x\\\beta \frac{y}{z}+c_y\\1\\\end{pmatrix}=\begin{pmatrix} \alpha x+zc_x\\\beta y+zc_y\\z \end{pmatrix}= \begin{pmatrix} \alpha&0&c_x&0\\0&\beta&c_y&0\\ 0&0&1&0 \end{pmatrix} \begin{pmatrix} x\\y\\z\\1 \end{pmatrix}=K\begin{bmatrix} I&0 \end{bmatrix}P P=xy1=αzx+cxβzy+cy1=αx+zcxβy+zcyz=α000β0cxcy1000xyz1=K[I0]P

4.2 外参矩阵 T T T

T = [ R 3 × 3 T 3 × 1 0 1 ] T=\begin{bmatrix} R_{3\times3}&T_{3\times1}\\0&1 \end{bmatrix} T=[R3×30T3×11]上面讨论的内参矩阵都是基于相机坐标系进行的,有了内参矩阵,我们就可以把相机坐标系下的 P P P点转化成像素坐标系下的 P ′ P' P。而如果物体的坐标是任意给定的世界坐标,则需要把世界坐标转化成相机坐标。外参矩阵就是干这个活的。
所以世界坐标系的坐标 P w P_w Pw经过外参矩阵转换后就成为了相机坐标系下的坐标 P P P
P = T P w P=TP_w P=TPw
总结:
P ′ = K [ I 0 ] T P w = M 3 × 4 P w P'=K \begin{bmatrix} I&0 \end{bmatrix}TP_w=M_{3\times4}P_w P=K[I0]TPw=M3×4Pw

5. 针孔相机标定的原理

相机矩阵 M M M的未知参数有11个,理论上给出已知11组世界坐标和像素坐标点对,然后罗列线性方程组即可将11个未知参数求出来。
M = [ m 1 m 2 m 3 ] M=\begin{bmatrix} m_1\\m_2\\m_3 \end{bmatrix} M=m1m2m3,则 P ′ = [ m 1 P w m 2 P w m 3 P w ] = [ m 1 P w m 3 P w m 2 P w m 3 P w 1 ] = [ u v 1 ] P'=\begin{bmatrix} m_1P_w \\m_2P_w\\m_3P_w \end{bmatrix}=\begin{bmatrix} \frac{m_1P_w}{m_3P_w}\\ \frac{m_2P_w}{m_3P_w}\\ 1 \end{bmatrix}=\begin{bmatrix} u\\v\\1 \end{bmatrix} P=m1Pwm2Pwm3Pw=m3Pwm1Pwm3Pwm2Pw1=uv1
{ ( m 3 P w ) u − m 1 P w = 0 ( m 3 P w ) v − m 2 P w = 0 \begin{cases} (m_3 P_w)u-m_1P_w=0\\ (m_3P_w)v-m_2P_w=0 \end{cases} {(m3Pw)um1Pw=0(m3Pw)vm2Pw=0
如上式所示,每对点对就提供了两个限定方程。所以我们只需提供6对点对,即可求出11个未知参数。
假设我们提供的点对分别是: < P 1 , ( u 1 , v 1 ) > 、 < P 2 , ( u 2 , v 2 ) > 、 ⋯ 、 < P 6 , ( u 6 , v 6 ) > <P_1,(u_1,v_1)>、<P_2,(u_2,v_2)>、\cdots 、<P_6,(u_6,v_6)> <P1,(u1,v1)><P2,(u2,v2)><P6,(u6,v6)>
罗列出方程组:

{ ( m 3 P 1 ) u 1 − m 1 P 1 = 0 ( m 3 P 1 ) v 1 − m 2 P 1 = 0 ( m 3 P 2 ) u 2 − m 1 P 2 = 0 ( m 3 P 2 ) v 2 − m 2 P 2 = 0 ⋮ ( m 3 P 6 ) u 6 − m 1 P 6 = 0 ( m 3 P 6 ) v 6 − m 2 P 6 = 0 \begin{cases} (m_3 P_1)u_1-m_1P_1=0\\ (m_3P_1)v_1-m_2P_1=0\\ (m_3 P_2)u_2-m_1P_2=0\\ (m_3P_2)v_2-m_2P_2=0\\ \vdots \\ (m_3 P_6)u_6-m_1P_6=0\\ (m_3P_6)v_6-m_2P_6=0\\ \end{cases} (m3P1)u1m1P1=0(m3P1)v1m2P1=0(m3P2)u2m1P2=0(m3P2)v2m2P2=0(m3P6)u6m1P6=0(m3P6)v6m2P6=0
以矩阵形式表示这个方程组:

[ x 1 y 1 z 1 1 0 0 0 0 − u 1 x 1 − u 1 y 1 − u 1 z 1 0 0 0 0 x 1 y 1 z 1 1 − v 1 x 1 − v 1 y 1 − v 1 z 1 ⋮ x 6 y 6 z 6 1 0 0 0 0 − u 6 x 6 − u 6 y 6 − u 6 z 6 0 0 0 0 x 6 y 6 z 6 1 − v 6 x 6 − v 6 y 6 − v 6 z 6 ] [ m 11 m 12 m 13 m 14 m 21 m 22 m 23 m 24 m 31 m 32 m 33 m 34 ] = [ u 1 v 1 ⋮ u 6 v 6 ] \begin{bmatrix} x_1&y_1&z_1 & 1 & 0 & 0 & 0 & 0 &-u_1x_1&-u_1y_1& -u_1z_1 \\ 0 & 0 & 0 & 0 & x_1 &y_1 & z_1 & 1 & -v_1x_1 & -v_1y_1 & -v_1z_1 \\ \vdots \\ x_6&y_6&z_6 & 1 & 0 & 0 & 0 & 0 &-u_6x_6&-u_6y_6& -u_6z_6 \\ 0 & 0 & 0 & 0 & x_6 &y_6 & z_6 & 1 & -v_6x_6 & -v_6y_6 & -v_6z_6 \\ \end{bmatrix} \begin{bmatrix} m_{11} \\ m_{12} \\ m_{13} \\ m_{14} \\ m_{21} \\ m_{22} \\ m_{23} \\ m_{24} \\m_{31} \\m_{32}\\m_{33} \\m_{34} \end{bmatrix}=\begin{bmatrix} u_1\\v_1\\ \vdots \\u_6\\v_6 \end{bmatrix} x10x60y10y60z10z6010100x10x60y10y60z10z60101u1x1v1x1u6x6v6x6u1y1v1y1u6y6v6y6u1z1v1z1u6z6v6z6m11m12m13m14m21m22m23m24m31m32m33m34=u1v1u6v6
简写成
K m = U Km=U Km=U
使用最小二乘法求解向量 m m m得:
m = ( K T K ) − 1 K T U m=(K^TK)^{-1}K^TU m=(KTK)1KTU
这样矩阵 M M M就被求出来了。
接下来我们通过矩阵 M M M求解内参和外参。
已知 M = [ K 0 ] T M=\begin{bmatrix} K & 0 \end{bmatrix} T M=[K0]T
[ m 11 m 12 m 13 m 14 m 21 m 22 m 23 m 24 m 31 m 32 m 33 m 34 ] = [ α 0 c x 0 0 β c y 0 0 0 1 0 ] [ r 11 r 12 r 13 t 1 r 21 r 22 r 23 t 2 r 31 r 32 r 33 t 3 0 0 0 1 ] \begin{bmatrix} m_{11} & m_{12} & m_{13} & m_{14}\\m_{21} & m_{22} & m_{23} & m_{24}\\m_{31} & m_{32} & m_{33} & m_{34} \end{bmatrix}= \begin{bmatrix}\alpha & 0 & c_x & 0\\ 0 & \beta & c_y & 0 \\ 0& 0& 1 & 0\end{bmatrix} \begin{bmatrix} r_{11} & r_{12} & r_{13} & t_1 \\ r_{21} & r_{22} & r_{23} & t_2 \\ r_{31} & r_{32} &r_{33} & t_3 \\ 0 & 0 & 0 & 1 \end{bmatrix} m11m21m31m12m22m32m13m23m33m14m24m34=α000β0cxcy1000r11r21r310r12r22r320r13r23r330t1t2t31

[ m 1 T m 14 m 2 T m 24 m 3 T m 34 ] = [ α 0 c x 0 0 β c y 0 0 0 1 0 ] [ r 1 T t 1 r 2 T t 2 r 3 T t 3 0 T 1 ] = [ α r 1 T + c x r 3 T α t 1 + c x t 3 β r 2 T + c y r 3 T β t 2 + c y t 3 r 3 T t 3 ] \begin{bmatrix} m_1^T & m_{14} \\ m_2^T & m_{24} \\ m_3^T & m_{34} \end{bmatrix} = \begin{bmatrix}\alpha & 0 & c_x & 0\\ 0 & \beta & c_y & 0 \\ 0& 0& 1 & 0\end{bmatrix} \begin{bmatrix} r_1^T & t_1 \\ r_2^T & t_2 \\ r_3^T & t_3 \\ 0^T & 1 \end{bmatrix} = \begin{bmatrix} \alpha r_1^T+c_xr_3^T & \alpha t_1+c_xt_3 \\ \beta r_2^T +c_yr_3^T & \beta t_2+c_yt_3 \\ r_3^T & t_3 \end{bmatrix} m1Tm2Tm3Tm14m24m34=α000β0cxcy1000r1Tr2Tr3T0Tt1t2t31=αr1T+cxr3Tβr2T+cyr3Tr3Tαt1+cxt3βt2+cyt3t3
解得:
{ m 34 = 1 ∣ m 3 ∣ r 3 = m 34 m 3 c x = ( α r 1 T + c x r 3 T ) r 3 = m 34 2 m 1 T m 3 c y = ( β r 2 T + c y r 3 T ) r 3 = m 34 2 m 2 T m 3 α = m 34 2 ∣ m 1 × m 3 ∣ β = m 34 2 ∣ m 2 × m 3 ∣ r 1 = m 34 α ( m 1 − c x m 3 ) r 2 = m 34 β ( m 2 − c y m 3 ) t 1 = m 34 α ( m 14 − c x ) t 2 = m 34 β ( m 24 − c y ) t 3 = m 34 \begin{cases} m_{34}=\frac{1}{|m_3|}\\ r_3=m_{34}m_3\\ c_x=(\alpha r_1^T +c_xr_3^T)r_3=m_{34}^2m_1^Tm_3\\ c_y=(\beta r_2^T+c_yr_3^T)r_3=m_{34}^2m_2^Tm_3\\ \alpha =m_{34}^2 |m_1 \times m_3| \\ \beta = m_{34}^2 |m_2 \times m_3| \\ r_1=\frac{m_{34}}{\alpha }(m_1-c_xm_3) \\ r_2=\frac{m_{34}}{\beta}(m_2-c_ym_3) \\ t_1=\frac{m_{34}}{\alpha}(m_{14}-c_x)\\ t_2=\frac{m_{34}}{\beta}(m_{24}-c_y)\\ t_3=m_{34} \end{cases} m34=m31r3=m34m3cx=(αr1T+cxr3T)r3=m342m1Tm3cy=(βr2T+cyr3T)r3=m342m2Tm3α=m342m1×m3β=m342m2×m3r1=αm34(m1cxm3)r2=βm34(m2cym3)t1=αm34(m14cx)t2=βm34(m24cy)t3=m34
综上所述,由空间6个坐标点以及它们的像素坐标,我们可以求出 M M M矩阵。并可以求出内参和外参。

6. 获取空间坐标点

6.1 选择校准目标

在这里插入图片描述
可以从boofcv的网站上下载想要的校准图案。

参考资料:

  1. CS231A Course Notes 1: Camera Models
  2. 计算机视觉计算理论与算法基础-马颂德、张正友 著
  3. Tutorial Camera Calibration
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
针孔相机标定是计算机视觉中的一个重要问题,它是指通过已知的一组二维图像点和对应的三维空间点,计算出相机的内部参数矩阵和外部参数矩阵的过程。下面是使用OpenCV C++实现针孔相机标定的步骤: 1.准备标定板:选择一个标定板,例如棋盘格,然后拍摄多张包含标定板的图片。 2.提取角点:使用OpenCV的findChessboardCorners函数在每张图片中检测标定板的角点,并使用cornerSubPix函数对角点进行亚像素级别的提取。 3.建立三维空间点:根据标定板的实际尺寸和布局,建立标定板上每个角点的三维坐标。 4.进行标定:使用calibrateCamera函数计算相机的内部参数矩阵和外部参数矩阵。 下面是一个简单的OpenCV C++针孔相机标定的示例代码: ```cpp // 准备标定板 Size boardSize = Size(9, 6); vector<Point2f> imageCorners; vector<Point3f> objectCorners; vector<vector<Point2f>> image_points; vector<vector<Point3f>> object_points; Mat img, gray; vector<String> filelist; glob("calib_images/*.jpg", filelist, false); for (size_t i = 0; i < filelist.size(); i++) { img = imread(filelist[i]); cvtColor(img, gray, COLOR_BGR2GRAY); bool found = findChessboardCorners(img, boardSize, imageCorners); if (found) { cornerSubPix(gray, imageCorners, Size(5, 5), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1)); drawChessboardCorners(img, boardSize, imageCorners, found); vector<Point3f> temp; for (int i = 0; i < boardSize.height; i++) { for (int j = 0; j < boardSize.width; j++) { temp.push_back(Point3f(j, i, 0)); } } objectCorners.push_back(temp); image_points.push_back(imageCorners); object_points.push_back(objectCorners); } } // 进行标定 Mat intrinsicMatrix, distortionCoeff, rvecs, tvecs; calibrateCamera(object_points, image_points, img.size(), intrinsicMatrix, distortionCoeff, rvecs, tvecs); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值