赞
踩
首先读入图片
- import cv2
- import numpy as np
-
- img1=cv2.imread("./picture1/picture1/1/14x00424.JPG")
- img2=cv2.imread("./picture1/picture1/1/14x00425.JPG")
-
然后识别影像特征点及其特征点描述子
- sift = cv2.SIFT_create(1000)
-
- kp1, des1 = sift.detectAndCompute(img1, None)
- kp2, des2 = sift.detectAndCompute(img2, None)
构建匹配器,执行KNN匹配。
- bf=cv2.BFMatcher()
-
- matches = bf.knnMatch(des1,des2,k=2)
- """
- 这里有个大坑,当你想这里直接画出所有的匹配时,
- 这里面的matches返回的是最近距离和次近距离的两个Dmacther元组。
- 如下图,直接用drawMatches函数时,matches1 to matches2就会是含有两个值的元组,然后出现BUG。
- """
但是在后续粗匹配时,我们又需要最近邻次距离之比做粗匹配筛选错点。如果不需要,建议直接用matches直接做暴力匹配。
但是,为了同时对比未筛选匹配和粗筛之后的匹配,我这里直接在近次邻中提取了最近距离。
- # 画出暴力匹配初步匹配后的所有匹配
- matches1=[]
- for i in matches:
- matches1.append(i[0])
- img_matches=cv2.drawMatches(img1,kp1,img2,kp2,matches1,None,flags=2)
然后根据最近邻次比做粗筛,画出粗筛之后的匹配。
- good_matches=[]
- for m,n in matches:
- if m.distance < 0.7 * n.distance:
- good_matches.append(m)
- img_good_matches=cv2.drawMatches(img1,kp1,img2,kp2,good_matches, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
仔细观察依旧存在很多误匹配的点。
这时,我们采用RANSAC算法进行最后的精匹配。
- MIN_MATCH_COUNT = 10
- if len(good_matches)>MIN_MATCH_COUNT:
- src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
- dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)
- M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 4.0)
- matchesMask = mask.ravel().tolist()
- ransac = []
- for i in range(0,len(matchesMask)):
- if matchesMask[i]==1:
- # print(i)
- ransac.append(good_matches[i]) #单独取出内点
- print(ransac)
- """
- 这里的cv2.findHomography()返回值有两个.
- 第一个是变换所需要的单应矩阵M,
- 第二个返回的是一个掩膜值mask,这个掩模确定了RANSAC算法筛选之后的内点和外点。
- """
可以发现这个掩膜的值为0或者1,掩膜通常是一个与原始图像大小相同的二值或布尔图像,其中,选定的区域被标记为1(或True),而其余区域被标记为0(或False)。也就是值为1所对应的good_matches是筛选之后的内点。
最后输出精匹配的成果图即可。
完整代码如下:
- import cv2
- import numpy as np
-
- img1=cv2.imread("./picture1/picture1/1/14x00424.JPG")
- img2=cv2.imread("./picture1/picture1/1/14x00425.JPG")
-
-
- sift = cv2.SIFT_create(1000)
-
- kp1, des1 = sift.detectAndCompute(img1, None)
- kp2, des2 = sift.detectAndCompute(img2, None)
-
- bf=cv2.BFMatcher()
-
- matches = bf.knnMatch(des1,des2,k=2)
- # 画出暴力匹配初步匹配后的所有匹配
- matches1=[] # 最近距离
- for i in matches:
- matches1.append(i[0])
- img_matches=cv2.drawMatches(img1,kp1,img2,kp2,matches1,None,flags=2)
-
- good_matches=[]
- for m,n in matches:
- if m.distance < 0.7 * n.distance:
- good_matches.append(m)
- img_good_matches=cv2.drawMatches(img1,kp1,img2,kp2,good_matches, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
-
- MIN_MATCH_COUNT = 10
- if len(good_matches)>MIN_MATCH_COUNT:
- src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
- dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)
- M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 4.0)
- matchesMask = mask.ravel().tolist()
- ransac = [] # 筛选出RANSAC之后的内点
- for i in range(0,len(matchesMask)):
- if matchesMask[i]==1:
- # print(i)
- ransac.append(good_matches[i])
- print(ransac)
- # h,w = img1.shape[:2]
- # pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]
- # ).reshape(-1, 1, 2)
- # dst = cv2.perspectiveTransform(pts, M)
- # # img2 = cv2.polylines(img2, [np.int32(dst)], True, 255, 5, cv2.LINE_AA)
- img_ransac=cv2.drawMatches(img1, kp1, img2, kp2, good_matches, None)
-
- "未经过筛选的匹配"
- cv2.namedWindow("matches1",cv2.WINDOW_NORMAL)
- cv2.imshow("matches1",img_matches)
- cv2.imwrite("img_matches.jpg",img_matches)
-
-
- "粗筛之后的匹配"
- cv2.namedWindow("good_matches",cv2.WINDOW_NORMAL)
- cv2.imshow("good_matches",img_good_matches)
- cv2.imwrite("./good_matches.jpg",img_good_matches)
-
- "使用RANSAC算法筛选过后的匹配"
- ransac_result=cv2.drawMatches(img1,kp1,img2,kp2,ransac,None,flags=2)
- cv2.namedWindow("ransac_result",cv2.WINDOW_NORMAL)
- cv2.imshow("ransac_result",ransac_result)
- cv2.imwrite("./ransac_result.jpg",ransac_result)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。