前言
在之前的文章中,介紹過相機矩陣,這是針對單個相機的,可我們知道單個相機圖片並不能告訴我們物體的深度信息,這時至少需要兩個相機,這樣在兩視圖間內在的射影幾何關係就是
對極幾何
,而基礎矩陣
就是對極幾何的代數表示。本文主要介紹對極幾何和基礎矩陣。
一、對級幾何
首先,從應用的角度分析,對極幾何的出現是爲了解決什麼問題?
立體視覺幾何中有以下問題:
1.已知一幅圖像中一點,如何尋找另一幅圖像中這個點的對應點(根據是否知道相機的相對位置,此問題求解方式不同)
2.已知兩幅圖像中兩點是對應關係,如何求解兩相機的相對位置和姿態
3.已知多幅圖像中同一3D點的對應點,如何求解該3D點的3D座標
對極幾何/基礎矩陣的出現可以解決問題2。
1.1 基本概念
立體成像的基本幾何就是對極幾何。下圖是最經典的對極幾何示意圖。
如果僅看一個相機,我們並不能知道深度信息,可如果有兩個相機的話(就像人有兩隻眼睛)我們就能得到深度的信息。
在上圖中O和O’是兩個相機中心(也有可能是一個相機在不同時刻的位置),P點是物體所在位置,兩個相對的白色平面是像面(嚴格按照光路應該是在O1 O2點的後方,與P點相反方向,CV中默認採用這種往前畫的方式節省空間)。p1和p2是P點在像面上的對應點,e1 e2爲像面和O1 O2的交點。O1O2爲基線,也被稱作相機的移動方向。
在對極幾何中,e1和e2被稱作極點,PO1O2平面爲極面,p1e1爲極線,同理p2e2也爲極線。這是對極幾何中重要的三個概念。
1.2 極點與像平面關係
在下面的實驗中,會分析極點與像平面在三種不同情況下的結果,所以這裏先對這三種情況做個介紹。
先來看極點的性質——
極點的性質:
- 基線與像平面相交點
- 光心在另一幅圖像中的投影
三種情況——
情況一:極點位於像平面
如上圖,兩個相機相對放置(匯聚視角),匯聚攝像機的對極幾何是比較一般的情形,如b,c圖所示,視圖之間的運動是一個平移加上旋轉。這是因爲拍攝過程中,相機1面向右邊,相機2面向左邊,可知極點位於b的右邊,c的左邊。圖中花瓶上標示的橫線即爲極線。
情況二:基線平行像平面
平行於圖像的平移運動是運動的特殊情況,基線與圖像平面相交於無窮遠,因此對極點是無限遠點,對極線是平行線。
情況三:相機前後方位關係
上圖b,c爲相機前後方位拍攝的圖像,極點在各自像平面上的位置相同,可以看到b,c中的極線呈現放射狀。
二、基礎矩陣
有了對極幾何的相關概念,我們就可以將講基礎矩陣了。在前言中也提到過,基礎矩陣
就是對極幾何的代數表示。下面對它進行介紹。
對基礎矩陣的作用理解:
如果已知基礎矩陣F,以及一個3D點在一個像面上的像素座標p,則可以求得在另一個像面上的像素座標p’。這個是基礎矩陣的作用,可以表徵兩個相機的相對位置及相機內參數。
2.1 本質矩陣E的推導
如上圖,設X在C,C’座標系中的相對座標分別p,p’.
我們可以建立座標軸,方便理解,如上圖,以C爲原點,光軸方向爲z軸,另外兩個方向爲x, y軸可以得到一個座標系,在這個座標系下,可以對X, p(即圖中所標x), p’(即圖中所標x’)得到三維座標,同理,對C’也可以得到一個三維座標,這兩個座標之間的轉換矩陣爲[R T],(說明:R爲旋轉矩陣,T爲相機中心位置的三維平移向量)
即通過旋轉R和平移T可以將C座標系下的點p(x1, y1, z1), 轉換成C’座標系下的p’(x2, y2, z2)。
則有:如果我們將其左叉乘一個T,即 其中 表示對極平面的法線,若再左點乘一個p’得到由於p’與法線是垂直的,所以有我們知道兩向量的叉乘可以轉換爲一向量的反對稱矩陣與另一向量的點乘,於是定義矩陣S爲S表示T的反對稱矩陣。叉積秩爲2。
將上式帶入叉積公式中,得到:我們讓 E=SR ,那麼這個E就是本質矩陣.
本質矩陣的作用:本質矩陣描述了空間中的點在兩個座標系中的座標對應關係。
對本質矩陣E的求解過程作個小結:以上內容中,p, p’分別爲P點的像點在兩個座標系下分別得到的座標(非二維像素座標)。Rp爲極面上一矢量,T爲極面上一矢量,則兩矢量一叉乘爲極面的法向量, 這個法向量與極面上一矢量p’一定是垂直的,所以上式一定成立。(這裏採用轉置是因爲p’會表示爲列向量的形式,此處需要爲行向量)
2.2 基礎矩陣F的推導
得到本質矩陣後,基礎矩陣也就容易推導了
設K和K’ 分別爲兩個相機的內參矩陣,根據約束關係可知:代入(1)式得到:
這樣我們就得到了兩個相機上的像素座標和基礎矩陣F之間的關係了。
基礎矩陣的作用:基礎矩陣F描述了空間中的點在兩 個像平面中的座標對應關係。
2.3 基礎矩陣F的性質
基礎矩陣的性質:
簡單說來,3x3的矩陣,理論上9個自由度,但是需要符合以下兩個約束:
a)如果F爲基礎矩陣,那麼kF也爲基礎矩陣
b)秩爲2
所以減去兩個自由度,F有7個自由度。
對第二條約束進行討論(爲什麼秩爲2?):
我們知道,矩陣的秩有這麼一個性質,矩陣相乘的秩不大於各矩陣的秩,那麼,可以知道F其實是以下這些矩陣相乘的結果其中,S的具體形式在2.1中有表述可以知道,第三列A2可以用第一列A0和第二列A1線性表示所以S秩爲2,那麼F秩爲2也得證了。
2.4 基礎矩陣F的求解
一般採用七點算法或八點算法對F進行求解,得知F後就可以對任意像面1上點找像面2上對應點了。下面介紹8點算法。
2.4.1 八點算法
由於基礎矩陣F定義爲:其中是兩幅圖像的任意一對匹配點。由於每一組點的匹配提供了計算F係數的一個線性方程,當給定至少7個點(3×3的齊次矩陣減去一個尺度,以及一個秩爲2的約束),方程就可以計算出未知的F。我們記點的座標爲,則對應的方程爲
展開後有
把矩陣F寫成列向量的形式,則有:
給定n組點的集合,我們有如下方程:
如果存在確定(非零)解,則係數矩陣A的自由度最多是8。由於F是齊次矩陣,所以如果矩陣A的自由度爲8,則在差一個尺度因子的情況下解是唯一的。可以直接用線性算法解得。
如果由於點座標存在噪聲則矩陣A的自由度可能大於8(也就是等於9,由於A是n×9的矩陣)。這時候就需要求最小二乘解,這裏就可以用SVD來求解,f的解就是係數矩陣A最小奇異值對應的奇異向量,也就是A奇異值分解後 中矩陣V的最後一列矢量,這是在解矢量f在約束||f||下取||Af||最小的解。以上算法是解基本矩陣的基本方法,稱爲8點算法。
由於基本矩陣有一個重要的特點就是奇異性,F矩陣的秩是2。如果基本矩陣是非奇異的,那麼所計算的對極線將不重合。所以在上述算法解得基本矩陣後,會增加一個奇異性約束。最簡便的方法就是修正上述算法中求得的矩陣F。設最終的解爲F′ ,令detF′=0下求得Frobenius範數(二範數)||F−F′|| 最小的F′。這種方法的實現還是使用了SVD分解,若 ,此時的對角矩陣,滿足,則最小化範數||F−F′||,也就是最終的解。
所以8點算法由下面兩個步驟組成:
1.求線性解 由係數矩陣A最小奇異值對應的奇異矢量f 求的F。
2.奇異性約束 是最小化Frobenius範數||F−F’||的F’代替F。
2.4.2 歸一化八點算法
上面8點算法估算基礎矩陣F的優缺點如下:
- 優點: 線性求解,容易實現,運行速度快
- 缺點:對噪聲敏感
8點算法是計算基本矩陣的最簡單的方法,但它存在問題,如:如果矩陣各列的數據尺度差異太大, 最小二乘得到的結果精度一般很低。爲了提高解的穩定性和精度,往往會對輸入點集的座標先進行歸一化處理。對於歸一化八點算法的總結如下:
給定 組對應點{},確定基本矩陣F使得
算法:
1.歸一化:根據變換圖像座標。其中T和T’是有平移和縮放組成的歸一化變換。
2.求解對應匹配的基本矩陣
①求線性解:用由對應點集{}確定的係數矩陣 的最小奇異值的奇異矢量確定
②奇異性約束:用SVD對進行分解,令其最小奇異值爲0,得到,使得
③解除歸一化:令。矩陣F就是數據對應的基本矩陣。
歸一化8點算法將圖像座標範圍限定在 ~[-1,1]x[- 1,1],實驗表明可以得到更可靠的結果。
三、實驗內容
3.1 實驗目的與要求
- 分別用七點、八點、十點(匹配點),計算基礎矩陣
- 實驗圖片包含三種情況,即(1)左右拍攝,極點位於圖像平面上(2)像平面接近平行,極點位於無窮遠(3)圖像拍攝位置位於前後
- 針對上述情況,畫出極點和極線,其中點座標要均勻分佈於各行
3.2 代碼實現
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
def drawlines(img1, img2, lines, pts1, pts2):
''' img1 - image on which we draw the epilines for the points in img2
lines - corresponding epilines '''
r, c = img1.shape
img1 = cv.cvtColor(img1, cv.COLOR_GRAY2BGR)
img2 = cv.cvtColor(img2, cv.COLOR_GRAY2BGR)
for r, pt1, pt2 in zip(lines, pts1, pts2):
color = tuple(np.random.randint(0, 255, 3).tolist())
x0, y0 = map(int, [0, -r[2] / r[1]])
x1, y1 = map(int, [c, -(r[2] + r[0] * c) / r[1]])
img1 = cv.line(img1, (x0, y0), (x1, y1), color, 1)
img1 = cv.circle(img1, tuple(pt1), 5, color, -1)
img2 = cv.circle(img2, tuple(pt2), 5, color, -1)
return img1, img2
img1 = cv.imread('D:/Alike/python_dw/Code_a/admin_code/data/data_five/p58.jpg', 0) # queryimage # left image
img2 = cv.imread('D:/Alike/python_dw/Code_a/admin_code/data/data_five/p59.jpg', 0) # trainimage # right image
sift = cv.xfeatures2d.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
# FLANN parameters
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
good = []
pts1 = []
pts2 = []
# ratio test as per Lowe's paper
for i, (m, n) in enumerate(matches):
if m.distance < 0.8 * n.distance:
good.append(m)
pts2.append(kp2[m.trainIdx].pt)
pts1.append(kp1[m.queryIdx].pt)
pts1 = np.int32(pts1)
pts2 = np.int32(pts2)
F, mask = cv.findFundamentalMat(pts1, pts2, cv.FM_LMEDS,cv.FM_8POINT)
print F
# We select only inlier points
pts1 = pts1[mask.ravel() == 1]
pts2 = pts2[mask.ravel() == 1]
# Find epilines corresponding to points in right image (second image) and
# drawing its lines on left image
lines1 = cv.computeCorrespondEpilines(pts2.reshape(-1, 1, 2), 2, F)
lines1 = lines1.reshape(-1, 3)
img5, img6 = drawlines(img1, img2, lines1, pts1, pts2)
# Find epilines corresponding to points in left image (first image) and
# drawing its lines on right image
lines2 = cv.computeCorrespondEpilines(pts1.reshape(-1, 1, 2), 1, F)
lines2 = lines2.reshape(-1, 3)
img3, img4 = drawlines(img2, img1, lines2, pts2, pts1)
plt.subplot(121), plt.imshow(img5)
plt.subplot(122), plt.imshow(img3)
plt.show()
若要改變匹配點數量(7點、8點、10點),修改代碼:
F, mask = cv.findFundamentalMat(pts1, pts2, cv.FM_LMEDS,cv.FM_8POINT)
3.3 實驗結果
分三種情況討論,每種情況輸出極點極線圖,並分別用7點、8點、10點(匹配點)計算基礎矩陣。
(1)左右拍攝,極點位於圖像平面上
極點極線圖:
基礎矩陣F:
(2)像平面接近平行
極點極線圖:
基礎矩陣F:
(3)圖像拍攝位置位於前後
極點極線圖:
基礎矩陣F:
3.4 實驗分析
-
首先觀察三種不同情況的結果圖:
極點位於圖像平面上的情況下,兩幅圖像中的極線各自有序排列,但延長線能夠匯聚,圖中的亮點表示的是對應點。 -
像平面接近平行的情況下,極線呈現的是幾乎平行的狀態,這裏對其展開解釋:
如上圖所示,當圖像平面互相平行時,由 O1 、O2 構成的基線平行於圖像平面,故極點 e 和 e’ 位於無窮遠處,對極線是平行線。
回到上述實驗,由於拍攝過程中相機是平移的關係,所以包包的像面互相平行,因此得到平行的對極線。 -
圖像拍攝位置位於前後情況下,極線呈現放射狀。在這組圖片的拍攝過程中,相機前後移動,從結果圖中可以看到所有極線的匯聚點爲對面房間的桌子方位附近,極點在各自像平面上的位置相同。
-
觀察圖中的對應點,發現絕大多數對應點落在極線上,但也有部分對應點散落在圖像上。
-
觀察基礎矩陣F,發現當選取的算法匹配點數不同時,得到的結果互不相同,一般情況下我們選取的是8點法求解基礎矩陣,當然還可以選取7點、10點等,經查閱資料,要評估誤差,可以採用3種方式:代數誤差、幾何誤差和重投影誤差。當然因爲拍攝過程中位移與旋轉角度不同,即R、T矩陣不同(或者外界光線等原因),看到不同情況下得到的是互不相同的F矩陣。
四、小結
實驗內容小結:
通過本次實驗瞭解了對極幾何的概念以及基礎矩陣的求導過程,對極幾何解決的是已知兩幅圖像中兩點是對應關係,如何求解兩相機的相對位置和姿態的問題,而基礎矩陣則是它的代數表示。通過三組不同情況的實驗進一步加深對本章內容的理解,發現三組實驗中,相機左右拍攝與前後拍攝得到的圖像中,能看到極線明顯地相交或者有相交趨勢,而在像平面接近於平行的情況下,極線卻是呈現平行的狀態,這時極點在無窮遠處。
實驗過程小結:
- 本次實驗在取材(拍攝圖片)上我花了不少時間,要注意的是圖片如果不壓縮,可能需要很長的運行時間,但壓縮了會導致找到的匹配點數量減少,影響sift特徵匹配和Ransac算法的結果,所以要把握好圖片像素大小。
- 遇到錯誤:pycharm中的array突然報錯,檢查開頭已經導入numpy包,可是無法使用。
解決辦法:根據系統的提示,在開頭處添加from array import array
即可。但是仍然存有疑惑,後續再做檢查更正。