img = cv2.imread('C:/Users/Dell/PycharmProjects/check_KeyPoint/image/right_01.png') img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) sift = cv2.xfeatures2d.SIFT_create() #创建一个sift对象 kp = sift.detect(img_gray, None) #检测关键点,返回的是关键点坐标 img_kp = cv2.drawKeypoints(img_gray, kp, None) #将关键点画到图上 kp, feature = sift.compute(img_gray, kp) #计算相应关键点上的特征值,是一个128维的向量
show(img_kp)
kp, feature = sift.detectAndCompute(img_gray, None) #可以用一条语句替换上面detect和compute两条语句
一对一匹配:
img1 = cv2.imread('C:/Users/Dell/PycharmProjects/check_KeyPoint/image/right_01.png') img2 = cv2.imread('C:/Users/Dell/PycharmProjects/check_KeyPoint/image/left_01.png') img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) sift = cv2.xfeatures2d.SIFT_create() #创建一个sift对象 kp1, feature1 = sift.detectAndCompute(img1_gray, None) #可以用一条语句替换上面detect和compute两条语句 kp2, feature2 = sift.detectAndCompute(img2_gray, None) bf = cv2.BFMatcher(crossCheck = True) #crossCheck表示互相匹配,即图像A中第i个点到B中第j个点的距离最近,则B中第j个点到A中第i个点的距离也是最近 #一对一匹配 match = bf.match(feature1, feature2) match = sorted(match, key = lambda a : a.distance) #按距离从小到大排序 img = cv2.drawMatches(img1, kp1, img2, kp2, match[ : 10], None, flags = 2) #先取前10个 show(img)
#多对匹配 bf = cv2.BFMatcher() match = bf.knnMatch(feature1, feature2, k = 2) #每个关键点之间找出两个匹配 good_match = [] for m1, m2 in match: if m1.distance < m2.distance * 0.75: #如果最大匹配的距离小于次大匹配距离的0.75,则认为是一个好匹配,一般都是0.75 good_match.append(m1) img = cv2.drawMatches(img1, kp1, img2, kp2, good_match, None, flags = 2) show(img)
RANSAC(随机抽样一致算法):
最小二乘相当于拟合时对所有的点负责,
ransac拟合时只对主要密集点负责,对于部分偏离点不负责
使用ransac找出匹配中最好的四对(至少4对),求出图像A到图像B相应部分的变换矩阵
其中H为变换矩阵,有8个未知数,因此需要四对,(每对一个x一个y),列出8个方程
图像拼接:
步骤:
1、分别计算两个图像的关键点和特征值
2、找出好的特征值,并将其对应在两个图像中的坐标存近列表中
3、根据对应坐标计算变换矩阵 使用findHomograph
4、将其中一张图像进行变换(注意长度要为两个图像加起来,宽度其中之一即可)
5、将两张图像拼接在一起(即上一步中变换完的图像的相应部分设置为第二张图像,即第二张图像应该在左边,就将左边的相应位置设置为第二张图像,若在右边,同理)
import numpy as np import cv2 def show(img): cv2.imshow('name', img) cv2.waitKey(0) cv2.destroyAllWindows() if __name__ == '__main__': img1 = cv2.imread('C:/Users/Dell/PycharmProjects/check_KeyPoint/image/right_01.png') img2 = cv2.imread('C:/Users/Dell/PycharmProjects/check_KeyPoint/image/left_01.png') img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) sift = cv2.xfeatures2d.SIFT_create() #创建一个sift对象 kp1, feature1 = sift.detectAndCompute(img1_gray, None) #可以用一条语句替换上面detect和compute两条语句 kp2, feature2 = sift.detectAndCompute(img2_gray, None) kp1 = np.float32([k.pt for k in kp1]) # 需要做计算,所以转化为np.float32格式 kp2 = np.float32([k.pt for k in kp2]) # bf = cv2.BFMatcher(crossCheck = True) #crossCheck表示互相匹配,即图像A中第i个点到B中第j个点的距离最近,则B中第j个点到A中第i个点的距离也是最近 #一对一匹配 # match = bf.match(feature1, feature2) # match = sorted(match, key = lambda a : a.distance) #按距离从小到大排序 # img = cv2.drawMatches(img1, kp1, img2, kp2, match[ : 10], None, flags = 2) #先取前10个 #k对匹配 bf = cv2.BFMatcher() match = bf.knnMatch(feature1, feature2, k = 2) good_match = [] for m1, m2 in match: if m1.distance < m2.distance * 0.75: #如果最大匹配的距离小于次大匹配距离的0.75,则认为是一个好匹配,一般都是0.75 good_match.append((m1.trainIdx, m1.queryIdx)) #将好匹配的在两个图像中的对应坐标取出 if len(good_match) > 4 : points1 = np.float32([kp1[i] for (_, i) in good_match]) #将挑选后的匹配相应的坐标取出,注意顺序 points2 = np.float32([kp2[i] for (i, _) in good_match]) H = cv2.findHomography(points1, points2, cv2.RANSAC, 4.0)[0] #将ransac与求矩阵封装到一起,返回变换矩阵 img_ret = cv2.warpPerspective(img1, H, (img1.shape[1] + img2.shape[1], img1.shape[0])) #图像变换 img_ret[0 : img2.shape[0], 0 : img2.shape[1]] = img2 #图像拼接 show(img_ret) else: print("Error!")