1基本原理
1.1 單應性矩陣(Homography)的建立
相機模型:世界坐標系下棋盤格平面(Z=0)到圖像平面的投影關系為:
s [ u v 1 ] = K [ r 1 r 2 t ] [ X Y 1 ] s \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = K \begin{bmatrix} r_1 & r_2 & t \end{bmatrix} \begin{bmatrix} X \\ Y \\ 1 \end{bmatrix} s ?uv1? ?=K[r1??r2??t?] ?XY1? ?
其中:
-
( X , Y ) (X,Y) (X,Y):棋盤格角點的世界坐標(Z=0)。
-
( u , v ) (u,v) (u,v):圖像平面上的像素坐標。
-
K K K:內參矩陣,形式為:
K = [ f x γ u 0 0 f y v 0 0 0 1 ] K = \begin{bmatrix} f_x & \gamma & u_0 \\ 0 & f_y & v_0 \\ 0 & 0 & 1 \end{bmatrix} K= ?fx?00?γfy?0?u0?v0?1? ? -
r 1 , r 2 , t r_1, r_2, t r1?,r2?,t:外參(旋轉矩陣的前兩列和平移向量)。
-
s s s:尺度因子。
單應性矩陣:將投影關系簡化為:
s [ u v 1 ] = H [ X Y 1 ] s \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = H \begin{bmatrix} X \\ Y \\ 1 \end{bmatrix} s ?uv1? ?=H ?XY1? ?
其中 H = K [ r 1 r 2 t ] H = K [r_1 \quad r_2 \quad t] H=K[r1?r2?t] 是一個3×3矩陣,稱為單應性矩陣。
1.2 單應性矩陣的求解
對每個棋盤格圖像,利用至少4組對應點(世界坐標和圖像坐標),通過最小二乘法或直接線性變換(DLT)求解 H H H。對于每組點:
[ X Y 1 0 0 0 ? u X ? u Y ? u 0 0 0 X Y 1 ? v X ? v Y ? v ] [ h 11 h 12 h 13 h 21 h 22 h 23 h 31 h 32 h 33 ] = 0 \begin{bmatrix} X & Y & 1 & 0 & 0 & 0 & -uX & -uY & -u \\ 0 & 0 & 0 & X & Y & 1 & -vX & -vY & -v \end{bmatrix} \begin{bmatrix} h_{11} \\ h_{12} \\ h_{13} \\ h_{21} \\ h_{22} \\ h_{23} \\ h_{31} \\ h_{32} \\ h_{33} \end{bmatrix} = 0 [X0?Y0?10?0X?0Y?01??uX?vX??uY?vY??u?v?] ?h11?h12?h13?h21?h22?h23?h31?h32?h33?? ?=0
通過SVD分解求解 H H H 的9個參數(歸一化后)。
1.3 內參矩陣的約束條件
張正友標定法中,通過旋轉矩陣的正交性推導兩個約束方程的過程是核心步驟。以下是結合正交矩陣性質與單應性矩陣的詳細推導:
1.3.1 旋轉矩陣的正交性
在張正友標定法中,旋轉矩陣 R R R 是正交矩陣,滿足以下性質:
- 列向量正交性: R R R 的列向量 r 1 , r 2 , r 3 r_1, r_2, r_3 r1?,r2?,r3? 兩兩正交。
- 單位模長約束:每個列向量的模長為1,即 ∥ r 1 ∥ = ∥ r 2 ∥ = ∥ r 3 ∥ = 1 \|r_1\| = \|r_2\| = \|r_3\| = 1 ∥r1?∥=∥r2?∥=∥r3?∥=1。
由于標定棋盤格平面位于世界坐標系的 Z = 0 Z=0 Z=0 平面,投影模型中僅涉及 R R R 的前兩列 r 1 r_1 r1? 和 r 2 r_2 r2?,因此正交性約束簡化為:
{ r 1 T r 2 = 0 (正交性) r 1 T r 1 = r 2 T r 2 = 1 (單位模長) \begin{cases} r_1^T r_2 = 0 \quad \text{(正交性)} \\ r_1^T r_1 = r_2^T r_2 = 1 \quad \text{(單位模長)} \end{cases} {r1T?r2?=0(正交性)r1T?r1?=r2T?r2?=1(單位模長)?
1.3.2 單應性矩陣 $ H $ 與旋轉矩陣的關聯
單應性矩陣 H H H 將棋盤格平面( Z = 0 Z=0 Z=0)映射到圖像平面,其表達式為:
H = λ K [ r 1 r 2 t ] H = \lambda K [r_1 \quad r_2 \quad t] H=λK[r1?r2?t]
其中:
- λ \lambda λ:尺度因子,
- K K K:內參矩陣,
- r 1 , r 2 r_1, r_2 r1?,r2?:旋轉矩陣的前兩列,
- t t t:平移向量。
將 H H H 的列向量表示為 h 1 , h 2 , h 3 h_1, h_2, h_3 h1?,h2?,h3?,則有:
h 1 = λ K r 1 , h 2 = λ K r 2 , h 3 = λ K t h_1 = \lambda K r_1, \quad h_2 = \lambda K r_2, \quad h_3 = \lambda K t h1?=λKr1?,h2?=λKr2?,h3?=λKt
1.3.3 正交性約束的代數轉化
通過 h 1 h_1 h1? 和 h 2 h_2 h2? 表達正交性條件:
-
正交性條件 r 1 T r 2 = 0 r_1^T r_2 = 0 r1T?r2?=0:
( 1 λ K ? 1 h 1 ) T ( 1 λ K ? 1 h 2 ) = 0 (\frac{1}{\lambda} K^{-1} h_1)^T (\frac{1}{\lambda} K^{-1} h_2) = 0 (λ1?K?1h1?)T(λ1?K?1h2?)=0化簡后得到:
h 1 T K ? T K ? 1 h 2 = 0 h_1^T K^{-T} K^{-1} h_2 = 0 h1T?K?TK?1h2?=0 -
單位模長條件 $ r_1^T r_1 = r_2^T r_2 = 1 $:
( 1 λ K ? 1 h 1 ) T ( 1 λ K ? 1 h 1 ) = ( 1 λ K ? 1 h 2 ) T ( 1 λ K ? 1 h 2 ) (\frac{1}{\lambda} K^{-1} h_1)^T (\frac{1}{\lambda} K^{-1} h_1) = (\frac{1}{\lambda} K^{-1} h_2)^T (\frac{1}{\lambda} K^{-1} h_2) (λ1?K?1h1?)T(λ1?K?1h1?)=(λ1?K?1h2?)T(λ1?K?1h2?)化簡后得到:
h 1 T K ? T K ? 1 h 1 = h 2 T K ? T K ? 1 h 2 h_1^T K^{-T} K^{-1} h_1 = h_2^T K^{-T} K^{-1} h_2 h1T?K?TK?1h1?=h2T?K?TK?1h2?
1.3.4 引入對稱矩陣 $ B $ 簡化計算
定義對稱矩陣 B = K ? T K ? 1 B = K^{-T} K^{-1} B=K?TK?1,其元素僅與內參矩陣 K K K 相關。將上述兩個條件轉化為:
{ h 1 T B h 2 = 0 h 1 T B h 1 = h 2 T B h 2 \begin{cases} h_1^T B h_2 = 0 \\ h_1^T B h_1 = h_2^T B h_2 \end{cases} {h1T?Bh2?=0h1T?Bh1?=h2T?Bh2??
矩陣 $ B $ 的表達式為:
B = [ 1 f x 2 ? γ f x 2 f y γ v 0 ? f y u 0 f x 2 f y ? γ f x 2 f y γ 2 f x 2 f y 2 + 1 f y 2 ? γ ( γ v 0 ? f y u 0 ) f x 2 f y 2 ? v 0 f y 2 γ v 0 ? f y u 0 f x 2 f y ? γ ( γ v 0 ? f y u 0 ) f x 2 f y 2 ? v 0 f y 2 ( γ v 0 ? f y u 0 ) 2 f x 2 f y 2 + v 0 2 f y 2 + 1 ] B = \begin{bmatrix} \frac{1}{f_x^2} & -\frac{\gamma}{f_x^2 f_y} & \frac{\gamma v_0 - f_y u_0}{f_x^2 f_y} \\ -\frac{\gamma}{f_x^2 f_y} & \frac{\gamma^2}{f_x^2 f_y^2} + \frac{1}{f_y^2} & -\frac{\gamma (\gamma v_0 - f_y u_0)}{f_x^2 f_y^2} - \frac{v_0}{f_y^2} \\ \frac{\gamma v_0 - f_y u_0}{f_x^2 f_y} & -\frac{\gamma (\gamma v_0 - f_y u_0)}{f_x^2 f_y^2} - \frac{v_0}{f_y^2} & \frac{(\gamma v_0 - f_y u_0)^2}{f_x^2 f_y^2} + \frac{v_0^2}{f_y^2} + 1 \end{bmatrix} B= ?fx2?1??fx2?fy?γ?fx2?fy?γv0??fy?u0????fx2?fy?γ?fx2?fy2?γ2?+fy2?1??fx2?fy2?γ(γv0??fy?u0?)??fy2?v0???fx2?fy?γv0??fy?u0???fx2?fy2?γ(γv0??fy?u0?)??fy2?v0??fx2?fy2?(γv0??fy?u0?)2?+fy2?v02??+1? ?
其中 f x , f y , u 0 , v 0 , γ f_x, f_y, u_0, v_0, \gamma fx?,fy?,u0?,v0?,γ 為內參參數。
1.3.5 構建線性方程組求解 B B B
將單應性矩陣 H H H 的元素代入約束方程:
-
正交性方程:
h 11 h 21 B 11 + ( h 11 h 22 + h 12 h 21 ) B 12 + ? + h 31 h 32 B 33 = 0 h_{11} h_{21} B_{11} + (h_{11} h_{22} + h_{12} h_{21}) B_{12} + \cdots + h_{31} h_{32} B_{33} = 0 h11?h21?B11?+(h11?h22?+h12?h21?)B12?+?+h31?h32?B33?=0 -
單位模長方程:
h 11 2 B 11 + 2 h 11 h 12 B 12 + ? + h 31 2 B 33 = h 21 2 B 11 + ? + h 32 2 B 33 h_{11}^2 B_{11} + 2 h_{11} h_{12} B_{12} + \cdots + h_{31}^2 B_{33} = h_{21}^2 B_{11} + \cdots + h_{32}^2 B_{33} h112?B11?+2h11?h12?B12?+?+h312?B33?=h212?B11?+?+h322?B33?
每幅標定圖像提供一個 $ H $,對應兩個方程。B為對稱矩陣所以有6個自由度,內參矩陣有5個自由度,因此最少需要3張照片提供6個方程求解B及內參。若使用 n n n 幅圖像,可構建 2 n 2n 2n 個方程的線性方程組:
V b = 0 V b = 0 Vb=0
其中:
- V V V 是系數矩陣,
- b = [ B 11 , B 12 , B 13 , B 22 , B 23 , B 33 ] T b = [B_{11}, B_{12}, B_{13}, B_{22}, B_{23}, B_{33}]^T b=[B11?,B12?,B13?,B22?,B23?,B33?]T 是 B B B 的向量化形式。
通過 奇異值分解(SVD) 求解 b b b,再通過 Cholesky分解 從 B B B 中恢復內參矩陣 K K K 。
這一過程將幾何約束(旋轉矩陣的正交性)與代數計算(線性方程求解)結合,是張正友標定法能夠僅用平面棋盤格實現高精度標定的核心。
1.4 外參求解
已知 $ K $ 后,通過 $ H $ 分解外參:
r 1 = λ K ? 1 h 1 , r 2 = λ K ? 1 h 2 , t = λ K ? 1 h 3 r_1 = \lambda K^{-1} h_1, \quad r_2 = \lambda K^{-1} h_2, \quad t = \lambda K^{-1} h_3 r1?=λK?1h1?,r2?=λK?1h2?,t=λK?1h3?
其中 λ = 1 / ∥ K ? 1 h 1 ∥ \lambda = 1 / \|K^{-1} h_1\| λ=1/∥K?1h1?∥。
旋轉矩陣 R = [ r 1 r 2 r 1 × r 2 ] R = [r_1 \quad r_2 \quad r_1 \times r_2] R=[r1?r2?r1?×r2?],需正交化處理(如QR分解)。
1.5 非線性優化與畸變校正
優化目標函數:最小化重投影誤差:
∑ i = 1 n ∑ j = 1 m ∥ p i j ? p ^ ( K , R i , t i , k 1 , k 2 , X j ) ∥ 2 \sum_{i=1}^n \sum_{j=1}^m \| p_{ij} - \hat{p}(K, R_i, t_i, k_1, k_2, X_j) \|^2 i=1∑n?j=1∑m?∥pij??p^?(K,Ri?,ti?,k1?,k2?,Xj?)∥2
其中 $ k_1, k_2 $ 為徑向畸變系數,畸變模型為:
u 畸變 = u ( 1 + k 1 r 2 + k 2 r 4 ) u_{\text{畸變}} = u (1 + k_1 r^2 + k_2 r^4) u畸變?=u(1+k1?r2+k2?r4)
采用Levenberg-Marquardt算法優化所有參數。
總結
張正友標定法通過單應性矩陣將棋盤格平面與圖像平面關聯,利用旋轉矩陣的正交性建立內參約束,最終通過線性與非線性優化聯合求解參數。公式推導的關鍵在于:
- 單應性矩陣的線性求解;
- 內參約束條件的正交性展開;
- 非線性優化的重投影誤差最小化。
該方法僅需平面棋盤格,無需精密設備,且精度較高,成為計算機視覺中廣泛應用的標定方法。
2opencv源碼解析
OpenCV的cv::calibrateCamera
函數是相機標定算法的核心實現,其源碼邏輯融合了張正友標定法的數學原理與非線性優化技術。以下從源碼層面對其核心流程和關鍵模塊進行深度剖析,并結合OpenCV 4.8版本代碼結構展開說明。
2.1 函數入口與參數解析
函數原型(簡化自modules/calib3d/src/calibration.cpp
):
double calibrateCamera(InputArrayOfArrays objectPoints, // 世界坐標點集(Z=0平面)InputArrayOfArrays imagePoints, // 圖像坐標點集Size imageSize, // 圖像尺寸InputOutputArray cameraMatrix, // 輸入/輸出內參矩陣InputOutputArray distCoeffs, // 輸入/輸出畸變系數OutputArrayOfArrays rvecs, // 輸出旋轉向量OutputArrayOfArrays tvecs, // 輸出平移向量int flags, // 標定標志位TermCriteria criteria) // 優化終止條件
關鍵參數說明:
- flags:控制標定行為的標志位,例如:
CALIB_USE_INTRINSIC_GUESS
:使用用戶提供的初始內參矩陣。CALIB_FIX_ASPECT_RATIO
:固定焦距比(fx/fy)。CALIB_ZERO_TANGENT_DIST
:忽略切向畸變(p1=p2=0)。
- criteria:優化終止條件(默認迭代30次或誤差<1e-6)。
2.2 源碼核心流程
階段1:數據校驗與初始化
// 檢查輸入數據合法性
CV_Assert(objectPoints.type() == CV_32FC3 || objectPoints.type() == CV_64FC3);
CV_Assert(imagePoints.type() == CV_32FC2 || imagePoints.type() == CV_64FC2);// 初始化內參矩陣和畸變系數
if (!(flags & CALIB_USE_INTRINSIC_GUESS)) {cameraMatrix = Mat::eye(3, 3, CV_64F); // 默認初始化為單位矩陣distCoeffs = Mat::zeros(5, 1, CV_64F); // 默認僅考慮k1,k2,p1,p2,k3
}
階段2:計算單應性矩陣(Homography)
代碼路徑:modules/calib3d/src/homography.cpp
// 對每幅圖像計算H矩陣
for (int i = 0; i < nimages; i++) {Mat H = findHomography(objectPoints[i], imagePoints[i], RANSAC);homographies.push_back(H);
}
數學原理:單應性矩陣 H H H 滿足 s [ u v 1 ] = H [ X Y 1 ] s \begin{bmatrix}u \\ v \\ 1\end{bmatrix} = H \begin{bmatrix}X \\ Y \\ 1\end{bmatrix} s ?uv1? ?=H ?XY1? ?,通過SVD分解最小化重投影誤差求解。
階段3:構建約束方程求解內參矩陣
核心代碼(簡化自modules/calib3d/src/calibration.cpp
):
// 步驟1:定義對稱矩陣B = K^{-T}K^{-1}
Mat B(3, 3, CV_64F);
B.at<double>(0,0) = 1.0 / (fx*fx);
B.at<double>(0,1) = -gamma / (fx*fx*fy);
// ... 其他元素根據內參展開// 步驟2:構建線性方程組V*b=0
Mat V(2*nimages, 6, CV_64F); // 每幅圖像貢獻2個方程
for (int i = 0; i < nimages; i++) {Mat h1 = homographies[i].col(0);Mat h2 = homographies[i].col(1);// 填充正交性約束和單位模長約束V.row(2*i) = ...; // h1^T*B*h2=0V.row(2*i+1) = ...; // h1^T*B*h1 = h2^T*B*h2
}// 步驟3:SVD求解最小特征值對應的b向量
SVD::solveZ(V, b);// 步驟4:Cholesky分解恢復內參矩陣K
Mat KInv = chol(B);
K = KInv.inv();
數學推導:通過旋轉矩陣的正交性 $ r_1^T r_2 = 0 $ 和單位模長約束 $ |r_1| = |r_2| = 1 $,將單應性矩陣 $ H $ 分解為內參矩陣 $ K $ 和外參的線性組合。
階段4:外參(R,t)估計
for (int i = 0; i < nimages; i++) {Mat h1 = homographies[i].col(0);Mat h2 = homographies[i].col(1);Mat h3 = homographies[i].col(2);// 計算尺度因子λdouble lambda = 1.0 / norm(K.inv() * h1);// 分解外參Mat r1 = lambda * K.inv() * h1;Mat r2 = lambda * K.inv() * h2;Mat r3 = r1.cross(r2); // 通過叉乘保證正交性Mat t = lambda * K.inv() * h3;// 構建旋轉矩陣并正交化Mat R;Rodrigues(rvec, R); // 旋轉向量轉矩陣SVDecomp(R, S, U, V, SVD::FULL_UV); // 正交化處理R = U * V.t();
}
階段5:非線性優化(Levenberg-Marquardt算法)
代碼路徑:modules/calib3d/src/lm.cpp
// 定義目標函數:最小化重投影誤差
class CalibFunc : public LMSolver::Function {
public:int getDims() const { return totalPoints * 2; }void compute(const Mat& params, Mat& err) const {// 解析參數:內參、畸變、外參Mat K = params.rowRange(0, 9).reshape(3,3);Mat dist = params.rowRange(9, 14);Mat rvecs = params.rowRange(14, 14 + 3*nimages);Mat tvecs = params.rowRange(14 + 3*nimages, end);// 計算重投影誤差for (int i = 0; i < nimages; i++) {projectPoints(objectPoints[i], rvecs[i], tvecs[i], K, dist, reproj);err += norm(imagePoints[i] - reproj);}}
};// 調用優化器
LMSolver lm(solverFunc, criteria);
lm.run(params);
優化變量:將所有參數(內參、畸變、每幅圖像的外參)拼接為一個長向量,通過迭代更新使重投影誤差最小化。
2.3 畸變模型與參數處理
畸變系數定義(modules/calib3d/src/distortion_model.hpp
):
enum DistCoeffs {K1 = 0, K2 = 1, P1 = 2, P2 = 3, K3 = 4 // 默認支持5參數模型
};
畸變校正公式:
{ x corrected = x ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) + 2 p 1 x y + p 2 ( r 2 + 2 x 2 ) y corrected = y ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) + p 1 ( r 2 + 2 y 2 ) + 2 p 2 x y \begin{cases} x_{\text{corrected}} = x(1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + 2p_1 xy + p_2(r^2 + 2x^2) \\ y_{\text{corrected}} = y(1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + p_1(r^2 + 2y^2) + 2p_2 xy \end{cases} {xcorrected?=x(1+k1?r2+k2?r4+k3?r6)+2p1?xy+p2?(r2+2x2)ycorrected?=y(1+k1?r2+k2?r4+k3?r6)+p1?(r2+2y2)+2p2?xy?
其中 $ r^2 = x^2 + y^2 $。優化過程中會根據flags
決定是否固定某些系數(如CALIB_FIX_TANGENT_DIST
)。
寫在后面的話
旋轉矩陣性質
一、旋轉矩陣作為正交矩陣的數學定義
旋轉矩陣是正交矩陣的一種特殊形式。根據正交矩陣的定義:
- 正交性:列向量(或行向量)兩兩正交,即內積為零。
- 單位模長:每個列向量的模長為1。
- 行列式為1:若行列式為+1,則為純旋轉矩陣;若為-1,則為反射矩陣(含鏡像變換)。
數學推導:
-
正交矩陣滿足 $ R^T R = I $,展開后得到:
{ r i T r j = 0 ( i ≠ j ) ∥ r i ∥ = 1 ( i = j ) \begin{cases} r_i^T r_j = 0 \quad (i \neq j) \\ \|r_i\| = 1 \quad (i = j) \end{cases} {riT?rj?=0(i=j)∥ri?∥=1(i=j)?因此,旋轉矩陣的列向量 $ r_1, r_2, r_3 $ 必然滿足正交性和單位模長。對于n階正交矩陣,其列向量組是n維向量空間的一組標準正交基。