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速度更快,不过效果较差