harris角点
- 角点可以是两个边缘的角点;
- 角点是邻域内具有两个主方向的特征点;
- 角点通常被定义为两条边的交点,更严格的说,角点的局部邻域应该具有两个不同区域的不同方向的边界。或者说,角点就是多条轮廓线之间的交点。
- 像素点附近区域像素无论是在梯度方向、还是在梯度幅值上都发生较大的变化。
- 一阶导数(即灰度的梯度)的局部最大所对应的像素点;
- 两条及两条以上边缘的交点;
- 图像中梯度值和梯度方向的变化速率都很高的点;
- 角点处的一阶导数最大,二阶导数为零,指示物体边缘变化不连续的方向。
- 角点在任意一个方向上做微小移动,都会引起该区域的梯度图的方向和幅值发生很大变化。
- 具有旋转不变形,但是不具备尺度不变性。
算法步骤
- 求x,y两个方向梯度,并计算出矩阵M
- 对矩阵M计算特征值、行列式和迹
- 根据特征值的关系并使用阈值确定图像特征
R
=
det
M
−
k
(
trace
M
)
2
R=\operatorname{det} M-k(\operatorname{trace} M)^2
R=detM−k(traceM)2
λ
1
\lambda 1
λ1 :X轴方向的偏导的特征值;
λ
2
:
Y
\lambda 2: Y
λ2:Y 轴方向的偏导的特征值;
- det M : \operatorname{det} M: detM: 矩阵行列式, λ 1 + λ 2 \lambda_1+\lambda_2 λ1+λ2
- traceM:矩阵的迹, λ 1 λ 2 \lambda_1 \lambda_2 λ1λ2
- k k k : Harri系数, 一般取值为 0.04 ∼ 0.06 0.04 \sim 0.06 0.04∼0.06
函数api
CV_EXPORTS_W void cornerHarris( InputArray src, OutputArray dst, int blockSize,
int ksize, double k,
int borderType = BORDER_DEFAULT );
dst:Harri算法的输出矩阵(输出图像),CV_32FC1类型,与src有同样的尺寸
src:输入图像,单通道,8位或浮点型
blockSize:邻域大小
ksize:Sobel算子的孔径大小
k:Harri算法系数
import cv2
import numpy as np
img = cv2.imread("./images/32.jpg")
img2gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img2gray = np.float32(img2gray)
dst = cv2.cornerHarris(img2gray,blockSize=2,ksize=3,k=0.02)
dst = cv2.dilate(dst,cv2.getStructuringElement(cv2.MORPH_RECT,ksize=(8,8)))
img[dst>0.01*dst.max()] = [0,0,255]
cv2.imshow("dst",img)
cv2.waitKey(0)
托马斯算法
- 原理:Harris 角点检测中每个窗口的分数公式是将矩阵 M M M 的行列式与 M M M 的迹相减:
R = λ 1 λ 2 − k ( λ 1 + λ 2 ) 2 R=\lambda_1 \lambda_2-k\left(\lambda_1+\lambda_2\right)^2 R=λ1λ2−k(λ1+λ2)2
- 由于 Harris 角点检测算法的稳定性和 k 值有关,而 k 是个经验值,不好设定最佳值。
Shi-Tomasi 发现,角点的稳定性其实和矩阵 M M M 的较小特征值有关,于是直接用较小的那个特征值作为分数。这样就不用调整k值了。所以 Shi-Tomasi 将分数公式改为如下形式:
R = min ( λ 1 , λ 2 ) R=\min \left(\lambda_1, \lambda_2\right) R=min(λ1,λ2)
cv2.goodFeaturesToTrack
是 OpenCV 中用于检测图像中角点(特征点)的函数,它通常用于光流法跟踪中的初始点检测。这个函数基于 Shi-Tomasi 角点检测算法,在给定的图像中找到一些“好”的特征点。以下是该函数的主要输入参数及其作用:
函数原型
cv2.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance[, corners[, mask[, blockSize[, useHarrisDetector[, k]]]]])
输入参数
-
image (
np.ndarray
):- 描述:输入图像,必须是单通道的灰度图像。
- 作用:在该图像中寻找角点。
-
maxCorners (
int
):- 描述:检测到的角点的最大数量。
- 作用:该参数指定了要返回的角点数量的上限。如果图像中的强角点数量超过了这个值,只会返回最强的前
maxCorners
个角点。如果设置为 0,表示不限制角点数量。
-
qualityLevel (
float
):- 描述:角点质量水平。
- 作用:这是一个相对值,表示角点被接受的最低质量水平。一般取值在 0 到 1 之间。例如,
0.01
表示仅接受最大响应值的 1%。这个参数控制了检测到的角点的最低质量。
-
minDistance (
float
):- 描述:最小欧氏距离。
- 作用:检测到的角点之间的最小距离。如果检测到的角点之间的距离小于此值,则会保留响应更强的角点,删除响应较弱的角点。这可以避免检测到过于接近的角点。
-
corners (
np.ndarray
, 可选):- 描述:输出角点的列表。
- 作用:如果提供了这个参数,函数会将检测到的角点坐标存入这个数组中。
-
mask (
np.ndarray
, 可选):- 描述:操作掩膜。
- 作用:用于指定感兴趣区域。只有掩膜中非零的像素对应的区域才会被检测角点。如果不需要掩膜,可以设置为
None
。
-
blockSize (
int
, 可选):- 描述:邻域大小。
- 作用:角点检测时考虑的邻域大小。通常设置为 3 或 5,即表示使用 3x3 或 5x5 的邻域来计算每个像素点的角点质量。
-
useHarrisDetector (
bool
, 可选):- 描述:是否使用 Harris 角点检测。
- 作用:如果设置为
True
,则使用 Harris 角点检测的方式来测量角点响应。如果设置为False
,则使用 Shi-Tomasi 角点检测方法。默认值为False
。
-
k (
float
, 可选):- 描述:Harris 检测器的自由参数。
- 作用:只有在
useHarrisDetector=True
时,该参数才有效。它是 Harris 角点检测中的自由参数,通常介于 0.04 到 0.06 之间。
返回值
- corners (
np.ndarray
):- 该函数返回检测到的角点的坐标。每个角点的坐标是一个二维数组
[x, y]
。返回的数组形状为(numCorners, 1, 2)
,其中numCorners
是检测到的角点数。
- 该函数返回检测到的角点的坐标。每个角点的坐标是一个二维数组
示例代码
import cv2
import numpy as np
# 读取图像并转换为灰度图
img = cv2.imread('image.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 检测角点
corners = cv2.goodFeaturesToTrack(gray, maxCorners=100, qualityLevel=0.01, minDistance=10)
# 绘制角点
for i in corners:
x, y = i.ravel()
cv2.circle(img, (x, y), 3, 255, -1)
cv2.imshow('Corners', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.goodFeaturesToTrack
是一个非常实用的函数,广泛应用于特征点检测和跟踪任务中。通过调整输入参数,您可以根据具体应用场景找到最合适的角点集合。
import cv2
import numpy as np
img = cv2.imread("./images/32.jpg")
img2gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img2gray = np.float32(img2gray)
# dst = cv2.cornerHarris(img2gray,blockSize=2,ksize=3,k=0.02)
corners = cv2.goodFeaturesToTrack(img2gray,100,0.01,10)
# dst = cv2.dilate(dst,cv2.getStructuringElement(cv2.MORPH_RECT,ksize=(8,8)))
# img[dst>0.01*dst.max()] = [0,0,255]
corners = np.int0(corners)
for i in corners:
x,y = i.ravel()
cv2.circle(img,(x,y),radius=3,color=255,thickness=3)
cv2.imshow("dst",img)
cv2.waitKey(0)
fast 算法
- 点与周围的值比较,阈值确定。
FAST(Features from Accelerated Segment Test)算法简介
FAST(Features from Accelerated Segment Test)是一种快速特征点检测算法,广泛用于实时计算机视觉任务中,如图像配准、SLAM、目标跟踪等。FAST 算法通过检测图像中具有显著变化的像素点(角点)来找到特征。它的主要优势是计算速度快且易于实现,特别适合需要实时处理的应用。
FAST 算法原理
-
圆形邻域检测:FAST 算法围绕一个中心像素以半径为 3 的圆形邻域(共 16 个像素)进行检测。
-
快速测试:根据一个阈值(称为
threshold
),比较中心像素的强度与邻域像素的强度:- 如果某个像素值显著亮于或暗于中心像素,则认为它是一个潜在的特征点。
-
连续像素检测:如果在圆形邻域上存在至少
N
个连续的像素都满足上述条件(亮于或暗于中心像素),则判定该像素为特征点。 -
非极大值抑制(Non-Maximum Suppression):为提高特征点的定位精度,通常会对检测到的特征点进行非极大值抑制,保留最强的特征点。
cv2.FastFeatureDetector_create
输入参数
cv2.FastFeatureDetector_create()
是 OpenCV 中创建 FAST 特征检测器的函数,它允许用户根据需要配置不同的检测参数。以下是该函数的主要输入参数:
-
threshold (
int
):- 描述:特征点检测的阈值。这个值用于决定一个像素点是否被认为是特征点。阈值越高,检测到的特征点越少。
- 作用:通过调整
threshold
,可以控制算法对特征点的敏感度。
-
nonmaxSuppression (
bool
):- 描述:是否启用非极大值抑制。默认情况下,FAST 会检测很多相邻的特征点,非极大值抑制可以去除相邻特征点中响应较弱的点。
- 作用:启用时,可以提高特征点的定位精度,并减少重复特征点。
-
type (
cv2.FastFeatureDetector_TYPE
):- 描述:指定 FAST 算法的类型。目前支持三种类型:
cv2.FAST_FEATURE_DETECTOR_TYPE_5_8
:使用 8 个连续像素来检测特征点。cv2.FAST_FEATURE_DETECTOR_TYPE_7_12
:使用 12 个连续像素来检测特征点。cv2.FAST_FEATURE_DETECTOR_TYPE_9_16
:使用 16 个连续像素来检测特征点。
- 作用:选择不同类型的 FAST 算法可以适应不同的图像细节和速度需求。
- 描述:指定 FAST 算法的类型。目前支持三种类型:
FAST 算法是一种快速且高效的特征点检测方法,适合实时性要求较高的任务。cv2.FastFeatureDetector_create
提供了灵活的配置选项,通过调整参数,可以有效控制检测的特征点数量和精度。
import cv2
src = cv2.imread("33.jpg")
grayImg = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
fast = cv2.FastFeatureDetector_create(threshold=35)
# fast.setNonmaxSuppression(False)
kp = fast.detect(grayImg, None)
img2 = cv2.drawKeypoints(src, kp, None, (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
print('Threshold: ', fast.getThreshold())
print('nonmaxSuppression: ', fast.getNonmaxSuppression())
print('neighborhood: ', fast.getType())
print('Total Keypoints with nonmaxSuppression: ', len(kp))
#
cv2.imshow('fast_true', img2)
#
# fast.setNonmaxSuppression(False)
# kp = fast.detect(grayImg, None)
#
# print('Total Keypoints without nonmaxSuppression: ', len(kp))
#
# img3 = cv2.drawKeypoints(src, kp, None, (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
# cv2.imshow('fast_false', img3)
cv2.waitKey()
- fast_true
- fast_false NMS关闭
import cv2
src = cv2.imread("./images/33.jpg")
grayImg = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
fast = cv2.FastFeatureDetector_create(threshold=35)
# fast.setNonmaxSuppression(False)
kp = fast.detect(grayImg, None)
img2 = cv2.drawKeypoints(src, kp, None, (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
print('Threshold: ', fast.getThreshold())
print('nonmaxSuppression: ', fast.getNonmaxSuppression())
print('neighborhood: ', fast.getType())
print('Total Keypoints with nonmaxSuppression: ', len(kp))
#
cv2.imshow('fast_true', img2)
#
fast.setNonmaxSuppression(False)
kp = fast.detect(grayImg, None)
print('Total Keypoints without nonmaxSuppression: ', len(kp))
img3 = cv2.drawKeypoints(src, kp, None, (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow('fast_false', img3)
cv2.waitKey()
ORB算法
- 常用,略菜sift,但是快
- fast还要快
ORB(Oriented FAST and Rotated BRIEF)算法简介
ORB(Oriented FAST and Rotated BRIEF)是一种用于特征检测和描述的算法,结合了 FAST 角点检测和 BRIEF 描述符,经过改进后适合于图像匹配、物体识别和图像拼接等任务。ORB 是一种开源的替代 SIFT(Scale-Invariant Feature Transform)和 SURF(Speeded-Up Robust Features)的方法,它既快又不受专利限制。
ORB 算法的原理
-
特征检测:
- 使用 FAST(Features from Accelerated Segment Test)算法进行角点检测。
- 为了增加旋转不变性,ORB 使用 Harris 响应函数来筛选和排序特征点。
-
方向分配:
- 计算特征点邻域的方向,通过中心像素的方向分布给每个特征点分配一个方向。
-
特征描述:
- 使用 BRIEF(Binary Robust Independent Elementary Features)描述符来描述特征点。
- 为了增加旋转不变性,ORB 通过对 BRIEF 的特征进行旋转处理,使得描述符具有旋转不变性。
-
特征点匹配:
- ORB 使用汉明距离(Hamming Distance)进行二进制描述符的快速匹配。
cv2.ORB_create
输入参数
cv2.ORB_create()
是 OpenCV 中创建 ORB 特征检测器和描述符提取器的函数。它允许用户根据需要配置不同的检测和描述参数。以下是该函数的主要输入参数:
-
nfeatures (
int
, 默认值500
):- 描述:要检测的特征点的最大数量。
- 作用:通过调整这个值可以控制检测到的特征点数量,较大的值会增加计算时间但能检测更多特征点。
-
scaleFactor (
float
, 默认值1.2
):- 描述:图像金字塔每层之间的尺度因子。
- 作用:这个参数影响了尺度空间的构建,每一层特征点的检测是基于对原始图像进行尺度缩放的结果。默认值
1.2
意味着每一层图像缩小 1.2 倍。
-
nlevels (
int
, 默认值8
):- 描述:金字塔的层数。
- 作用:影响 ORB 在不同尺度下检测特征点的能力。层数越多,算法可以检测到更多不同尺度的特征点。
-
edgeThreshold (
int
, 默认值31
):- 描述:边界阈值。
- 作用:这个参数决定了特征检测过程中图像边缘忽略的像素大小,以避免检测到不完整的角点。
-
firstLevel (
int
, 默认值0
):- 描述:金字塔的第一级。
- 作用:设置金字塔的起始层。通常从第 0 层开始。
-
WTA_K (
int
, 默认值2
):- 描述:每次比较 BRIEF 描述符的点对数量。
- 作用:该参数可以是 2、3 或 4,数值越大意味着描述符的辨识度更高。
-
scoreType (
cv2.ORB_HARRIS_SCORE
orcv2.ORB_FAST_SCORE
, 默认值cv2.ORB_HARRIS_SCORE
):- 描述:特征点排序的方法。
- 作用:
cv2.ORB_HARRIS_SCORE
使用 Harris 响应值进行排序。cv2.ORB_FAST_SCORE
使用 FAST 响应值进行排序。
-
patchSize (
int
, 默认值31
):- 描述:计算方向和 BRIEF 描述符的补丁大小。
- 作用:补丁大小越大,算法的抗噪能力越强。
-
fastThreshold (
int
, 默认值20
):- 描述:FAST 角点检测的阈值。
- 作用:调整这个参数可以改变 ORB 算法对角点的敏感度。
示例代码
ORB 是一种高效、快速的特征检测和描述算法,适用于实时计算机视觉任务。cv2.ORB_create
提供了多种配置选项,通过调整参数,可以根据应用需求检测和描述图像中的特征点。ORB 的特点是计算速度快且不受专利限制,是许多计算机视觉任务的理想选择。
import cv2
import numpy as np
img = cv2.imread("./images/33.jpg")
img2gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
orb = cv2.ORB_create()
kp = orb.detect(img2gray,None)
kp,des = orb.compute(img2gray,kp)
img2 = cv2.drawKeypoints(img,kp,None,color=(0,0,255),flags=0)
cv2.imshow("dst",img2)
cv2.waitKey(0)
sift 算法
- 加了大小匹配,解决了尺度不变形
- 专利算法,慎用
SIFT(Scale-Invariant Feature Transform)算法简介
SIFT(Scale-Invariant Feature Transform)是一种经典的特征检测和描述算法,由 David Lowe 在 1999 年提出。它能够检测图像中的特征点(关键点)并生成具有尺度和旋转不变性的描述符,广泛应用于图像匹配、物体识别、图像拼接、三维重建等计算机视觉任务。
SIFT 算法的原理
-
尺度空间极值检测:
- 通过在不同尺度下对图像进行高斯模糊并构建高斯金字塔(Gaussian Pyramid),在图像尺度空间中检测关键点。
- 使用差分高斯(Difference of Gaussian, DoG)来近似拉普拉斯算子,找到图像在空间和尺度上变化最显著的点(关键点)。
-
关键点精确定位:
- 对检测到的关键点进行亚像素精确定位,去除低对比度的关键点和边缘响应点,以提高关键点的稳定性和鲁棒性。
-
方向分配:
- 根据关键点的局部梯度方向分布,为每个关键点分配一个或多个方向,确保特征的旋转不变性。
-
关键点描述符生成:
- 在每个关键点的方向对齐的局部邻域内,计算多个方向梯度直方图(Histogram of Oriented Gradients, HOG),生成具有 128 维特征向量的描述符。
-
特征点匹配:
- 通过欧氏距离(或其他距离度量)匹配两个图像中的 SIFT 描述符,实现图像之间的特征点匹配。
cv2.SIFT_create()
输入参数
cv2.SIFT_create()
是 OpenCV 中创建 SIFT 特征检测器和描述符提取器的函数,用户可以根据需要调整多个参数来控制特征检测和描述符生成的过程。以下是该函数的主要输入参数及其含义:
-
nfeatures (
int
, 默认值0
):- 描述:要保留的关键点的最大数量。
- 作用:该参数控制算法保留的关键点数量。默认情况下检测所有特征点。
-
nOctaveLayers (
int
, 默认值3
):- 描述:每组(Octave)中的层数(层间的图像数量)。
- 作用:每个组中的层数越多,检测的关键点越多,描述符的计算也会更加详细。通常使用默认值
3
。
-
contrastThreshold (
float
, 默认值0.04
):- 描述:对比度阈值,用于过滤掉低对比度的特征点。
- 作用:这个参数影响检测到的特征点的数量,值越大,特征点越少且更稳定,值越小则可以检测到更多细节特征点,但可能会有更多噪声。
-
edgeThreshold (
float
, 默认值10
):- 描述:边缘阈值,用于过滤掉位于边缘上的特征点。
- 作用:较低的值会导致检测到的特征点数减少,较高的值会检测到更多的特征点。调整该参数可以改善检测到的特征点的质量。
-
sigma (
float
, 默认值1.6
):- 描述:高斯模糊的标准差。
- 作用:用于在高斯金字塔中生成尺度空间时的初始模糊程度。较高的值使得算法在更高尺度上检测特征点,较低的值可以检测到更多细节特征点。
SIFT 是一种经典且非常有效的特征检测和描述算法,具有很强的尺度和旋转不变性,能够在许多复杂的视觉任务中表现出色。cv2.SIFT_create()
函数提供了多种参数来调节特征点检测和描述符生成的过程,通过合理调整这些参数,用户可以在不同的应用场景中获得最佳效果。
import cv2
src = cv2.imread("./images/33.jpg")
grayImg = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
sift = cv2.SIFT_create()
kp = sift.detect(grayImg,None)
img = cv2.drawKeypoints(src,kp,None,color=(0,0,255))
cv2.imshow("img",img)
cv2.waitKey()
SURF算法
-
比sift快
-
现有专利保护,需要重新编译,或者换OpenCV版本
SURF(Speeded-Up Robust Features)算法简介
SURF(Speeded-Up Robust Features)是 SIFT 的加速版本,由 Bay et al. 在 2006 年提出。SURF 算法通过对 SIFT 进行优化,提高了计算速度,同时在特征检测和描述符生成方面保持了较高的精度和稳定性。SURF 在图像识别、对象跟踪、图像配准和三维重建等计算机视觉任务中广泛应用。
SURF 算法的原理
-
积分图像(Integral Image):
- 使用积分图像来快速计算不同尺度下的卷积操作,这是 SURF 提高计算效率的关键步骤。
-
Hessian 矩阵行列式:
- SURF 使用 Hessian 矩阵的行列式来检测图像中的特征点。Hessian 矩阵反映了图像在某点的二阶导数信息,能有效检测出角点和斜率变化显著的区域。
-
方向分配:
- 在特征点的局部邻域内,SURF 计算梯度信息并通过加权直方图分配一个主方向,使得特征具有旋转不变性。
-
特征描述符:
- 在主方向的基础上,SURF 通过对特征点邻域内的梯度信息进行编码,生成 64 维或 128 维的描述符。SURF 的描述符与 SIFT 类似,但通过使用 Haar 小波响应加速了计算过程。
-
快速匹配:
- SURF 描述符可以通过欧氏距离或汉明距离进行快速匹配,适用于实时计算机视觉任务。
cv2.xfeatures2d.SURF_create()
输入参数
cv2.xfeatures2d.SURF_create()
是 OpenCV 中创建 SURF 特征检测器和描述符提取器的函数。以下是该函数的主要输入参数及其含义:
-
hessianThreshold (
float
, 默认值100
):- 描述:Hessian 矩阵行列式的阈值。
- 作用:该阈值控制了检测到的关键点数量,值越高检测到的关键点越少且更稳定,值越低则会检测到更多的特征点。通常在实际应用中需要根据图像内容和需求调整该参数。
-
nOctaves (
int
, 默认值4
):- 描述:金字塔的层数(Octave 的数量)。
- 作用:每个 Octave 是尺度空间的一层,层数越多可以检测到的特征点尺度范围越广,但计算开销也会增加。
-
nOctaveLayers (
int
, 默认值3
):- 描述:每个 Octave 中的层数。
- 作用:控制在每个尺度空间层中的图像采样数,层数越多可以检测到更多细节特征。
-
extended (
bool
, 默认值True
):- 描述:控制描述符的维度。
- 作用:如果为
True
,生成的描述符为 128 维;如果为False
,生成的描述符为 64 维。128 维描述符虽然更加精确,但计算量也更大。
-
upright (
bool
, 默认值False
):- 描述:是否使用不考虑方向的描述符。
- 作用:如果为
True
,SURF 生成的描述符不考虑方向信息,从而不具备旋转不变性。这种设置下,算法速度更快,但只能用于不需要旋转不变性的场景。
SURF 算法通过对 SIFT 的优化,极大地提高了特征检测和描述符生成的速度,同时在许多应用场景中保持了较高的精度。cv2.xfeatures2d.SURF_create()
提供了多个参数来调节特征检测器的行为,用户可以根据具体需求灵活调整这些参数,以在速度和精度之间取得平衡。
import cv2
src = cv2.imread("./images/33.jpg")
grayImg = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
surf= cv2.xfeatures2d.SURF_create()
kp = surf.detect(grayImg,None)
img = cv2.drawKeypoints(src,kp,None,color=(0,0,255))
cv2.imshow("img",img)
cv2.waitKey()
匹配算法
import cv2
img1 = cv2.imread("./images/34.jpg")
grayImage1= cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
img2 = cv2.imread("./images/33.jpg")
grayImage2= cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(grayImage1, None)
kp2, des2 = orb.detectAndCompute(grayImage2, None)
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)
matches = sorted(matches, key=lambda x: x.distance)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)
cv2.imshow("img",img3)
cv2.waitKey(0
![在这里插入图片描述](https://img-blog.csdnimg.cn/img_convert/1f7e2c34445cc8de306e9c4db05ac3d7.png
- KD树匹配
import cv2
img1 = cv2.imread('./images/34.jpg')
grayImg1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
img2 = cv2.imread('./images/33.jpg')
grayImg2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
detector = cv2.xfeatures2d.SIFT_create()
kp1, des1 = detector.detectAndCompute(grayImg1, None)
kp2, des2 = detector.detectAndCompute(grayImg2, None)
matcher = cv2.DescriptorMatcher_create(cv2.DescriptorMatcher_FLANNBASED)
matches = matcher.knnMatch(des1, des2, k=2)
matchesMask = [[0, 0] for i in range(len(matches))]
for i, (m, n) in enumerate(matches):
if m.distance < 0.7 * n.distance:
matchesMask[i] = [1, 0]
draw_params = dict(matchColor=(0, 255, 0), singlePointColor=(255, 0, 0), matchesMask=matchesMask, flags=0)
img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches, None, **draw_params)
cv2.imshow("img", img3)
cv2.waitKey(0)