下面我们学习特征点匹配的使用
import cv2
def cv_show_image(name, img):
cv2.imshow(name, img)
cv2.waitKey(0) # 等待时间,单位是毫秒,0代表任意键终止
cv2.destroyAllWindows()
# 第一步:先读取俩图片
imgA = cv2.imread('images/build.jpeg', 0)
imgB = cv2.imread('images/build2.png', 0)
# 第二步:构造sift,求解出特征点和sift特征向量
sift = cv2.xfeatures2d.SIFT_create()
kpsA, dpA = sift.detectAndCompute(imgA, None)
kpsB, dpB = sift.detectAndCompute(imgB, None)
# 第三步:构造BFMatcher()蛮力匹配(Brute-Force),匹配sift特征向量距离最近对应组分
bf = cv2.BFMatcher()
# ===================================1对1的匹配
# A图像的一关键点和B图像的一关键点,互相都是对方最匹配的点。
# 获得匹配的结果,结果是一对,A图像的第 i 个kp 和 B图像的第 j 个kp一堆,匹配程度是多少,
# 匹配程度(两个128维度特征向量的近似度)用欧式距离表示,距离越小,表示越相近
matches = bf.match(dpA, dpB)
# 按照匹配程度,对匹配的 对儿 排个序,
matches = sorted(matches, key=lambda x: x.distance)
# 使用cv2.drawMacthes进行画图操作,这里我们只画出前30个最相近的。
ret = cv2.drawMatches(imgA, kpsA, imgB, kpsB, matches[:30], None, flags=2)
cv_show_image('1_vs_1_img', ret)
# ===================================K对最佳的匹配
# A图像中的某个关键点,可以在B图像中找到K的最匹配的点都保留下来。
# 假如我们取前2最匹配,
# 第一个图像有个点A,和第二个图像的有个点B最匹配,和C是次级最匹配。
# 匹配程度(两个128维度特征向量的近似度)用欧式距离表示,距离越小,表示越相近,dis(A,B)=m, dis(A,B)=n
# 我们再做个比较,如果 m < 0.75 * n 就可以取m,否则不取m,因为区分度不高,这个很模糊,不好说的。
matches = bf.knnMatch(dpA, dpB, k=2)
# 完了后需要做个过滤
good_pts = []
for res in matches:
m, n = res
if m.distance < 0.75 * n.distance:
good_pts.append([m])
# 第四步:使用cv2.drawMacthes进行画图操作,这里我们只画出前30个最相近的。
ret = cv2.drawMatchesKnn(imgA, kpsA, imgB, kpsB, good_pts, None, flags=2)
cv_show_image('knn_match', ret)
效果如下:
1对1匹配的结果
k对匹配的结果
很明显,K对匹配会有一些匹配错误的点,或者说是异常点,这个将大大折扣匹配效果,这个怎么消除呢?下一次的学习中将介绍方法。