目錄
1.RANSAC簡介
RANSAC(Random Sample Consensus)隨機採樣一致算法是根據一組包含異常數據的樣本數據集,計算出數據的數學模型參數,得到有效樣本數據的算法。
1.1 算法基本思想和流程
RANSAC是通過反覆選擇數據集去估計出模型,一直迭代到估計出認爲比較好的模型。具體的實現步驟可以分爲以下幾步:
- 選擇出可以估計出模型的最小數據集;(對於直線擬合來說就是兩個點,對於計算Homography矩陣就是4個點)
- 使用這個數據集來計算出數據模型;
- 將所有數據帶入這個模型,計算出“內點”的數目;(累加在一定誤差範圍內的適合當前迭代推出模型的數據)
- 比較當前模型和之前推出的最好的模型的“內點“的數量,記錄最大“內點”數的模型參數和“內點”數;
- 重複1-4步,直到迭代結束或者當前模型已經足夠好了(“內點數目大於一定數量”)。
1.2 RANSAC 求解單應矩陣
RANSAC 循環:
- 隨機選擇四對匹配特徵
- 根據DLT計算單應矩陣 H (唯一解)
- 對所有匹配點,計算映射誤差ε= ||p i ’, H p i ||
- 根據誤差閾值,確定inliers(例如3-5像素)
- 針對最大inliers集合,重新計算單應矩陣 H
2.圖像映射與全景拼接
首先是在連續圖像對間使用SIFT特徵尋找匹配對應點對,SIFT是具有較強穩健性的描述子,能夠比其他描述子產生更少的錯誤點,但是該方法仍不是很完美;使用RANSAC算法估計出圖像間的單應性矩陣,判定哪些點對是正確的,哪些點對是錯誤的,即使用一個閾值來決定哪些單應性矩陣是合理的;然後將所有的圖像扭曲到一個公共的圖像平面上。
基於SIFT特徵匹配的RNASAC在上一篇博客也有相應實驗的敘述,可參見博客SIFT理解與應用。
通常,這裏的公共平面爲中心圖像平面。一種方法是創建一個很大的圖像,比如將圖像中全部填充0,使其和中心圖像平行,然後將所有的圖像扭曲到上面。由於我們所有的圖像是由照相機水平旋轉拍攝的,因此我們可以使用一個較簡單的步驟:將中心圖像左邊或者右邊的區域填充爲0,以便爲扭曲的圖像騰出空間。
圖像拼接的幾何原理:全景融合的 3D 幾何解釋,圖像被投影到共同的拼接平面上(同一座標系), 在拼接平面上實現全景融合。在拼接的應用中,其實可以簡化理解爲 2D圖像的變換,疊加過程。
基礎流程
① 針對某個場景拍攝多張/序列圖像
② 計算第二張圖像與第一張圖像之間的變換關係
③ 將第二張圖像疊加到第一張圖像的座標系中
④ 變換後的融合/合成
⑤ 在多圖場景中,重複上述過程
2.1 計算第二張圖像與第一張圖像之間的變換關係
(1)變換類型選擇
將兩幅圖像疊加在一起,選擇需要採用模型,如位移、旋轉、尺度大小、仿射和透視等。
(2)2D 圖像變換原理:
圖像濾波: 改變圖像的像素點取值範圍
圖像變換: 改變圖像的座標取值範圍
(3)2D 圖像變換類型
#DoF | Preserves | Icon | |
平移 | 2 | orientation | |
旋轉+平移 (剛體) |
3 | lengths | |
相似 |
4 | angles | |
仿射
|
6 | parallelism | |
單應性變換
|
8 | straight lines |
(4)參數求解:平移問題、仿射變換和單應性變換等
2.2 將第二張圖像疊加到第一張圖像的座標系中
2D 圖像變換
給定變換模型 x'= h(x) ,以及輸入圖像f(x), 根據f(x)計算變換後的圖像 g(x')= f(h(x))。前向映射:對於 f(x) 中的每個像素 x,根據變換模型計算相應的映射座標x' = h(x),並將x的像素值賦給 g(x')。逆向映射:對於 g(x')中的每個像素 x',根據變換模型計算相應的映射座標 x = h -1 (x'),並將x的像素值賦給g(x')。
2.3. 圖像映射小結
流程:
① 針對兩張/多張圖像提取特徵
② 特徵匹配
③ 根據圖像變換特點,選取合適的變換結構
④ 根據DLT等方法計算變換結構
⑤ 採用正向/逆向映射,利用插值方式實現圖像映射變換
2.4 圖像拼接整體流程
- 根據給定圖像/集, 實現特徵匹配
- 通過匹配特徵計算圖像之間的變換結構
- 利用圖像變換結構, 實現圖像映射
- 針對疊加後的圖像, 採用APAP算法對齊特徵點
- 通過圖割方法, 自動選取拼接縫
- 根據multi-band bleing策略實現融合
(1)針對疊加後的圖像, 採用APAP算法對齊特徵點
對兩張圖片進行SIFT特徵匹配, 然後對SIFT特徵匹配得到的特徵點使用 RANSAC算法進行去除錯誤的特徵點對。篩選後的特徵點基本能夠一一對應。使用DLT算法,將剩下的特徵點對進行透視變換矩陣的估計。因爲得到的透視變換矩陣是基於全局特徵點對進行的,即一個剛性的單應性矩陣完成配準。爲提高配準的精度,Apap將圖像切割成無數多個小方塊,對每個小方塊的變換矩陣逐一估計。非常依賴於特徵點對。若圖像高頻信息較少,特徵點對過少,配准將完全失效,並且對大尺度的圖像進行配準,其效果也不是很好,一切都決定於特徵點對的數量。
(2)通過圖割方法, 自動選取拼接縫
尋找代價最小的分割,典型算法是最小割最大流算法,將圖內帶權值的看作帶有流量值的管道,將最大量水從源點送到匯點。
(3)根據multi-band bleing策略實現融合
融合目的在於拼縫消除, Multi-Band能夠達到比較好的融合效果,但是效率低,採用Laplacian(拉普拉斯)金字塔,通過對相鄰兩層的高斯金字塔進行差分,將原圖分解成不同尺度的子圖,對每一個之圖進行加權平均,得到每一層的融合結果,最後進行金字塔的反向重建,得到最終融合效果過程。
3.實驗分析
3.1 代碼實現
# -*- coding: utf-8 -*-
from pylab import *
from numpy import *
from PIL import Image
from PCV.geometry import homography, warp
from PCV.localdescriptors import sift
featname = ['data/pic1/c' + str(i + 1) + '.sift' for i in range(3)]
imname = ['data/pic1/c' + str(i + 1) + '.jpg' for i in range(3)]
l = {}
d = {}
for i in range(3):
sift.process_image(imname[i], featname[i])
l[i], d[i] = sift.read_features_from_file(featname[i])
matches = {}
for i in range(2):
matches[i] = sift.match(d[i + 1], d[i])
for i in range(2):
im1 = array(Image.open(imname[i]))
im2 = array(Image.open(imname[i + 1]))
figure()
sift.plot_matches(im2, im1, l[i + 1], l[i], matches[i], show_below=True)
def convert_points(j):
ndx = matches[j].nonzero()[0]
fp = homography.make_homog(l[j + 1][ndx, :2].T)
ndx2 = [int(matches[j][i]) for i in ndx]
tp = homography.make_homog(l[j][ndx2, :2].T)
fp = vstack([fp[1], fp[0], fp[2]])
tp = vstack([tp[1], tp[0], tp[2]])
return fp, tp
model = homography.RansacModel()
fp, tp = convert_points(1)
H_12 = homography.H_from_ransac(fp, tp, model)[0] # im 1 to 2
fp, tp = convert_points(0)
H_01 = homography.H_from_ransac(fp, tp, model)[0] # im 0 to 1
delta = 1000 # for padding and translation
im1 = array(Image.open(imname[1]), "uint8")
im2 = array(Image.open(imname[2]), "uint8")
im_12 = warp.panorama(H_12, im1, im2, delta, delta)
im1 = array(Image.open(imname[0]), "f")
im_02 = warp.panorama(dot(H_12, H_01), im1, im_12, delta, delta)
figure()
imshow(array(im_02, "uint8"))
axis('off')
show()
3.2 實驗分析
3.2.1 實驗場景一
針對固定點位拍攝多張圖片,以中間圖片爲中心
小結:
從該全景拼接圖可以看出左邊的拼接效果較好,雖然因圖片曝光度的不同存在一定的邊緣效應,但特徵點能相對應,兩圖的拼接沒有扭曲或者其他的問題;而全景拼接圖的右邊,雖然實現了拼接在一起,但是右邊的圖片被變大扭曲了,邊緣樓房明顯傾斜變形,且越右邊變形的越厲害,右邊的圖片整個都被拉伸扭曲變形。從SIFT特徵匹配的結果來看,兩兩匹配得到的特徵點很多,匹配效果也很好,但是最後的全景拼接圖只有左邊能夠實現較好的點對點拼接。
3.2.2 實驗場景二
針對同一場景(選取視差變化大的場景,也就是有近景目標),更換拍攝位置
小結:
該全景拼接圖相對於實驗(1)得到的全景拼接圖效果要好,左邊拼接依然存在曝光度不同導致的邊緣效應,但是圖片沒有被大幅度扭曲,只是在花盆左後面旁邊的瓷磚拼接有點扭曲,兩張圖片過渡不連續存在的拼接縫隙;此時的全景拼接圖沒有再出現右邊扭曲變形的情況,反而因爲曝光度的相似性,特徵點能一一對應得到了較好的拼接效果。
3.3 實驗總結
- 圖片全景拼接把幾張圖片拼接在一起,先選取一箇中間圖像作爲中心圖像,也就是希望將其他圖像變成的圖像,由於匹配是從最右邊的圖像開始計算,所以需要注意將圖片的順序進行顛倒(即由1,2,3,4,5的存放順序變爲5,4,3,2,1),使得從左邊圖像開始扭曲,將所有圖像扭曲到一個公共的圖像平面上。
- 圖像右邊的黑色區域可以通過減小代碼中的delta相應減小,但不能設置的過小,delta值太小會使得圖片不能完整呈現,即可能存在部分圖片被截取了。
- 兩個實驗場景我選取的都是建築物較多的室外場景,背景比較複雜,但也因爲繁複的建築物背景可以檢測出較多的特徵點,總結兩個實驗都是左邊的匹配效果較佳,即特徵點能夠較好的實現一一對應。
- 曝光度的不同容易導致拼接全景圖存在邊緣效應。
4.錯誤
錯誤提示爲ImportError: No module named delaunay。
解決:
1.先進入到進入到python目錄下的Lib\site-packages\PCV\geometry\warp.py,把黑色方框中的
import matplotlib.delaunay as md
改爲紅色方框的
from scipy.spatial import Delaunay
2.把紅色方框的...triangulate_points(x,y)裏面的代碼替換成
tri = Delaunay(np.c_[x,y]).simplices