python-全景拼接圖像

一、全景拼接介紹

在同一位置(即圖像的照相機位置相同)拍攝的兩幅或者多幅圖像是單應性相關的。我們經常使用該約束將很多圖像縫補,來拼成一個大的圖像來創建全景圖像。

1.1 流程:

1.根據給定圖像/集,實現特徵匹配。
2.通過匹配特徵計算圖像之間的變換結構。
3.利用圖像變換結構,實現圖像映射。
4.針對疊加後的圖像,採用APAP之類的算法,對齊特徵點。(圖像配準)
5.通過圖割方法,自動選取拼接縫。
6.根據multi-band blending策略實現融合。

1.2 sift匹配與RANSAC

sift匹配與RANSAC在上一個博客有詳細的介紹過,SIFT算法的描述子穩健性很強,比Harris角點要來得精確,但是它的匹配正確率也並不是百分百的,會受到一些噪聲點的干擾,有時就會因爲不同地方有類似的圖案導致匹配錯誤。那麼RANSAC算法便是用來找到正確模型來擬合帶有噪聲數據的迭代方法。RANSAC通過反覆取樣,也就是從整個觀測數據中隨機抽一些數據估算模型參數之後看和所有數據誤差有多大,然後取誤差最小視爲最好以及分離內羣與離羣數據。基本的思想是,數據中包含正確的點和噪聲點,合理的模型應該能夠在描述正確數據點的同時摒棄噪聲點。
舉個簡單的例子,直線的擬合便是RANSAC的一個標準化體現:

  • 在所有的點中隨機選擇兩個點。
  • 根據這兩個點作一條直線。
  • 設定一個閾值,計算在這條線上的點的數量,記爲inliners。
  • 根據最大的inliners那條線進行後續計算。

同理,RANSAC算法可以應用到其它模塊中,例如用於圖像變換的單應性矩陣的計算。
在拼接的過程中,通過將響速和單應矩陣H相乘,然後對齊次座標進行歸一化來實現像素間的映射。通過查看H中的平移量,我們可以決定應該將該圖像填補到左邊還是右邊。當該圖像填補到左邊時,由於目標圖像中點的座標也變化了,所以在“左邊”情況中,需要在單應矩陣中加入平移。

1.3 圖像配準

圖像配準是對圖像進行變換,使變換後的圖像能夠在很好的拼接在上一張圖片的座標系。
爲了能夠進行圖像對比和更精細的圖像分析,圖像配準是一步非常重要的操作。
圖像配準的方法可以參考這篇博客:https://blog.csdn.net/gaoyu1253401563/article/details/80631601

1.4 最大流最小割

最大流
給定指定的一個有向圖,其中有兩個特殊的點源S(Sources)和匯T(Sinks),每條邊有指定的容量(Capacity),求滿足條件的從S到T的最大流(MaxFlow)。
最小割
割是網絡中定點的一個劃分,它把網絡中的所有頂點劃分成兩個頂點集合S和T,其中源點s∈S,匯點t∈T。記爲CUT(S,T),滿足條件的從S到T的最小割(Min cut)。

在這裏插入圖片描述
可以計算出對於這兩種情況淨流f(S,T)等於19。
一個直觀的解釋是:根據網絡流的定義,只有源點s會產生流量,匯點t會接收流量。因此任意非s和t的點u,其淨流量一定爲0,也即是Σ(f(u,v))=0。而源點s的流量最終都會通過割(S,T)的邊到達匯點t,所以網絡流的流f等於割的靜流f(S,T)。

對於一個網絡流圖G=(V,E),其中有源點s和匯點t,那麼下面三個條件是等價的:

  • 流f是圖G的最大流
  • 殘留網絡Gf不存在增廣路
  • 對於G的某一個割(S,T),此時f = C(S,T)
  • 找到最小割後,沿最小割進行分割,可以得到比較好的效果。
    例如:
    在這裏插入圖片描述

1.5 圖像融合-blending

圖像拼接之後可以發現,在拼接的交界處有明顯的銜接痕跡,存在邊緣效應,因爲光照色澤的原因使得圖片交界處的過渡很糟糕,所以需要特定的處理解決這種不自然。那麼這時候可以採用blending方法。multi-band blending是目前圖像融和方面比較好的方法。
原理:
1.建立兩幅圖像的拉普拉斯金字塔
2.求高斯金字塔(掩模金字塔-爲了拼接左右兩幅圖像)因爲其具有尺度不變性
3. 進行拼接blendLapPyrs() ; 在每一層上將左右laplacian圖像直接拼起來得結果金字塔resultLapPyr
4.重建圖像: 從最高層結果圖
將左右laplacian圖像拼成的resultLapPyr金字塔中每一層,從上到下插值放大並和下一層相加,即得blend圖像結果(reconstructImgFromLapPyramid)

