4.特征匹配
测试图片自取
book.jpg book1.jpg zuo.jpg you.jpg
4.1 Brute-Force蛮力匹配
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
img1=cv2.imread('book.jpg')
img2=cv2.imread('book1.jpg')
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv_show('img1',img1)
cv_show('img2',img2)
sift=cv2.xfeatures2d.SIFT_create()
kp1,des1=sift.detectAndCompute(img1,None)
kp2,des2=sift.detectAndCompute(img2,None)
bf=cv2.BFMatcher(crossCheck=True)
matches=bf.match(des1,des2)
matches=sorted(matches,key=lambda x:x.distance)
img3=cv2.drawMatches(img1,kp1,img2,kp2,matches[:10],None,flags=2)
cv_show('img3',img3)
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])
img3=cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2)
cv_show('img3',img3)
如果需要更快速完成操作,可以尝试使用cv2.FlannBasedMatcher
4.2 RANSAC算法
随机抽样一致算法(Random sample consensus,RANSAC)
选择初始样本进行拟合,给定一个容忍,不断进行迭代。
每一次拟合后,容差范围内都有对应的数据点数,找出数据点个数最多的情况,就是最终的拟合结果
单应性矩阵
4.2.1 图像拼接
实现过程
1、用SIFT提取图像中的特征点,并对每个关键点周围的区域计算特征向量。 2、在分别提取好了两张图片的关键点和特征向量以后,可以利用它们进行两张图片的匹配。在拼接图片中,可以使用Knn进行匹配,但是使用FLANN快速匹配库更快,图片拼接,需要用到FLANN的单应性匹配。 3、单应性匹配完之后可以获得透视变换H矩阵,用这个的逆矩阵来对第二幅图片进行透视变换,将其转到和第一张图一样的视角,为下一步拼接做准备。 4、透视变化完后就可以直接拼接图片了,将图片通过numpy直接加到透视变化完成的图像的左边,覆盖掉重合的部分,得到拼接图片,但是这样拼接得图片中间会有一条很明显的缝隙,可以通过加权平均法,界线的两侧各取一定的比例来融合缝隙,速度快,但不自然。或者羽化法,或者拉普拉斯金字塔融合,效果最好。在这里用的是加权平均法,可以把第一张图叠在左边,但是对第一张图和它的重叠区做一些加权处理,重叠部分,离左边图近的,左边图的权重就高一些,离右边近的,右边旋转图的权重就高一些,然后两者相加,使得过渡是平滑地,这样看上去效果好一些,速度就比较慢。
import cv2
import numpy as np
import sys
from PIL import Image
def show(name,img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
ima = cv2.imread("you.jpg")
imb = cv2.imread("zuo.jpg")
A = ima.copy()
B = imb.copy()
imageA = cv2.resize(A,(0,0),fx=0.2,fy=0.2)
imageB = cv2.resize(B,(0,0),fx=0.2,fy=0.2)
def detectAndDescribe(image):
sift = cv2.xfeatures2d.SIFT_create()
(kps, features) = sift.detectAndCompute(image, None)
kps = np.float32([kp.pt for kp in kps])
return (kps, features)
kpsA, featuresA = detectAndDescribe(imageA)
kpsB, featuresB = detectAndDescribe(imageB)
bf = cv2.BFMatcher()
matches = bf.knnMatch(featuresA, featuresB, 2)
good = []
for m in matches:
if len(m) == 2 and m[0].distance < m[1].distance * 0.75:
good.append((m[0].trainIdx, m[0].queryIdx))
if len(good) > 4:
ptsA = np.float32([kpsA[i] for (_, i) in good])
ptsB = np.float32([kpsB[i] for (i, _) in good])
H, status = cv2.findHomography(ptsA, ptsB, cv2.RANSAC,4.0)
M = (matches, H, status)
if M is None:
print("无匹配结果")
sys.exit()
(matches, H, status) = M
result = cv2.warpPerspective(imageA, H, (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))
result[0:imageB.shape[0], 0:imageB.shape[1]] = imageB
show('res',result)
print(result.shape)
|