Python OpenCV SIFT特征提取的原理与代码实现_乔卿的博客-CSDN博客如果对图像扩大规模,如缩放,如下图所示,那么原本的角点在变换后的某些窗口中可能就不是角点,因此,HarrisDetectors不具有尺度不变性。例如,在上图中,低σ的高斯核可以为小角点提供高值,而高σ的高斯核则适合于大角点。因此,我们可以在尺度空间中找到局部极大值。...https://qiaoxs.blog.csdn.net/article/details/125849051?spm=1001.2014.3001.5502
获得两张图像的关键点之后,下一步就是找到它们之间的对应关系,找到那些相匹配的点,从而基于这些点,实现图像拼接。在OpenCV中,我们可以用于Feature Matching的方法有两种:Brute-Force Matcher 和 FLANN Matcher。
这一方法即暴力搜索法,它选择第一个集合中一个特征的描述符,计算与第二个集合中的所有其他特征描述符之间的距离,返回最接近的一个。
对于BF Matcher,我们首先使用cv.BFMatcher()创建BFMatcher对象,该方法需要两个可选参数:
创建BFMatcher对象之后,使用BFMatcher.match()方法获得最佳匹配。更进一步地,可以使用BFMatcher.knnMatch()方法返回 k 个最佳匹配,其中 k 由用户指定。
该方法返回的结果是DMatch对象的列表。一个DMatch对象具有如下属性:
该方法被用于绘制关键点的匹配情况。我们看到的许多匹配结果都是使用这一方法绘制的——一左一右两张图像,匹配的关键点之间用线条链接。
函数原型:
cv.drawMatches( img1, keypoints1, img2, keypoints2, matches1to2, outImg[, matchColor[, singlePointColor[, matchesMask[, flags]]]]) -> outImg
cv.drawMatches( img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchesThickness[, matchColor[, singlePointColor[, matchesMask[, flags]]]] ) -> outImg
cv.drawMatchesKnn( img1, keypoints1, img2, keypoints2, matches1to2, outImg[, matchColor[, singlePointColor[, matchesMask[, flags]]]]) -> outImg
参数:
# Brute-Force Matching
def bf_match(img_path1, img_path2):
# 读取两张图像
img1 = cv2.imread(img_path1, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(img_path2, cv2.IMREAD_GRAYSCALE)
# 计算两张图像的SIFT描述符
kp1, des1, _ = sift_algorithm(img_path1)
kp2, des2, _ = sift_algorithm(img_path2)
# 创建BFMatcher实例
bf = cv2.BFMatcher()
# 获得最佳匹配
# matches = bf.match(des1, des2)
matches = bf.knnMatch(des1, des2, k=2)
# 使用比率检测,筛选出好的匹配
good = []
for m, n in matches:
if m.distance < 0.75 * n.distance:
good.append([m])
# 绘制匹配结果
# matches = sorted(matches, key = lambda x:x.distance)
# match_result = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
match_result = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
# 显示绘制结果
plt.imshow(match_result)
plt.show()
return match_result
bf_match(images_list[0], images_list[1])
FLANN,即近似最近邻的快速库(Fast Library for Approximate Nearest Neighbors)。
它包含一系列算法,这些算法针对大型数据集中的快速最近邻搜索(KD树)和高维特征进行了优化。对于大型数据集,它比BFMatcher工作得更快。
对于基于 FLANN 的匹配器,我们使用cv2.FlannBasedMatcher()创建FLANN匹配器对象,该方法需要传递两个字典来指定要使用的算法及其相关参数等。
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
FLANN_INDEX_LSH = 6
index_params= dict(algorithm = FLANN_INDEX_LSH,
table_number = 6,
key_size = 12,
multi_probe_level = 1)
search_params = dict(checks=100)
# FLANN Matching
def flann_match(img_path1, img_path2):
# 读取两张图像
img1 = cv2.imread(img_path1, cv2.IMREAD_GRAYSCALE) # queryImage
img2 = cv2.imread(img_path2, cv2.IMREAD_GRAYSCALE) # trainImage
# 计算两张图像的SIFT描述符
kp1, des1, _ = sift_algorithm(img_path1)
kp2, des2, _ = sift_algorithm(img_path2)
# 设置FLANN所需要的两个字典
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
# 创建FlannBasedMatcher对象
flann = cv2.FlannBasedMatcher(index_params, search_params)
# 获得匹配
matches = flann.knnMatch(des1, des2, k=2)
# 为了只绘制好的匹配,这里使用掩码
matches_mask = [[0,0] for i in range(len(matches))]
# 使用比率检测,筛选出好的匹配
for i, (m, n) in enumerate(matches):
if m.distance < 0.7 * n.distance:
matches_mask[i] = [1, 0]
# 绘制匹配结果,这里使用一个字典传递参数
draw_params = dict(matchColor=(0, 255, 0),
singlePointColor=(255, 0, 0),
matchesMask=matches_mask,
flags=cv2.DrawMatchesFlags_DEFAULT)
match_result = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches, None, **draw_params)
# 显示绘制结果
plt.imshow(match_result)
plt.show()
return match_result
flann_match(images_list[0], images_list[1])
匹配结果