畸变是指光学系统对物体所成的像相对于物体本身而言的失真程度,是光学透镜的固有特性,其直接原因是因为透镜的边缘部分和中心部分的放大倍率不一样。
透镜的畸变是不可消除的,但在实际的应用中可以通过一些软件来进行畸变的补偿,如OpenCV、MATLAB等。
相机的畸变主要分为以下几类:
通常情况下径向畸变的影响要远远大于其他畸变,因此由Brown在《Close-Range Camera Celibration》一文中所提及的径向畸变模型和切向畸变模型应用比较广泛。
如下为Brown在论文中提及的径向畸变和切向畸变模型:
径向畸变模型:
{ x ′ = x + x ‾ ( k 1 r 2 + k 2 r 4 + k 3 r 6 ) y ′ = y + y ‾ ( k 1 r 2 + k 2 r 4 + k 3 r 6 ) \left\{ \begin{array}{c} x'=x +\overline{x}(k_1r^2+k_2r^4+k_3r^6)\\ y'=y +\overline{y}(k_1r^2+k_2r^4+k_3r^6) \end{array}\right. {x′=x+x(k1r2+k2r4+k3r6)y′=y+y(k1r2+k2r4+k3r6)切向畸变模型:
{ x ′ = x + p 1 ( r 2 + 2 x ‾ 2 ) + 2 p 2 x ‾ ∗ y ‾ y ′ = y + p 2 ( r 2 + 2 y ‾ 2 ) + 2 p 1 x ‾ ∗ y ‾ \left\{ \begin{array}{c} x'=x +p_1(r^2+2\overline{x}^2)+2p_2\overline{x}*\overline{y}\\ y'=y +p_2(r^2+2\overline{y}^2)+2p_1\overline{x}*\overline{y} \end{array}\right. {x′=x+p1(r2+2x2)+2p2x∗yy′=y+p2(r2+2y2)+2p1x∗y径向加切向畸变模型:
{ x ′ = x + x ‾ ( k 1 r 2 + k 2 r 4 + k 3 r 6 ) + p 1 ( r 2 + 2 x ‾ 2 ) + 2 p 2 x ‾ ∗ y ‾ y ′ = y + y ‾ ( k 1 r 2 + k 2 r 4 + k 3 r 6 ) + p 2 ( r 2 + 2 y ‾ 2 ) + 2 p 1 x ‾ ∗ y ‾ \left\{ \begin{array}{c} x'=x +\overline{x}(k_1r^2+k_2r^4+k_3r^6)+p_1(r^2+2\overline{x}^2)+2p_2\overline{x}*\overline{y}\\ y'=y +\overline{y}(k_1r^2+k_2r^4+k_3r^6)+p_2(r^2+2\overline{y}^2)+2p_1\overline{x}*\overline{y} \end{array}\right. {x′=x+x(k1r2+k2r4+k3r6)+p1(r2+2x2)+2p2x∗yy′=y+y(k1r2+k2r4+k3r6)+p2(r2+2y2)+2p1x∗y该畸变模型中 ( x ′ , y ′ ) (x',y') (x′,y′)为二次畸变的坐标, ( x , y ) (x,y) (x,y)为一次畸变(未校正前的图像下的)坐标。
这里谁是畸变坐标,谁是理想坐标,真的是搞晕了。
论文原文中描述为:
However,if the coordinates x,y of points on the image of a plumb line were corrected for such distortion, ther would conform to a straight line.
译文:然而,如果这个铅垂线的图像上的点的坐标(x,y)被校正过这种失真,它们将符合一条直线。
这在 ( x , y ) (x,y) (x,y)为畸变坐标还是理想坐标的概念上有些模糊。
在《最详细、最完整的相机标定讲解》链接一文中有明确指出 ( x ′ , y ′ ) (x',y') (x′,y′)为理想坐标, ( x , y ) (x,y) (x,y)为实际坐标。在论文《数码相机畸变模型的相互转换方法》-任超峰 中,作者称 ( x , y ) (x,y) (x,y)为原始像点, ( x ′ , y ′ ) (x',y') (x′,y′)为理论像点。
但是好多文章里也会讲到, ( x ′ , y ′ ) (x',y') (x′,y′)为实际坐标, ( x , y ) (x,y) (x,y)为理想坐标。如在《相机参数标定》链接一文中就有明确指出。
笔者这里认为 ( x ′ , y ′ ) (x',y') (x′,y′)为产生了畸变的坐标, ( x , y ) (x,y) (x,y)为理想状态下的坐标。
这与下述的OpenCV的畸变模型能够产生对照,可信度更大。
(实践是检验真理的唯一标准,在条件允许的情况下,大家可以通过OpenCV来验证一下。欢迎讨论)
**> 2021/12/3日对该处进行补充:
畸变模型是对真实物体的二次畸变,准确来说,透过镜头得到的图像(桶形畸变等)称为一次畸变,之后通过畸变模型进行调整称为二次畸变。即准确来说 ( x ′ , y ′ ) (x',y') (x′,y′)为二次畸变后的坐标, ( x , y ) (x,y) (x,y)为一次畸变后的坐标。**这里可以参考《计算机视觉——算法与应用》第46页2.1.6<镜头畸变>中的说法
x ‾ = x − x p y ‾ = y − y p \overline{x} = x-x_p\\ \overline{y} = y-y_p\\ x=x−xpy=y−yp r 2 = x ‾ 2 + y ‾ 2 = ( x − x p ) 2 + ( y − y p ) 2 r^2=\overline{x}^2+\overline{y}^2=(x-x_p)^2+(y-y_p)^2 r2=x2+y2=(x−xp)2+(y−yp)2
由于该公式是根据Brown在1964,1965两年发表的文章进行修正的,所以式中的 ( x p , y p ) (x_p,y_p) (xp,yp)的具体含义在原文中并没有过多赘述。但这两篇文章笔者也没能够找到原文。
这里附上这两篇文章的名字《An Advanced Plate Reduction for Photogrammetric Cameras》、《Decentering Distortion of Lenses》
读者有兴趣可以查找一下
查阅论文《数码相机畸变模型的相互转换方法》-任超峰。确定 ( x p , y p ) (x_p,y_p) (xp,yp)为相机的内方位元素。
内方位元素是描述摄影中心与图像平面之间相互位置关系的元素,主要包含焦距 f f f,以及 ( x p , y p ) (x_p,y_p) (xp,yp)
( x p , y p ) (x_p,y_p) (xp,yp)为像主点在图像坐标系中的坐标,像主点为图像的中心点,理论上应当通过相机光轴。
即实际的图像坐标系和理论上的图像坐标系之间由于制造或者安装的缘故,使二者之间产生了 ( x p , y p ) (x_p,y_p) (xp,yp)的偏差。
内方位元素一般视为已知的,可以通过对相机的鉴定的得到
通常情况下,对于数码影像,其内方位元素可以视为 ( x p , y p ) = ( 0 , 0 ) (x_p,y_p)=(0,0) (xp,yp)=(0,0)
因此,我们通常看到的畸变模型为如下形式:
{ x ′ = x ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) + p 1 ( r 2 + 2 x 2 ) + 2 p 2 x y y ′ = y ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) + p 2 ( r 2 + 2 y 2 ) + 2 p 1 x y \left\{ \begin{array}{c} x'=x (1+k_1r^2+k_2r^4+k_3r^6)+p_1(r^2+2x^2)+2p_2xy\\ y'=y (1+k_1r^2+k_2r^4+k_3r^6)+p_2(r^2+2y^2)+2p_1xy \end{array}\right. {x′=x(1+k1r2+k2r4+k3r6)+p1(r2+2x2)+2p2xyy′=y(1+k1r2+k2r4+k3r6)+p2(r2+2y2)+2p1xy
像方畸变模型和物方畸变模型都是对图像的校正模型,只是采取的参考系不同而已。
OpenCV采用了物方畸变模型,对相机坐标系下的坐标进行畸变模型处理
在OpenCV官网文件中有对畸变模型的详细介绍链接
上篇文章中讲到,一点X,其在世界坐标系中的坐标为: ( x w , y w , z w ) (x_w,y_w,z_w) (xw,yw,zw)
其在相机坐标系中的坐标为: ( X c , Y c , Z c ) (X_c,Y_c,Z_c) (Xc,Yc,Zc)
其在图像坐标系中的坐标为: ( x i , y i ) (x_i,y_i) (xi,yi)
其在像素坐标系中的坐标为: ( P x i , P y i ) (P_{x_i},P_{y_i}) (Pxi,Pyi)
世界坐标系到像素坐标系的坐标转换矩阵:
[ P x i ∗ Z c P y i ∗ Z c Z c ] = [ M ∗ f 0 M ∗ P x 0 N ∗ f N ∗ P y 0 0 1 ] ∗ ( R ∣ − R c ) ∗ [ x w y w z w 1 ] \left[\begin{array}{ccccc} P_{x_i}*Z_c\\ P_{y_i}*Z_c\\ Z_c \end{array}\right]= \left[ \begin{array}{ccccc} M*f&0&M*P_x\\ 0&N*f&N*P_y\\ 0&0&1 \end{array} \right]*(R|-Rc)* \left[\begin{array}{ccccc} x_w\\ y_w\\ z_w\\ 1 \end{array}\right] ⎣⎡Pxi∗ZcPyi∗ZcZc⎦⎤=⎣⎡M∗f000N∗f0M∗PxN∗Py1⎦⎤∗(R∣−Rc)∗⎣⎢⎢⎡xwywzw1⎦⎥⎥⎤将其中的坐标带入到OpenCV中转换坐标中: [ X c Y c Z c ] = R ∗ [ x w y w z w ] + C \left[ \begin{array}{ccccc} X_c\\ Y_c\\ Z_c \end{array}\right]= R* \left[ \begin{array}{ccccc} x_w\\ y_w\\ z_w \end{array}\right]+C ⎣⎡XcYcZc⎦⎤=R∗⎣⎡xwywzw⎦⎤+C
对相机坐标系的坐标进行处理:
{ x ′ = X c / Z c y ′ = Y x / Z c \left\{ \begin{array}{ccccc} x' = X_c/Z_c\\ y'=Y_x/Z_c \end{array}\right. {x′=Xc/Zcy′=Yx/Zc将处理后的坐标带入到畸变模型中,(公式有些复杂,上图吧)
然后转化到图像坐标系
{ x i ′ = x ′ ′ ∗ f y i ′ = y ′ ′ ∗ f \left\{ \begin{array}{c} x_i '= x''*f\\ y_i '= y''*f \end{array}\right. {xi′=x′′∗fyi′=y′′∗f再转化到像素坐标系进行单位转换
{ P x i ′ = x i ′ + P x P y i ′ = y i ′ + P y \left\{ \begin{array}{c} P_{x_i}' = x_i'+P_x\\ P_{y_i}' = y_i'+P_y \end{array}\right. {Pxi′=xi′+PxPyi′=yi′+Py进行单位转换
{ P x i ′ = M x i ′ + M P x P y i ′ = N y i ′ + N P y \left\{ \begin{array}{c} P_{x_i}' = Mx_i'+MP_x\\ P_{y_i}' = Ny_i'+NP_y \end{array}\right. {Pxi′=Mxi′+MPxPyi′=Nyi′+NPy
式中 k 1 , k 2 , k 3 , k 4 , k 5 , k 6 k_1,k_2,k_3,k_4,k_5,k_6 k1,k2,k3,k4,k5,k6是径向畸变系数。 p 1 , p 2 p_1,p_2 p1,p2为切向畸变系数。薄棱镜畸变不考虑。
容易知道,OpenCV是将畸变模型加在相机坐标系下,因此属于物方畸变模型
将加入畸变模型后的转换过程整理为矩阵形式如下,整体上来看和理想状态下的坐标转换矩阵相似:
[ P x i ′ P y i ′ 1 ] = [ M ∗ f 0 M ∗ P x 0 N ∗ f N ∗ P y 0 0 1 ] [ x ′ ′ y ′ ′ 1 ] \left[\begin{array}{ccccc} P_{x_i}'\\ P_{y_i}'\\ 1 \end{array}\right]= \left[ \begin{array}{ccccc} M*f&0&M*P_x\\ 0&N*f&N*P_y\\ 0&0&1 \end{array} \right] \left[\begin{array}{ccccc} x''\\ y''\\ 1 \end{array}\right] ⎣⎡Pxi′Pyi′1⎦⎤=⎣⎡M∗f000N∗f0M∗PxN∗Py1⎦⎤⎣⎡x′′y′′1⎦⎤