python opencv進行影象拼接
本文例項為大家分享了python opencv進行影象拼接的具體程式碼,供大家參考,具體內容如下
思路和方法
思路
1、提取要拼接的兩張圖片的特徵點、特徵描述符;
2、將兩張圖片中對應的位置點找到,匹配起來;
3、如果找到了足夠多的匹配點,就能將兩幅圖拼接起來,拼接前,可能需要將第二幅圖透視旋轉一下,利用找到的關鍵點,將第二幅圖透視旋轉到一個與第一幅圖相同的可以拼接的角度;
4、進行拼接;
5、進行拼接後的一些處理,讓效果看上去更好。
實現方法
1、提取圖片的特徵點、描述符,可以使用opencv建立一個SIFT物件,SIFT物件使用DoG方法檢測關鍵點,並對每個關鍵點周圍的區域計算特徵向量。在實現時,可以使用比SIFT快的SURF方法,使用Hessian演算法檢測關鍵點。因為只是進行全景圖拼接,在使用SURF時,還可以調節它的引數,減少一些關鍵點,只獲取64維而不是128維的向量等,加快速度。
3、單應性匹配完之後可以獲得透視變換H矩陣,用這個的逆矩陣來對第二幅圖片進行透視變換,將其轉到和第一張圖一樣的視角,為下一步拼接做準備。
4、透視變換完的圖片,其大小就是最後全景圖的大小,它的右邊是透視變換以後的圖片,左邊是黑色沒有資訊。拼接時可以比較簡單地處理,通過numpy陣列選擇直接把第一張圖加到它的左邊,覆蓋掉重疊部分,得到拼接圖片,這樣做非常快,但是最後效果不是很好,中間有一條分割痕跡非常明顯。使用opencv指南中影象金字塔的程式碼對拼接好的圖片進行處理,整個圖片平滑了,中間的縫還是特別突兀。
python_opencv中主要使用的函式
0、基於python 3.7和對應的python-opencv
1、cv2.xfeatures2d.SURF_create ([hessianThreshold[,nOctaves[,nOctaveLayers[,extended[,upright]]]]])
2、cv2.SURF.detectAndCompute(image,mask[,descriptors[,useProvidedKeypoints]])
該函式用於計算圖片的關鍵點和描述符,需要對兩幅圖都進行計算。
3、flann=cv2.FlannBasedMatcher(indexParams,searchParams)
match=flann.knnMatch(descrip1,descrip2,k=2)
flann快速匹配器有兩個引數,一個是indexParams,一個是searchParams,都用手冊上建議的值就可以。在建立了匹配器得到匹配陣列match以後,就可以參考Lowe給出的引數,對匹配進行過濾,過濾掉不好的匹配。其中返回值match包括了兩張圖的描述符距離distance 、訓練圖(第二張)的描述符索引trainIdx 、查詢的圖(第一張)的描述符索引queryIdx 這幾個屬性。
4、M,mask=cv2.findHomography(srcPoints,dstPoints[,method[,ransacReprojThreshold[,mask]]])
這個函式實現單應性匹配,返回的M是一個矩陣,即對關鍵點srcPoints做M變換能變到dstPoints的位置。
5、warpImg=cv2.warpPerspective(src,np.linalg.inv(M),dsize[,dst[,flags[,borderMode[,borderValue]]]])
用這個函式進行透視變換,變換視角。src是要變換的圖片,np.linalg.inv(M)是④中M的逆矩陣,得到方向一致的圖片。
6、a=b.copy() 實現深度複製,Python中預設是按引用複製,a=b是a指向b的記憶體。
7、draw_params = dict(matchColor = (0,255,0),singlePointColor = (255,matchesMask = matchMask,flags = 2),img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
使用drawMatches可以畫出匹配的好的關鍵點,matchMask是比較好的匹配點,之間用綠色線連線起來。
核心程式碼
import cv2 import numpy as np from matplotlib import pyplot as plt import time MIN = 10 starttime=time.time() img1 = cv2.imread('1.jpg') #query img2 = cv2.imread('2.jpg') #train #img1gray=cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY) #img2gray=cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY) surf=cv2.xfeatures2d.SURF_create(10000,nOctaves=4,extended=False,upright=True) #surf=cv2.xfeatures2d.SIFT_create()#可以改為SIFT kp1,descrip1=surf.detectAndCompute(img1,None) kp2,descrip2=surf.detectAndCompute(img2,None) FLANN_INDEX_KDTREE = 0 indexParams = dict(algorithm = FLANN_INDEX_KDTREE,trees = 5) searchParams = dict(checks=50) flann=cv2.FlannBasedMatcher(indexParams,searchParams) match=flann.knnMatch(descrip1,k=2) good=[] for i,(m,n) in enumerate(match): if(m.distance<0.75*n.distance): good.append(m) if len(good)>MIN: src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2) ano_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,2) M,mask=cv2.findHomography(src_pts,ano_pts,cv2.RANSAC,5.0) warpImg = cv2.warpPerspective(img2,(img1.shape[1]+img2.shape[1],img2.shape[0])) direct=warpImg.copy() direct[0:img1.shape[0],0:img1.shape[1]] =img1 simple=time.time() #cv2.namedWindow("Result",cv2.WINDOW_NORMAL) #cv2.imshow("Result",warpImg) rows,cols=img1.shape[:2] for col in range(0,cols): if img1[:,col].any() and warpImg[:,col].any():#開始重疊的最左端 left = col break for col in range(cols-1,-1): if img1[:,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 img1[row,col].any():#如果沒有原圖,用旋轉的填充 res[row,col] = warpImg[row,col] elif not warpImg[row,col].any(): res[row,col] = img1[row,col] else: srcImgLen = float(abs(col - left)) testImgLen = float(abs(col - right)) alpha = srcImgLen / (srcImgLen + testImgLen) res[row,col] = np.clip(img1[row,col] * (1-alpha) + warpImg[row,col] * alpha,255) warpImg[0:img1.shape[0],0:img1.shape[1]]=res final=time.time() img3=cv2.cvtColor(direct,cv2.COLOR_BGR2RGB) plt.imshow(img3,),plt.show() img4=cv2.cvtColor(warpImg,cv2.COLOR_BGR2RGB) plt.imshow(img4,plt.show() print("simple stich cost %f"%(simple-starttime)) print("\ntotal cost %f"%(final-starttime)) cv2.imwrite("simplepanorma.png",direct) cv2.imwrite("bestpanorma.png",warpImg) else: print("not enough matches!")
執行結果
原圖1.jpg
原圖2.jpg
特徵點匹配
直接拼接和平滑對比
效果
本文已被收錄到專題《python圖片處理操作》 ,歡迎大家點選學習更多精彩內容。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。