文章目錄
- 引言
- 透視變換(projective transform)
- 單應性(Homography)
- opencv代碼
- 仿射變換相關函式
- 投影變換相關的函式
- 鳥瞰圖代碼示例
- 小結
引言
影像的幾何變換通常包括拉伸、縮放、扭曲和旋轉等操作,
對于平面區域來說,分為兩類幾何轉換:1
- ??仿射變換(affine transform),基于
2x3矩陣進行變換,指影像可以通過一系列的幾何變換來實作平移、旋轉等多種操作,該變換能夠保持影像的平直性和平行性,平直性是指影像經過仿射變換后,直線仍然是直線;平行性是指影像在完成仿射變換后,平行線仍然是平行線, - ??透視變換(projective transform),基于
3x3矩陣進行變換,透視變換將視錐體轉換為長方體形狀,視錐體的近端比遠端小,具有擴大相機附近物體的效果,透視變換可以改變平行關系,將矩形映射為任意四邊形,
透視變換通常被用于當作從特定角度觀察三維平面的計算方法(非垂直觀測),在三維視覺領域具有廣泛的應用,
本文主要介紹opencv中的透視變換(projective transform)原理和代碼,
透視變換(projective transform)
透視變換,又稱為投影變換,是指將坐標為 ( X , Y , Z ) (X,Y,Z) (X,Y,Z)的物理點 Q Q Q映射到投影平面上坐標為 ( x , y ) (x,y) (x,y)的點 q q q的程序1,

基本投影幾何
將定義攝像機引數的矩陣(包含 f x , f y , c x , c y f_x,f_y,c_x,c_y fx?,fy?,cx?,cy?)稱為攝像機的內引數矩陣(camera intrinsics matrix),
物理世界中的點 Q Q Q投影到攝像機上的點 q q q的程序,可以用下式表示:
q = M ? Q , 其 中 q = [ x y w ] , M = [ f x 0 c x 0 f y c y 0 0 1 ] , Q = [ X Y Z ] q=M\cdot{Q},其中q= \begin{bmatrix} x \\ y \\ w \end{bmatrix} , M=\begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} ,Q=\begin{bmatrix} X \\ Y \\ Z \end{bmatrix} q=M?Q,其中q=???xyw????,M=???fx?00?0fy?0?cx?cy?1????,Q=???XYZ????
單應性(Homography)
計算機視覺中,平面的單應性被定義為從一個平面到另一個平面的投影映射,(注:“單應性”在不同學科有不同含義,在數學上有更通用的意思,這里僅說明計算機視覺中的單應性,1)
二維平面上的點映射到攝像機成像畫面上的映射,就是平面單應性的典型例子,

