【opencv学习】SIFT算法的基本使用以及特征匹配

下面我们学习特征点匹配的使用

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对匹配会有一些匹配错误的点,或者说是异常点,这个将大大折扣匹配效果,这个怎么消除呢?下一次的学习中将介绍方法。

猜你喜欢

转载自blog.csdn.net/qq_29367075/article/details/123365843