且我們可以將拉普拉斯金字塔理解爲高斯金字塔的逆形式。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

二、實驗與分析

2.1 近景拼接

2.1.1 實驗結果:
在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述
拼接結果:
在這裏插入圖片描述
2.1.2 分析:
上面實驗用的五張圖是比較近距離的場景,由匹配的結果我們可以發現每兩張圖像間的匹配還是比較準確的,但是在拼接的結果圖裏看到拼接的時候發生很大的錯位和明顯的明暗差距。在觀察圖片的時候發現最左邊和最右邊的圖光線是比較亮的,因爲距離也比較近,每張圖相似的部分很多,最終的拼接結果圖中顯示的幾乎都是最左邊和最右邊的圖的拼接,中間比較暗的三張圖片形成明顯的接縫。

2.2 室外遠景拼接

2.2.1實驗結果:
在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述
拼接結果:
在這裏插入圖片描述
2.2.2 分析:
這是站在同一位置拍攝的不同角度的五張圖片,最後一張匹配圖匹配的結果不太好,可以看到杆子的頂部匹配到了另一幅圖中的房頂,拼接的視覺效果也不太好,拼接線太明顯,同一位置左右拍的時候每張圖光線差比較大,遠處的物體也能看到斷層的感覺。

2.3 視差大的圖像拼接

2.3.1 實驗結果:
在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述
拼接結果:
在這裏插入圖片描述
2.3.2 分析:
選用的圖是有遠近視差的場景,近距離的樹枝加上橋後面的樹木的遠景。我們也可以看到兩兩圖之間的匹配是比較良好的,一一對應。選用的這五張圖光照是比較均勻的,每張圖的曝光差不多,拼接結果剛一看右側部分的銜接很好,但是在最左邊的橋下影子部分可以看到,影子也是有錯開的。

2.4 實驗代碼:

# -*- coding: utf-8 -*-
from pylab import *
from numpy import *
from PIL import Image
import numpy as np

np.seterr(divide='ignore', invalid='ignore')

# If you have PCV installed, these imports should work
from PCV.geometry import homography, warp
from PCV.localdescriptors import sift

# set paths to data folder
featname = ['C:/Users/asus/Pictures/window/RANSAC/pinjie3/' + str(i + 1) + '.sift' for i in range(5)]
imname = ['C:/Users/asus/Pictures/window/RANSAC/pinjie3/' + str(i + 1) + '.jpg' for i in range(5)]

# extract features and match
l = {}
d = {}
for i in range(5):
    sift.process_image(imname[i], featname[i])
    l[i], d[i] = sift.read_features_from_file(featname[i])

matches = {}
for i in range(4):
    matches[i] = sift.match(d[i + 1], d[i])

# visualize the matches (Figure 3-11 in the book)
for i in range(4):
    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)


# function to convert the matches to hom. points
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)

    # switch x and y - TODO this should move elsewhere
    fp = vstack([fp[1], fp[0], fp[2]])
    tp = vstack([tp[1], tp[0], tp[2]])
    return fp, tp


# estimate the homographies
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

tp, fp = convert_points(2)  # NB: reverse order
H_32 = homography.H_from_ransac(fp, tp, model)[0]  # im 3 to 2

tp, fp = convert_points(3)  # NB: reverse order
H_43 = homography.H_from_ransac(fp, tp, model)[0]  # im 4 to 3

# warp the images
delta = 160  # 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)

im1 = array(Image.open(imname[3]), "f")
im_32 = warp.panorama(H_32, im1, im_02, delta, delta)

im1 = array(Image.open(imname[4]), "f")
im_42 = warp.panorama(dot(H_32, H_43), im1, im_32, delta, 2 * delta)

figure()
imshow(array(im_42, "uint8"))
axis('off')
savefig("example1.png", dpi=300)
show()

三、實驗總結

(1)拍攝光照明暗變化明顯的話會導致拼接結果在拼接處很明顯的,出現斷層現象。
(2)圖片像素太大的時候,運行五張圖片用的時間很長,電腦還可能會死機,因此可以拍攝照片之後適當的修改一下圖片的像素大小,提高運行效率。

問題:
在進行室內這五張圖的拼接時會報錯:did not meet fit acceptance criteria 。現在還沒找到原因
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章