利用齊次坐標,可以對物理世界的點Q到成像畫面上的點q的映射進行表示:
q
=
s
?
M
?
W
?
Q
q =s \cdot{M}\cdot{W} \cdot{Q}
q=s?M?W?Q
其中,引數s表示尺度比例,
M
=
[
f
x
0
c
x
0
f
y
c
y
0
0
1
]
M=\begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix}
M=???fx?00?0fy?0?cx?cy?1???? ,W表示旋轉R和平移t的影響之和
W
=
[
R
t
]
W = [R \space\space\space t]
W=[R t],旋轉矩陣
R
=
[
r
1
?
r
2
?
r
3
?
]
R=\begin{bmatrix} \vec{r_1} & \vec{r_2} & \vec{r_3} \end{bmatrix}
R=[r1?
??r2?
??r3?
??]
由于我們只關注這個物體平面,為了簡化計算,令Z=0:
[
x
y
1
]
=
s
?
M
?
[
r
1
?
r
2
?
r
3
?
t
?
]
?
[
X
Y
0
1
]
=
s
?
M
?
[
r
1
?
r
2
?
t
?
]
?
[
X
Y
1
]
\begin{bmatrix} x \\ y \\ 1 \end{bmatrix} =s \cdot{M}\cdot{\begin{bmatrix} \vec{r_1} & \vec{r_2} & \vec{r_3} & \vec{t} \end{bmatrix}} \cdot{\begin{bmatrix} X \\ Y \\ 0 \\ 1 \end{bmatrix}} =s \cdot{M}\cdot{\begin{bmatrix} \vec{r_1} & \vec{r_2} & \vec{t} \end{bmatrix}} \cdot{\begin{bmatrix} X \\ Y \\ 1 \end{bmatrix}}
???xy1????=s?M?[r1?
??r2?
??r3?
??t
?]??????XY01??????=s?M?[r1?
??r2?
??t
?]????XY1????
用H表示轉換矩陣:
H
=
s
?
M
?
[
r
1
?
r
2
?
t
?
]
H = s \cdot{M}\cdot{\begin{bmatrix} \vec{r_1} & \vec{r_2} & \vec{t} \end{bmatrix}}
H=s?M?[r1?
??r2?
??t
?]
H由兩部分組成:用于定位觀察的物體平面的物理變換和使用攝像機內引數矩陣的投影,
對于同一攝像頭拍攝的畫面來說,無需計算內參矩陣和物理變換,僅通過下面這個簡化的方程,就能利用單應性矩陣H將源平面上的點與目標像平面上的點聯系起來:
P
d
s
t
=
H
P
s
r
c
,
P
s
r
c
=
H
?
1
P
d
s
t
P_{dst} = HP_{src},P_{src} = H^{-1}P_{dst}
Pdst?=HPsrc?,Psrc?=H?1Pdst?
P
d
s
t
=
[
x
d
s
t
y
d
s
t
1
]
,
P
s
r
c
=
[
x
s
r
c
y
s
r
c
1
]
P_{dst} = \begin{bmatrix} x_{dst} \\ y_{dst} \\ 1 \end{bmatrix}, P_{src} = \begin{bmatrix} x_{src} \\ y_{src} \\ 1 \end{bmatrix}
Pdst?=???xdst?ydst?1????,Psrc?=???xsrc?ysrc?1????
有了這個簡化的公式,我們就能明白opencv中求解單應性矩陣的原理了,
opencv代碼
仿射變換相關函式
- cv::transform:對一組點進行仿射變換
- cv::warpAffine:對整幅影像進行仿射變換
- cv::getAffineTransform:從一組點計算仿射變換矩陣
- cv::getRotationMatrix2D:計算旋轉矩陣
投影變換相關的函式
- cv::perspectiveTransform:對一組點進行透射變換/投影變換
- cv::warpPerspective:對整幅影像進行透視變換/投影變換
- cv::getPerspectiveTransform:獲取透視變換/投影變換矩陣
- cv::findHomography:計算單應性矩陣
其中,findHomography的method引數用于選擇計算單應性矩陣的演算法,
- cv::RANSAC:隨機抽樣方法( random sampling with consensus),隨機選擇所提供點的子集,并計算一個同源矩陣,RANSAC演算法計算許多這樣的隨機抽樣,并保留具有最大部分的抽樣,該方法在實際應用中在拒絕噪聲離群資料和尋找正確答案方面非常有效
- cv::LMEDS:最小二乘中位數(least median of squares method),顧名思義,LMeDS背后的想法是最小化中值誤差,而不是用默認方法基本上最小化的均方誤差,這種方法的缺點是,只有當插入器至少構成資料點的大多數時,它才能表現良好,相比之下,RANSAC可以正常作業,并在給出幾乎任何信噪比時給出令人滿意的答案,
- cv::RHO:RHO演算法,在OpenCV3中使用,它基于一種被稱為PROSAC的“加權”RANSAC修改,在許多例外值的情況下運行得更快,
鳥瞰圖代碼示例
《Learning OpenCV》中有一個經典的例子,是將前置車載攝像頭拍攝的影像,利用透視變換轉換成鳥瞰圖的視角,
這里的做法是,選取前置攝像頭拍攝的透視圖中的一塊區域的四個點,獲取影像中這四個點對應在俯瞰視角中的坐標點,計算轉換矩陣,然后進行重映射,就能將前視圖重映射到鳥瞰圖,

在沒有相機標定引數的情況下,可以利用物理平面和像平面中的四個對應點計算單應性矩陣,從而實作從透視圖變換到鳥瞰圖的效果,
python代碼如下:
import numpy as np
import cv2 as cv
# 讀取影像
src = cv.imread(img_path)
# 獲取四個對應點
dstPts = np.array([(0,0),(640,0),(0,520),(640,520)])
srcPts = np.array([(265,99),(696,99),(129,473),(832,473)])
# 獲取單應性矩陣
H = cv.findHomography(srcPts,dstPts,method=cv.RANSAC)
#M = cv.getPerspectiveTransform(objPts,imgPts)
print(f"Homography: {H.shape} \n{H}")
if len(H)>1:
H = H[0]
# 利用轉換矩陣進行重映射(Remap)
birdView = cv.warpPerspective(src,H,None,cv.INTER_LINEAR | cv.WARP_INVERSE_MAP | cv.WARP_FILL_OUTLIERS)
# 顯示重映射后的鳥瞰圖
while (1):
cv.imshow("perspective", birdView)
if cv.waitKey(100) == ord('q'): # 按下q退出
break
cv.destroyAllWindows()
如果需要對影像進行反變換,可以利用numpy對矩陣求逆np.linalg.inv(H),作為cv.warpPerspective的轉換矩陣,
小結
本文整理了計算機視覺中透視變換 / 投影變換 / 單應性的基本概念,以及OpenCV中的函式和使用示例,
如果對你有幫助的話,歡迎一鍵三連支持下博主~
《Learning OpenCV 3》 ?? ?? ??
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300573.html
標籤:其他
上一篇:二輪技術考核
