基于OpenCV的透視圖轉(zhuǎn)化為不同平面
點擊上方“小白學(xué)視覺”,選擇加"星標"或“置頂”
重磅干貨,第一時間送達

由于相機技術(shù)的進步,相機能夠以各種角度和視角拍攝照片。無人機的廣角,鳥瞰圖,側(cè)視圖等不同的角度,魚眼鏡頭之類的不同相機鏡頭將場景投射到相機圖像平面上的方式與對象在世界上的實際位置不同。這種現(xiàn)象被稱為攝影中的透視變形。
雷梅霍夫?qū)懙健扮R子中物體的距離小于它們的實際距離”,總是在側(cè)視鏡其中大部分是傾斜,稍彎曲。由于這種曲率,我們在鏡子中看到的圖像中會發(fā)生透視失真。
形式上,透視失真是對象及其周圍區(qū)域的扭曲或變形,由于附近和遠處特征的相對比例,該扭曲或變形與對象在正常焦距下的外觀明顯不同。我們將介紹如何根據(jù)給定的2D攝影機圖像(在特定的假設(shè)下)校正這些變形,以找出物體在世界上的實際位置。
首先,我們必須了解世界上的3d對象如何投影到相機的圖像平面上。

從本質(zhì)上講,光線是通過相機的針孔投射到物體上的。當(dāng)從物體反射時,該光會投射在相機內(nèi)部的圖像平面上,并給出倒置的圖像。為了獲得實際視圖,請將該圖像平面反轉(zhuǎn)(上圖中的虛擬圖像平面)。
無需深入研究數(shù)學(xué)細節(jié),就可以將對象在3d世界中的坐標轉(zhuǎn)換為2d平面平面。

在數(shù)學(xué)上,將3d坐標乘以3x4矩陣(稱為透視矩陣)可得到圖像平面中的2d坐標。

使用3x4透視矩陣將3d世界坐標系中的點(x,y,z)轉(zhuǎn)換為2d相機圖像平面上的點(u,v)。
但是在這篇文章中,我們想找到一個從2d圖像平面到世界坐標的矩陣。直觀地講,這是不可能的,因為在2d圖像平面中,我們丟失了深度尺寸,并且在沒有任何額外知識的情況下也無法恢復(fù)3d尺寸(這就是RGB-D相機退出的原因)。同樣在數(shù)學(xué)上,3x4投影矩陣不是正方形的,因此是不可逆的。
但是,如果我們僅對固定z的對象的(x,y)世界坐標感興趣,則可以找到這些坐標。例如,如果我們在無人機的頂部有一個安全攝像機,并且我們想從攝像機圖像中知道人在地板上的實際位置(將固定z = 0作為地板平面),則有可能有兩種方法可以做到這一點:
如果需要(x,y)世界坐標的平面在系統(tǒng)的z = 0處,則地板平面上的任何點都將具有坐標<x,y,0>,這有效地消除了第三個坐標的影響透視矩陣從等式1開始的一列?,F(xiàn)在,透視矩陣P可以簡化為3x3矩陣,因此變?yōu)榭赡娴模ㄈ缦滤荆?/span>

現(xiàn)在要從(u,v)得到(x,y),我們只需要找到3x3透視矩陣P的逆,就可以從像平面找到地板平面上的對應(yīng)點。但是,如果我們想在z不等于0的任意平面上找到(x,y)坐標,該怎么辦。我們可以使用Homography來實現(xiàn)這一點。
單應(yīng)矩陣涉及從一個平面到另一平面的變換。本質(zhì)上,如果我們在一個平面中具有<u,v>點,而在另一平面中具有<x,y>,則從<u,v>到<x,y>的轉(zhuǎn)換可以寫為

但是要獲得單應(yīng)性矩陣,我們必須在一個平面上至少需要4個點,而在另一平面上至少需要它們的映射點。給定透視矩陣P,我們可以輕松找到任意3d世界平面(保持固定的z)和2d平面之間的4個對應(yīng)點。
在OpenCV中,可以cv2.findHomography通過在源平面和目標平面中提供4個或更多點來使用函數(shù)查找單應(yīng)矩陣。
下面是使用OpenCV的代碼。
import cv2import numpy as npdefget_inverse_pespective(perspective_matrix: np.array)-> np.array:"""This method calculates the inverse of prespective matrix by homography.-Takes 4 random points on the floor plane(destination_plane) and calculates thecorresponding pointsonthe camera image plane(src_plane) using perspective matrix.-Calculates the Homography matrix to map any point in image plane to floorplane.Parameters----------perspective_matrix: 3 x 4 camera prespective matrix to convert 3dhomogeneous world coordinates to2dhomogeneous camera coordinates.Returns----------3x3homography matrix for moving from 2d homogeneous image plane to world floorplane(at z=0)"""#Take 5 homogenous points on the floor(Unit is in Meters)pts_dst = np.array([[0,0,0,1],[0,1,0,1],[1,0,0,1],[1,1,0,1],[0,0,0,1]])#Obtain respective homogenous points on the image planepts_src = (perspective_matrix @ pts_dst.T).T#convert homogenous coordinates to cartesian coorndinatespts_src_cart = np.array([[x/w, y/w] for x,y,w in pts_src])pts_dst_cart = np.array([[x/w, y/w] for x,y,z,w in pts_dst])#find the 3x3 Homography Matrix for transforming image plane to floorplaneH,status = cv2.findHomography(pts_src_cart, pts_dst_cart)return Hdef project_to_floor(image_coordinates:List[int], H: np.array) -> List[int]:"""This method takes the Homography matrix and the 2d image cartesiancoordinates. It returns the (x, y)cartesian coordinates in 3d cartesian world coordinates on floorplane(at z=0). Notice that z coordinate is omittedhere and added inside the tracking funtion.Parameters----------image_coordinates: 2d pixel coordinates (x,y)h:3x3 Homography matrix np.array[3x3]Returns----------floor_coordinates: List of x, y coordinates in 3d world of same pixel onfloor plane i.e. (x,y,z) Considering z=0 andommitted here."""#adding 1 for homogenous coordinate systemx,y, w = H @ np.array([[*image_coordinates, 1]]).Treturn [x/w, y/w]p = np.random.rand(3,4)H = get_inverse_pespective(p)src_point = (5,10)dst_point = project_to_floor(src_point, H)
一旦獲得了單應(yīng)性矩陣,就可以使用等式2從像平面移動到所需平面。這些方法并不暗示有關(guān)世界坐標系中沿z軸的位置的任何信息,并認為它是固定的。
需要注意:
1.對于在世界坐標中從“圖像”平面到固定平面的“透視”轉(zhuǎn)換,可以使用兩種方法。
2.如果平面方程為z = 0,則可以通過完全忽略第3列將3x4透視矩陣簡化為3x3矩陣,并且可以使用此3x3矩陣的逆矩陣。
3.對于任何其他任意平面,應(yīng)使用單應(yīng)性矩陣。為了找到單應(yīng)矩陣,該cv.findhomography方法在兩個平面中至少需要4個對應(yīng)點。
交流群
歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN、算法競賽等微信群(以后會逐漸細分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~

