模型
我們最常見的投影模型描述了針孔相機的成像原理。從上圖可以基于相似三角形得出結論
frac{X_c}{Z_c} = frac{u-c_x}{f}tag{1}\
其中 c_x 是圖像中光軸的 x 坐標。 如果相機的光軸與感光元件完全對齊,則c_x = frac{1}{2}W,W為圖像的寬度(像素)
當我們最常見的將三維點投影到像素坐標系中時,可以直接使用下面的公式,它對應的是針孔相機模型。
begin{}u \v \ 1\ end{} = begin{} f_x \ 0 \ c_x\ 0 \ f_y \ c_y\ 0 \ 0 \ 1\ end{} begin{} X_c \Y_c\Z_cend{} tag{2}\
p=KP標簽{3}\
其中P為相機坐標系中的三維點,K為相機內參,p為像素坐標系中的坐標。
實際計算時上面的公式也可以寫成下面的公式
{ begin{align} &u=frac{}{Z_c} + c_x\ &v=frac{}{Z_c} + c_y end{align}tag{4}\
如果我們加上將世界坐標系的點轉移到相機坐標系的過程,上面的投影過程就變成了
p=K[R|t]P_wtag{5}\
總結
這部分可以直接參考:鏈接包含畸變模型。 稍后將介紹失真模型。
不同相機型號
以上就是針孔相機的成像過程。 需要注意的一點是,對于相機坐標系中的點P,無論如何延伸,在圖片上的成像點都是同一個點。 也就是說,對于一個三維點,乘以一個系數,上述模型中的成像點保持不變。 這一點對于后面了解其他相機型號其實特別重要。
什么是相機型號
一句話總結:相機模型從數學上描述了現實世界中的三維點與圖像中的像素坐標之間的映射關系。
經典成像模型
由于成像模型是用來描述真實相機鏡頭的投影關系的,因此理論與現實之間不可避免地存在差距。 因此,研究人員設計了不同的成像模型來描述不同鏡頭的投影關系。 真實的物理鏡頭也可以基于這些數學模型進行設計。 其實只要成像角度比鏡頭稍大一點(可以想象為魚眼鏡頭),如果還是用簡單的針孔模型來描述,偏差就會很大,所以需要不同的相機模型來描述它。
經典成像模型的第一步是首先將三維坐標點投影到單位球體(Unit)上。 有時這個單位球體也稱為
P_s=frac{P_c}{||P_c||}=[frac{X_c}{||P_c||},frac{Y_c}{||P_c||},frac{Z_c}{|| P_c||}]\
資料來源:DSO:與
這部分的經典論文是::The Wrong Model
參考:錯誤的模型; 首先將三維點投影到單位球面上。 其在圖像上的成像點與圖像y軸之間的角度保持不變。 它與圖像上原點的距離是角度 α 的函數。
q=sqrt{(X_s^2+Y_s^2)}\ alpha=atan(q,Z_s)\ beta=atan(Y_s,X_s)tag{6}\
上圖中的點P=[X_s,Y_s,Z_s]就是三維點投影到單位圓上后的點。 當該點投影到圖像上時,與圖像x軸的角度保持不變。 它到圖像中心的距離是anglealpharho(alpha)的函數,這個函數的不同形式對應著不同的經典成像模型
經典成像模型的成像功能
上圖來自于
本文直觀地列出了五種經典投影模型的投影函數。 與上面的表示法略有不同,上面引用的論文的表達方式更加統一,但不太直觀。 上圖中的θ可以看作是式(6)中β角為0時退化的α角。因此,無論是從博文還是論文《The Wrong Model》中,我們都可以推導出如下的成像方程:五款經典相機型號。 這里我們仍然用論文中的表述:The Wrong Model 來描述。
rho(alpha)=k tan(alpha), ( ) rho(alpha)=k tan(frac{alpha}{2}), ( ) rho(alpha )=k alpha, ( ) rho(alpha)=k sin(alpha), (正弦律 ) rho(alpha)=k sin(frac{alpha} {2}),(等實體角度)不同成像模型的半徑投影方程函數圖
:為什么錯誤的模型可以投影到單位球體上
無論是小孔成像模型還是其他模型,都可以看作是首先將世界的點縮放到單位球。 這是可能的原因是,在從相機的光學中心發出的線上,線上的所有點都被投影到相同的像素值。 也就是說,我們做投影的時候,按一個常數縮放的結果是一樣的。 教程中對此進行了描述:
因此,對于 k≠0,一個點的所有 k*Ph 都指向同一點 Ph。其中的一個是,在 a 下,所有 Ph 都指向同一點。 這就是這樣做的原因,因為沿著一條射線,所有的射線都指向同一個圖像點,例如,沿著上面模型的圖像中的紅色射線,所有的射線都指向同一個圖像。 這也是模型中的比例 s。 概括
如果你想對這部分有更全面(但很基礎)的了解,可以按照以下順序閱讀:
:錯誤(用更多的函數圖來描繪不同投影方程的距離差異、成像角度差異等) 鏡頭(用實際圖片展示不同投影模型的成像效果) 相機的畸變
不同的相機型號對應不同類型的物理鏡頭,但在實際的物理鏡頭中不可能完美對應某個相機型號。 這里的不完善之處包括鏡頭本身的安裝誤差和成像模型本身的表達限制。 事實上,鏡頭制造商的主要工作之一就是設計和生產盡可能接近相機型號的鏡頭。
因此,成像模型與真實鏡頭成像之間的差異稱為畸變。 失真也可以通過一定的數學函數來描述。 可以簡單的理解,畸變就是在完美的相機成像模型中間插入一個函數,使得最終的像素坐標與利用相機投影關系得到的坐標不一致。
但需要注意的是,實際代碼中“失真”一詞的含義并不是消除成像模型與真實物理成像過程之間的特定差距。 用于消除失真的代碼實際上校正了圖片的成像過程以使用透視。 ( ) 模型的圖像。 也就是說,圖像去除畸變后,圖像的投影函數僅用透視投影的四個參數(fx,fy,cx,cy)來表示。
以透視投影鏡頭中出現的徑向畸變模型為例,本文中的公式(4)實際上會變為
begin{} u\v\ end{} = begin{} f_x g_1(x',y';omega) + c_x\ f_y g_2(x',y';omega) + c_y end{}tag{7}\
在
begin{} x'\y'\ end{} = begin{} X_c/Z_c\ Y_c/Z_c end{}tag{8}\
式(7)中的函數g(cdot,cdot;omega)描述了畸變模型。 可以看出:給出了最經典的畸變模型之一。
總結
嚴格來說(不知道對不對),畸變這個詞應該描述的是實際情況不可能完美,所以沒有一個相機模型能夠完美地描述物理鏡頭。 這里的實際誤差稱為失真。
但是當使用或者其他工具庫去畸變的時候,意思就是我們用一個高階函數來擬合相機和小孔成像相機之間的間隙,然后用優化的方法來使用這個高階函數的系數。階函數(畸變參數)將圖像轉換為使用針孔成像過程成像的圖片。
也就是說,去除畸變后,你可以認為該圖片就是利用針孔成像模型成像的圖片。
全景相機( )-CMei型號
上面提到的不同相機型號已經有很多成像模型,理論上可以成像水平角度大于180度的圖像。 后來,不同的研究人員提出了不同的全景相機模型來模擬全景相機的成像過程。
:通過鏡片實現小孔成像原理,主要是折射; :使用標準相機加遮罩; :通過多個攝像頭重疊視野;
實現了兩個成像模型的標定小孔成像原理,即
CMei 的 View Point from Grids,位于 cv:: 命名空間
和 cv:: 命名空間中的模型 和 for 、廣角和魚眼
這里我們以CMei模型為例。 投影過程如下圖所示。
代碼示例1:針孔相機去畸變(模型)
# undistort image
h, w = img.shape[:2]
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(K, distortions, (w,h), alpha, (w,h))
undistorted_img = cv2.undistort(img, K, distortions, None, newcameramtx)
x, y, w, h = roi
undistorted_img = undistorted_img[y:y+h, x:x+w]
# undistort image points
if points2d.ndim == 2:
points2d = points2d[:, None, :]
undistorted_points = cv2.undistortPoints(points2d, K, distortions, P=K)
undistorted_points = undistorted_points.reshape(-1, 2)
代碼示例 2:全向鏡頭去畸變 ( )
# undistort image
if newK:
K_new = np.zeros((3,3), np.float64)
h,w = img.shape[:2]
K_new[0, 0] = w/4
K_new[0, 2] = w/2
K_new[1, 1] = h/4
K_new[1, 2] = h/2
K_new[2, 2] = 1.0
else:
K_new = None
undistorted_img = cv2.omnidir.undistortImage(
img, K, distortions, Xi, cv2.omnidir.RECTIFY_PERSPECTIVE, Knew=K_new)
# undistort image points
if points2d.ndim == 2:
points2d = points2d[:, None, :]
undistorted_points = cv2.omnidir.undistortPoints(points2d, K, distortions, Xi, None)
undistorted_points = undistorted_points.squeeze()
f0 = K_new[0,0]
f1 = K_new[1,1]
c0 = K_new[0,2]
c1 = K_new[1,2]
undistorted_points[:, 0] = f0* undistorted_points[:, 0] + c0
undistorted_points[:, 1] = f1 * undistorted_points[:, 1] + c1
一個坑
舊版本的cv2::::有bug,請參考這個issue。 Space尚未成為官方穩定接口,因此它被維護在--包中。 最新的軟件包 (4.6.x) 已修復錯誤。 請務必檢查是否存在該錯誤! ! ! !
代碼示例三:魚眼相機去畸變( )
這部分接口還沒有使用過。 用完之后我會補上的。
相機標定方法張正友標定方法也是使用的算法。中文解釋原文其他信息
這個CSDN專欄的投影模型系列文章看起來很專業、很系統,但我還沒讀過。
::: 有一篇文章從模型、廣角、魚眼三個方面簡單介紹了相機View Point的統一投影模型:The Wrong Model相機底層