1.SIFT特征點和特征描述提取(注意opencv版本)
高斯金字塔:O組L層不同尺度的圖像(每一組中各層尺寸相同,高斯函數的參數不同,不同組尺寸遞減2倍)
特征點定位:極值點
特征點描述:根據不同bin下的方向給定一個主方向,對每個關鍵點,采用4*4*8共128維向量的描述子進項關鍵點表征,綜合效果最佳:
pip uninstall opencv-python pip install opencv-contrib-python==3.4.2.16
1.特征點檢測
def sift_kp(image): gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) sift = cv2.xfeatures2d_SIFT.create() kp,des = sift.detectAndCompute(gray_image,None)
kp_image = cv2.drawKeypoints(gray_image,kp,None) return kp_image,kp,des
2.SIFT特征點匹配
SIFT算法得到了圖像中的特征點以及相應的特征描述,一般的可以使用K近鄰(KNN)算法。K近鄰算法求取在空間中距離最近的K個數據點,並將這些數據點歸為一類。在進行特征點匹配時,一般使用KNN算法找到最近鄰的兩個數據點,如果最接近和次接近的比值大於一個既定的值,那么我們保留這個最接近的值,認為它和其匹配的點為good match
def get_good_match(des1,des2): bf = cv2.BFMatcher() matches = bf.knnMatch(des1, des2, k=2) good = [] for m, n in matches: if m.distance < 0.75 * n.distance: good.append(m) return good
3.單應性矩陣Homography Matrix
通過上面的步驟,我們找到了若干兩張圖中的匹配點,如何將其中一張圖通過旋轉、變換等方式將其與另一張圖對齊呢?這就用到了單應性矩陣了。Homography這個詞由Homo和graphy,Homo意為同一,graphy意為圖像,也就是同一個東西產生的圖像。
單應性矩陣有八個參數,如果要解這八個參數的話,需要八個方程,由於每一個對應的像素點可以產生2個方程(x一個,y一個),那么總共只需要四個像素點就能解出這個單應性矩陣。
RANSAC算法選擇其中最優的四個點
隨機抽樣一致算法(Random sample consensus:RANSAC)
H, status = cv2.findHomography(ptsA,ptsB,cv2.RANSAC,ransacReprojThreshold) #其中H為求得的單應性矩陣矩陣 #status則返回一個列表來表征匹配成功的特征點。 #ptsA,ptsB為關鍵點 #cv2.RANSAC, ransacReprojThreshold這兩個參數與RANSAC有關
4.圖像匹配
其中:
- 第一個參數為需要投影的圖像(
img2
) - 第二個參數為單應性矩陣(
H
) - 第三個參數為所得圖像的矩陣大小((img1.shape[1],img1.shape[0]) )
- 最后的參數cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP,為插值時使用的插值方法INTER_LINEAR,cv2.WARP_INVERSE_MAP則將M設置為dst--->src的方向變換。
def siftImageAlignment(img1,img2): _,kp1,des1 = sift_kp(img1) _,kp2,des2 = sift_kp(img2) goodMatch = get_good_match(des1,des2) if len(goodMatch) > 4: ptsA= np.float32([kp1[m.queryIdx].pt for m in goodMatch]).reshape(-1, 1, 2) ptsB = np.float32([kp2[m.trainIdx].pt for m in goodMatch]).reshape(-1, 1, 2) ransacReprojThreshold = 4 H, status =cv2.findHomography(ptsA,ptsB,cv2.RANSAC,ransacReprojThreshold); imgOut = cv2.warpPerspective(img2, H, (img1.shape[1],img1.shape[0]),flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP) return imgOut,H,status
5.綜合應用:
import numpy as np import cv2 import Utility img1 = cv2.imread('1.jpg') img2 = cv2.imread('2.jpg') result,_,_ = siftImageAlignment(img1,img2) allImg = np.concatenate((img1,img2,result),axis=1) cv2.namedWindow('Result',cv2.WINDOW_NORMAL) cv2.imshow('Result',allImg) cv2.waitKey(0)
6.SIFT速度太慢,利用surf檢測
def surf_kp(image): '''SIFT(surf)特征點檢測(速度比sift快)''' height, width = image.shape[:2] size = (int(width * 0.2), int(height * 0.2)) shrink = cv2.resize(image, size, interpolation=cv2.INTER_AREA) gray_image = cv2.cvtColor(shrink,cv2.COLOR_BGR2GRAY) surf = cv2.xfeatures2d_SURF.create() kp, des = surf.detectAndCompute(gray_image, None) return kp,des
為了再一次提升速度將圖片進行了縮放,再進行匹配的時候要對4對坐標點進行相應的放大即可。
ORB速度更快,不過效果較差