
ORB(Oriented FAST and Rotated BRIEF)是一种快速关键点定位与特征描述子提取算法。它结合了FAST角点检测器和旋转不变的BRIEF描述符。FAST用于快速检测兴趣点,而BRIEF则提供了一种高效的方式来描述这些点的局部特征。为了实现旋转不变性,ORB在生成BRIEF描述子时考虑了关键点的方向。
SIFT(Scale-Invariant Feature Transform)特征描述子是一种特征提取方法,能够在不同尺度下检测和描述图像中的关键点的提取,并生成描述子。主要有以下四个步骤:
1. 尺度空间构建:通过构建高斯金字塔来寻找在不同尺度
下的稳定关键点。
2. 关键点定位:精确定位关键点的位置和尺度,排除低对
比度的点和边缘响应强的点。
3. 方向指派:计算每个关键点的主方向,使特征具有旋转不变性。
4. 描述子生成:在关键点周围区域生成16x16的窗口,分成4x4的小方块,
计算每个小方块的方向直方图,形成一个128维的特征向量。SIFT能够提取出具有尺度不变性和旋转不变性的特征描述子。
OpenCV特征匹配算法支持
01
暴力匹配(Brute-Force Matcher):
暴力匹配是一种简单的最近邻搜索算法,它通过计算两个特征描述子之间的欧氏距离或汉明距离来找到最佳匹配。在OpenCV中, ORB特征与SIFT特征的暴力方式是不同的、原因是以为ORB特征数据是基于字节的,SIFT跟SURF特征是基于浮点数的。代码演示如下:
ORB + 暴力匹配+汉明距离
import cv2
# 加载图像和创建ORB检测器
img1 = cv2.imread('image1.jpg', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('image2.jpg', cv2.IMREAD_GRAYSCALE)
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
# 创建暴力匹配器
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)
matches = sorted(matches, key=lambda x: x.distance)
# 绘制前10个匹配结果
img_matches = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv2.imshow('Matches', img_matches)
cv2.waitKey()SIFT + 暴力匹配 + L2
import cv2
# 加载图像和创建SIFT检测器
img1 = cv2.imread('image1.jpg', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('image2.jpg', cv2.IMREAD_GRAYSCALE)
sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
# 创建暴力匹配器
bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)
matches = bf.match(des1, des2)
matches = sorted(matches, key=lambda x: x.distance)
# 绘制前10个匹配结果
img_matches = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv2.imshow('Matches', img_matches)
cv2.waitKey()02
FLANN匹配:
FLANN匹配器是一种高效的近似最近邻搜索算法,适用于大型数据集和高维特征。它通过建立索引和使用优化的搜索策略来提高匹配速度。在OpenCV中,ORB特征与SIFT特征的FLANN匹配也是不一样的,通常ORB是基于LSH、SIFT基于KNN或者KDTree。代码演示如下:
ORB + FLANN
import cv2
# 加载图像和创建ORB检测器
img1 = cv2.imread('image1.jpg', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('image2.jpg', cv2.IMREAD_GRAYSCALE)
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
# 创建FLANN匹配器 - LSH
index_params = dict(algorithm=6, table_number =5, key_size=12)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.match(des1, des2)
matches = sorted(matches, key=lambda x: x.distance)
# 绘制前10个匹配结果
img_matches = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv2.imshow('Matches', img_matches)
cv2.waitKey()SIFT + FLANN
import cv2
# 加载图像和创建SIFT检测器
img1 = cv2.imread('image1.jpg', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('image2.jpg', cv2.IMREAD_GRAYSCALE)
sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
# 创建FLANN匹配器- KDTree
index_params = dict(algorithm=1, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.match(des1, des2)
matches = sorted(matches, key=lambda x: x.distance)
# 绘制前10个匹配结果
img_matches = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv2.imshow('Matches', img_matches)
cv2.waitKey()
总结
ORB特征的暴力匹配支持汉明距离、FLANN匹配支持LSH;SIFT特征的暴力匹配支持L1与L2、FLANN匹配支持KNN、KDTree等。