這篇博客不會詳細介紹張正友相機標定算法的計算過程,所以只是想怎么用openCV或者Matlab實現相機標定的朋友就不用費時間去看了。這篇博客介紹我對張氏標定算法的理解。因為我看到很多資料,覺得很多人對這個算法的理解有問題。雖然我沒有用程序實現,但從數學的角度上還是可以分析出來的。
首先推薦一篇博客張正友標定法。這篇博文是我找到的講解最為詳細的,但當中有些論點我仍然覺得有問題。大家可以先看這一篇,理解差不多了在看看我說的是不是有道理。
1.提取多少個角點可以求解方程
2.極大似然估計怎么應用
3.畸變糾正
提取多少個角點可以求解方程
首先我們看一眼要求解的方程
\(s\begin{bmatrix}u\\ v\\ 1\end{bmatrix} = \begin{bmatrix}h_{11} & h_{12} & h_{13}\\ h_{21} & h_{22} & h_{23}\\ h_{31} & h_{32} & h_{33}\end{bmatrix}\begin{bmatrix}X\\ Y\\ 1\end{bmatrix}=H\begin{bmatrix}X\\ Y\\ 1\end{bmatrix}\)
式中:
\(H=A\begin{bmatrix}R & t\end{bmatrix}=\begin{bmatrix}\alpha & \gamma & u_0\\ 0 & \beta & v_0\\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix}r_1 & r_2 & r_3 & t\end{bmatrix}\)
由於,現實坐標是在棋盤板上建立的,默認找到的所有角點,其Z軸坐標都為0,所以省去了一列r3。我們對后一個矩陣繼續展開:
\(\begin{bmatrix}r_1 & r_2 & r_3 & t\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\end{bmatrix}\)
我首先說明這個R矩陣是三個分別表示繞x軸,y軸,z軸旋轉的單位正交陣相乘的結果,所以每一個列向量和三個旋轉方向都是相關的。而不是像別人說,r1與x軸相關,r2與y周相關,r3與z軸相關。由於單位正交陣乘積的結果還是單位正交陣,所以r1,r2,r3是相互正交的單位向量。
注意R和t一共有12個量值,但是R只和三個旋轉角度相關,t代表三個方向的偏移量,所以實際上只有6個未知量。而A陣中有5個未知量(如果不考慮x軸與y軸的影響,可以不考慮\(\gamma\)),加起來一共有11個未知量。但最后簡化成H陣只有9個變量(雖然刪除了r3,但三個旋轉角度仍然存在於r1與r2中)。我們還要注意,我么對單眼相機標定的目標不是找到現實世界的坐標和相機像素坐標的關系,准確來講是要獲取相機的內參數。所以我們對棋盤板的位置並不關心。例如我現在有兩個大小不同的棋盤版,大的相對小的放的遠一點,但保證在相片的中像素坐標是相同的。那么這兩個棋盤版計算出來的兩個H陣是不同的(棋盤版位置不同),但是是成比例的!這說明H的比例變化是不影響相機的內參數計算的,那么我們干脆將H中的一個變量設定為常數“1”,這樣H陣的結果就是唯一的了。此時,這種比例變化就由變量s來平衡,使得方程成立。
我們不妨假定\(h_{33}=1\)。現在只剩下8個變量。其它人都說一個點提供兩個方程,所以找4個點就可以了。但是想想就知道,一個平面只有兩個線性無關向量,怎么可能提供4個獨立無關的點,理論上不是只能提供兩個點嗎?如果認為只能提供兩個點,那么一定忽略的常數項。注意方程:
\(s\begin{bmatrix}u\\ v\\ 1\end{bmatrix} = \begin{bmatrix}h_{11} & h_{12} & h_{13}\\ h_{21} & h_{22} & h_{23}\\ h_{31} & h_{32} & h_{33}\end{bmatrix}\begin{bmatrix}X\\ Y\\ 1\end{bmatrix}=H\begin{bmatrix}X\\ Y\\ 1\end{bmatrix}\)
最后一項是1,而不是0!所以一個平面的基底[1,0]和[0,1],帶入方程就變成了[1,0,1]和[0,1,1],這兩個向量不能線性表示[0,0,1]。所以實際上一個平面可以提供三個線性無關的點。我們還要注意一個點提供的方程數量是三個,而不是兩個(我也不知道別人是怎么得出一個點兩個方程的結論)。這樣我們從一個棋盤版得到了9個線性無關的方程。可是未知量有8個,方程有9個,不是過約束了?注意,一個棋盤版得到H陣既和內參數相關也和自身位置相關,所以H陣是唯一的!只不過我們知道了H陣的比例變化不影響內參數,才在解出H之后對其做比例變化的。所以實際求解中,忽略s,求解H中的9個參數,再添加s,調整使得\(h_{33}=1\)。
我們求解了H矩陣,得到了9個量值,但是未知量有11個,所以還是不能直接解出內參數矩陣。至於解法,我推薦博文中算法,沒有什么問題。
如果我們得到了相機的內參數,那么在以后的坐標轉換的問題中就只剩下6個未知量(三個旋轉角度和三個平移距離)。邏輯上只需要提供兩個點就可以求解這個矩陣。那么是不是以后我們只要輸入兩個特征點就可以找到坐標轉換函數?如果你這樣認為,那么你就被我騙了。只要想想就知道,僅憑兩個點是不可能確定一個空間坐標系。既然連世界坐標系都確定不了,怎么可能得到坐標轉換方程。
並不是我存心要耍你,我只是推理到這一步時才發覺之前的理解有問題。我們所謂的坐標系轉換,不是將世界坐標系移動到相機坐標系上,使得兩個坐標系重合。如果真能這樣,那么深度信息毫無疑問能得到,你都可以移動過來,自然知道兩者的距離了。但是這個坐標變換與深度信息毫無關系。這種坐標變換的實質是調整一個坐標系,使得其中元素的表示與元素在另一個坐標系中對應的元素的坐標表示相同。舉個例子,現在有坐標系A(相機坐標系)和坐標系B(世界坐標系),我們所做的所有變換是對坐標系B進行平移,旋轉,伸縮,使得世界坐標系中的物體在B中坐標表示和對應在相片中的物體在相機中的坐標(由於沒有Z,默認兩個坐標的Z是相同的),兩者的數值相同。由於變換的前后改變的只是坐標系B,而坐標系A和坐標系B的位置關系從頭到尾都沒有涉及。
其實說到這里,你應該能想到為什么用兩個點的對應關系能確定轉換矩陣。答案自然是我們少考慮了一些變量——代表三個坐標軸伸縮變換的量
\(K=\begin{bmatrix}k_1\\ k_2\\ k_3\end{bmatrix}\)
如果我們僅用兩個點,我們能夠確定的是將這兩個點對應的直線變換到所對應的直線,實際只需要兩個旋轉,兩個伸縮,兩個移動就可以了,所以也剛好有6個獨立的方程。但對於完整的坐標變化,我們依然需要9個變量全部知道才可以,也就是我們還是需要知道三個點。
那么之前的推理是否存在問題?我們把伸縮變換添加到方程中:
\(H=KA\begin{bmatrix}R & t\end{bmatrix}=\begin{bmatrix}k_1\\ k_2\\ k_3\end{bmatrix}\begin{bmatrix}\alpha & \gamma & u_0\\ 0 & \beta & v_0\\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix}r_1 & r_2 & r_3 & t\end{bmatrix}\)
我們注意到雖然添加了但H還是9個量,所以對H的求解不影響。至於對相機內參數的求解,你推一下就知道,兩個約束方程中也不會出現與K相關的變量,所以A的求解也沒有問題。綜上,之前的推理不受伸縮變換的影響!但是在坐標系變換的確定中,伸縮變換還是有影響的!所以即使知道了相機的內參數,我們還是需要知道三個點的對應關系才可以求解出轉換矩陣!
2018/3/8更新:
之后再仔細想想,發現自己的想法還是有問題。之前說坐標變換與兩個坐標系沒有關系,只是考慮元素在坐標系中的變換只是一個數學運算,沒有考慮物理意義。但如果在兩個坐標系中表示的元素是同一個呢?在空間中固定三個點,如果這三個點在兩個坐標系中的表示是一樣的,說明什么?說明這兩個坐標系是完全重合的!同理應用到相機標定,如果得到外參數,可以由世界坐標轉到相機坐標下的。證明世界坐標經過變換與相機坐標重疊了。說明這個變換可以把世界坐標轉移到相機坐標。而且在世界坐標系中我們應用的長度單位和在相機坐標系中應用的長度單位是相同的,說明坐標系是不需要伸縮變換。那么未知量只有三個旋轉角度和三個平移距離,共六個變量,那么得到兩個點可以求解了嗎?不能!
之前我談到過方程中s的含義,我理解這是一個比例系數。如果我們修改方程:
\(s\begin{bmatrix}u\\ v\\ 1\end{bmatrix} =z'\begin{bmatrix} \frac{u'}{z'}\\ \frac{v'}{z'}\\1\end{bmatrix}= \begin{bmatrix}h_{11} & h_{12} & h_{13}\\ h_{21} & h_{22} & h_{23}\\ h_{31} & h_{32} & h_{33}\end{bmatrix}\begin{bmatrix}X\\ Y\\ 1\end{bmatrix}=H\begin{bmatrix}X\\ Y\\ 1\end{bmatrix}\)
當中u',v',z'是相機坐標下的坐標,那么z'的含義就是z向距離,也就是深度信息。由於對圖片沒有深度信息,最終\(u=\frac{u'}{z'}\) \(v=\frac{v'}{z'}\)。那么對於每一個點的z‘都是不一樣的,所以現在有了三個新的變量。所以其實方程實際有三個變量,一個點可以提供三個方程,求解坐標變換矩陣需要三個點。
極大似然估計
我們對一個棋盤板可以得到多個點,但是在求解的過程中我們只會用到三個點。那么選擇哪三個點?很簡單,遍歷所有線性無關的三個點的組合,求解對應的H,並用這個H檢驗其它點的對應關系是否准確,根據誤差計算公式
\(\sum_{n}^{i=1}\sum_{m}^{j=1}\left \| m_{ij}-\hat{m}(H,M_{ij}) \right \|\)
選擇誤差最小的一組點。
畸變糾正
我對畸變糾正的算法有一個問題。因為畸變在一開始就是存在的,但是在計算坐標轉換時默認是不考慮的。那么我們計算的坐標轉換就是不准確的,怎么可以應用到畸變糾正中,並期望得到正確的結果?實際這就是一個雞生蛋還是蛋生雞的問題。對於這種問題常用的求解算法就是迭代求解。我們可以選取視覺中心的三個點求解H,盡可能減少畸變的影響,再去求解畸變參數。有了畸變參數再去糾正圖像,再去計算轉換矩陣H,反復幾次應該就可以減小誤差。實際上在最大似然估計的過程中,大概率選擇的三個點就是中心的三個點。