1. 程式人生 > 程式設計 >python實現影象全景拼接

python實現影象全景拼接

影象的全景拼接包括三大部分:特徵點提取與匹配、影象配準、影象融合。

1、基於SIFT的特徵點的提取與匹配

利用Sift提取影象的區域性特徵,在尺度空間尋找極值點,並提取出其位置、尺度、方向資訊。

具體步驟:

1). 生成高斯差分金字塔(DOG金字塔),尺度空間構建

2). 空間極值點檢測(關鍵點的初步查探)

3). 穩定關鍵點的精確定位

4). 穩定關鍵點方向資訊分配

5). 關鍵點描述

6). 特徵點匹配

2、影象配準

影象配準是一種確定待拼接影象間的重疊區域以及重疊位置的技術,它是整個影象拼接的核心。本節採用的是基於特徵點的影象配準方法,即通過匹配點對構建影象序列之間的變換矩陣,從而完成全景影象的拼接。

變換矩陣H求解是影象配準的核心,其求解的演算法流程如下。

1)檢測每幅影象中特徵點。

2)計算特徵點之間的匹配。

3)計算影象間變換矩陣的初始值。

4)迭代精煉H變換矩陣。

5)引導匹配。用估計的H去定義對極線附近的搜尋區域,進一步確定特徵點的對應。

6)重複迭代4)和5)直到對應點的數目穩定為止。

設影象序列之間的變換為投影變換

可用4組最佳匹配計算出H矩陣的8 個自由度引數hi=( i=0,1,...,7),並以此作為初始值。

為了提高影象配準的精度,本節採用RANSAC演算法對影象變換矩陣進行求解與精煉,達到了較好的影象拼接效果。RANSAC演算法的思想簡單而巧妙:首先隨機地選擇兩個點,這兩個點確定了一條直線,並且稱在這條直線的一定範圍內的點為這條直線的支撐。這樣的隨機選擇重複數次,然後,具有最大支撐集的直線被確認為是樣本點集的擬合。在擬合的誤差距離範圍內的點被認為是內點,它們構成一致集,反之則為外點。根據演算法描述,可以很快判斷,如果只有少量外點,那麼隨機選取的包含外點的初始點集確定的直線不會獲得很大的支撐,值得注意的是,過大比例的外點將導致RANSAC演算法失敗。在直線擬合的例子中,由點集確定直線至少需要兩個點;而對於透視變換,這樣的最小集合需要有4個點。

3、影象融合

因為相機和光照強度的差異,會造成一幅影象內部,以及影象之間亮度的不均勻,拼接後的影象會出現明暗交替,這樣給觀察造成極大的不便。 亮度與顏色均衡處理,通常的處理方式是通過相機的光照模型,校正一幅影象內部的光照不均勻性,然後通過相鄰兩幅影象重疊區域之間的關係,建立相鄰兩幅影象之間直方圖對映表,通過對映表對兩幅影象做整體的對映變換,最終達到整體的亮度和顏色的一致性。

具體實現:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

if __name__ == '__main__':
top,bot,left,right = 100,100,500
img1 = cv.imread('1.jpg')
img2 = cv.imread('2.jpg')
srcImg = cv.copyMakeBorder(img1,top,right,cv.BORDER_CONSTANT,value=(0,0))
testImg = cv.copyMakeBorder(img2,0))
img1gray = cv.cvtColor(srcImg,cv.COLOR_BGR2GRAY)
img2gray = cv.cvtColor(testImg,cv.COLOR_BGR2GRAY)
sift = cv.xfeatures2d_SIFT().create()
# find the keypoints and descriptors with SIFT
kp1,des1 = sift.detectAndCompute(img1gray,None)
kp2,des2 = sift.detectAndCompute(img2gray,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)

# Need to draw only good matches,so create a mask
matchesMask = [[0,0] for i in range(len(matches))]

good = []
pts1 = []
pts2 = []
# ratio test as per Lowe's paper
for i,(m,n) in enumerate(matches):
if m.distance < 0.7*n.distance:
good.append(m)
pts2.append(kp2[m.trainIdx].pt)
pts1.append(kp1[m.queryIdx].pt)
matchesMask[i] = [1,0]

draw_params = dict(matchColor=(0,255,0),singlePointColor=(255,matchesMask=matchesMask,flags=0)
img3 = cv.drawMatchesKnn(img1gray,kp1,img2gray,kp2,matches,None,**draw_params)
plt.imshow(img3,),plt.show()

rows,cols = srcImg.shape[:2]
MIN_MATCH_COUNT = 10
if len(good) > MIN_MATCH_COUNT:
src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,2)
M,mask = cv.findHomography(src_pts,dst_pts,cv.RANSAC,5.0)
warpImg = cv.warpPerspective(testImg,np.array(M),(testImg.shape[1],testImg.shape[0]),flags=cv.WARP_INVERSE_MAP)

for col in range(0,cols):
if srcImg[:,col].any() and warpImg[:,col].any():
left = col
break
for col in range(cols-1,-1):
if srcImg[:,col].any():
right = col
break

res = np.zeros([rows,cols,3],np.uint8)
for row in range(0,rows):
for col in range(0,cols):
if not srcImg[row,col].any():
res[row,col] = warpImg[row,col]
elif not warpImg[row,col] = srcImg[row,col]
else:
srcImgLen = float(abs(col - left))
testImgLen = float(abs(col - right))
alpha = srcImgLen / (srcImgLen + testImgLen)
res[row,col] = np.clip(srcImg[row,col] * (1-alpha) + warpImg[row,col] * alpha,255)

# opencv is bgr,matplotlib is rgb
res = cv.cvtColor(res,cv.COLOR_BGR2RGB)
# show the result
plt.figure()
plt.imshow(res)
plt.show()
else:
print("Not enough matches are found - {}/{}".format(len(good),MIN_MATCH_COUNT))
matchesMask = None

實驗結果:

1、室內場景:

python實現影象全景拼接

原圖1

python實現影象全景拼接

原圖2

拼接後:

python實現影象全景拼接

2、室外場景:

場景1:

python實現影象全景拼接

原圖1

python實現影象全景拼接

原圖2

拼接後:

python實現影象全景拼接

場景2:

python實現影象全景拼接

原圖1

python實現影象全景拼接

原圖2

拼接後:

python實現影象全景拼接

場景3:

python實現影象全景拼接

原圖1

python實現影象全景拼接

原圖2

拼接後:

python實現影象全景拼接

總結:

本文分別針對室內和室外兩種情況對兩張影象做全景拼接,發現室內情況下拼接的效果較為好。在室外場景1情況下,兩張影象有近景和遠景結合,兩張影象拼接後近景的影象被放大並有一定程度的傾斜;在場景2中,兩張影象都是遠景,拼接後的效果還不錯但是在拼接後圖像的中上方出現了拼接縫;場景3是在不同明亮程度下影象的拼接可以發現拼接後的影象出現明顯的明暗差距,並且拼接縫明顯兩張影象沒有很好的拼接在一起,出現很多沒有重合的地方。

本實驗最初是用opencv-contrib3.4.5版本,但是由於sift的專利限制無法使用,隨後用opencv-contriv3.4.2程式碼可以執行,不會出現問題。方法:先解除安裝當前版本的opencv並安裝:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-contrib-python==3.4.2.16

本文已被收錄到專題《python圖片處理操作》 ,歡迎大家點選學習更多精彩內容。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。