传统CV算法——角点特征点提取匹配算法实战

news2024/11/15 15:56:05

harris角点

  • 角点可以是两个边缘的角点;
  • 角点是邻域内具有两个主方向的特征点;
  • 角点通常被定义为两条边的交点,更严格的说,角点的局部邻域应该具有两个不同区域的不同方向的边界。或者说,角点就是多条轮廓线之间的交点。
  • 像素点附近区域像素无论是在梯度方向、还是在梯度幅值上都发生较大的变化。
  • 一阶导数(即灰度的梯度)的局部最大所对应的像素点;
  • 两条及两条以上边缘的交点;
  • 图像中梯度值和梯度方向的变化速率都很高的点;
  • 角点处的一阶导数最大,二阶导数为零,指示物体边缘变化不连续的方向。
  • 角点在任意一个方向上做微小移动,都会引起该区域的梯度图的方向和幅值发生很大变化。
  • 具有旋转不变形,但是不具备尺度不变性。

算法步骤

- 求x,y两个方向梯度,并计算出矩阵M
- 对矩阵M计算特征值、行列式和迹
- 根据特征值的关系并使用阈值确定图像特征

R = det ⁡ M − k ( trace ⁡ M ) 2 R=\operatorname{det} M-k(\operatorname{trace} M)^2 R=detMk(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.040.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λ2k(λ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]]]]])

输入参数

  1. image (np.ndarray):

    • 描述:输入图像,必须是单通道的灰度图像。
    • 作用:在该图像中寻找角点。
  2. maxCorners (int):

    • 描述:检测到的角点的最大数量。
    • 作用:该参数指定了要返回的角点数量的上限。如果图像中的强角点数量超过了这个值,只会返回最强的前 maxCorners 个角点。如果设置为 0,表示不限制角点数量。
  3. qualityLevel (float):

    • 描述:角点质量水平。
    • 作用:这是一个相对值,表示角点被接受的最低质量水平。一般取值在 0 到 1 之间。例如,0.01 表示仅接受最大响应值的 1%。这个参数控制了检测到的角点的最低质量。
  4. minDistance (float):

    • 描述:最小欧氏距离。
    • 作用:检测到的角点之间的最小距离。如果检测到的角点之间的距离小于此值,则会保留响应更强的角点,删除响应较弱的角点。这可以避免检测到过于接近的角点。
  5. corners (np.ndarray, 可选):

    • 描述:输出角点的列表。
    • 作用:如果提供了这个参数,函数会将检测到的角点坐标存入这个数组中。
  6. mask (np.ndarray, 可选):

    • 描述:操作掩膜。
    • 作用:用于指定感兴趣区域。只有掩膜中非零的像素对应的区域才会被检测角点。如果不需要掩膜,可以设置为 None
  7. blockSize (int, 可选):

    • 描述:邻域大小。
    • 作用:角点检测时考虑的邻域大小。通常设置为 3 或 5,即表示使用 3x3 或 5x5 的邻域来计算每个像素点的角点质量。
  8. useHarrisDetector (bool, 可选):

    • 描述:是否使用 Harris 角点检测。
    • 作用:如果设置为 True,则使用 Harris 角点检测的方式来测量角点响应。如果设置为 False,则使用 Shi-Tomasi 角点检测方法。默认值为 False
  9. 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 算法原理
  1. 圆形邻域检测:FAST 算法围绕一个中心像素以半径为 3 的圆形邻域(共 16 个像素)进行检测。

  2. 快速测试:根据一个阈值(称为 threshold),比较中心像素的强度与邻域像素的强度:

    • 如果某个像素值显著亮于或暗于中心像素,则认为它是一个潜在的特征点。
  3. 连续像素检测:如果在圆形邻域上存在至少 N 个连续的像素都满足上述条件(亮于或暗于中心像素),则判定该像素为特征点。

  4. 非极大值抑制(Non-Maximum Suppression):为提高特征点的定位精度,通常会对检测到的特征点进行非极大值抑制,保留最强的特征点。

cv2.FastFeatureDetector_create 输入参数

cv2.FastFeatureDetector_create() 是 OpenCV 中创建 FAST 特征检测器的函数,它允许用户根据需要配置不同的检测参数。以下是该函数的主要输入参数:

  1. threshold (int):

    • 描述:特征点检测的阈值。这个值用于决定一个像素点是否被认为是特征点。阈值越高,检测到的特征点越少。
    • 作用:通过调整 threshold,可以控制算法对特征点的敏感度。
  2. nonmaxSuppression (bool):

    • 描述:是否启用非极大值抑制。默认情况下,FAST 会检测很多相邻的特征点,非极大值抑制可以去除相邻特征点中响应较弱的点。
    • 作用:启用时,可以提高特征点的定位精度,并减少重复特征点。
  3. 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 算法是一种快速且高效的特征点检测方法,适合实时性要求较高的任务。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 算法的原理
  1. 特征检测

    • 使用 FAST(Features from Accelerated Segment Test)算法进行角点检测。
    • 为了增加旋转不变性,ORB 使用 Harris 响应函数来筛选和排序特征点。
  2. 方向分配

    • 计算特征点邻域的方向,通过中心像素的方向分布给每个特征点分配一个方向。
  3. 特征描述

    • 使用 BRIEF(Binary Robust Independent Elementary Features)描述符来描述特征点。
    • 为了增加旋转不变性,ORB 通过对 BRIEF 的特征进行旋转处理,使得描述符具有旋转不变性。
  4. 特征点匹配

    • ORB 使用汉明距离(Hamming Distance)进行二进制描述符的快速匹配。

cv2.ORB_create 输入参数

cv2.ORB_create() 是 OpenCV 中创建 ORB 特征检测器和描述符提取器的函数。它允许用户根据需要配置不同的检测和描述参数。以下是该函数的主要输入参数:

  1. nfeatures (int, 默认值 500):

    • 描述:要检测的特征点的最大数量。
    • 作用:通过调整这个值可以控制检测到的特征点数量,较大的值会增加计算时间但能检测更多特征点。
  2. scaleFactor (float, 默认值 1.2):

    • 描述:图像金字塔每层之间的尺度因子。
    • 作用:这个参数影响了尺度空间的构建,每一层特征点的检测是基于对原始图像进行尺度缩放的结果。默认值 1.2 意味着每一层图像缩小 1.2 倍。
  3. nlevels (int, 默认值 8):

    • 描述:金字塔的层数。
    • 作用:影响 ORB 在不同尺度下检测特征点的能力。层数越多,算法可以检测到更多不同尺度的特征点。
  4. edgeThreshold (int, 默认值 31):

    • 描述:边界阈值。
    • 作用:这个参数决定了特征检测过程中图像边缘忽略的像素大小,以避免检测到不完整的角点。
  5. firstLevel (int, 默认值 0):

    • 描述:金字塔的第一级。
    • 作用:设置金字塔的起始层。通常从第 0 层开始。
  6. WTA_K (int, 默认值 2):

    • 描述:每次比较 BRIEF 描述符的点对数量。
    • 作用:该参数可以是 2、3 或 4,数值越大意味着描述符的辨识度更高。
  7. scoreType (cv2.ORB_HARRIS_SCORE or cv2.ORB_FAST_SCORE, 默认值 cv2.ORB_HARRIS_SCORE):

    • 描述:特征点排序的方法。
    • 作用
      • cv2.ORB_HARRIS_SCORE 使用 Harris 响应值进行排序。
      • cv2.ORB_FAST_SCORE 使用 FAST 响应值进行排序。
  8. patchSize (int, 默认值 31):

    • 描述:计算方向和 BRIEF 描述符的补丁大小。
    • 作用:补丁大小越大,算法的抗噪能力越强。
  9. 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 算法的原理
  1. 尺度空间极值检测

    • 通过在不同尺度下对图像进行高斯模糊并构建高斯金字塔(Gaussian Pyramid),在图像尺度空间中检测关键点。
    • 使用差分高斯(Difference of Gaussian, DoG)来近似拉普拉斯算子,找到图像在空间和尺度上变化最显著的点(关键点)。
  2. 关键点精确定位

    • 对检测到的关键点进行亚像素精确定位,去除低对比度的关键点和边缘响应点,以提高关键点的稳定性和鲁棒性。
  3. 方向分配

    • 根据关键点的局部梯度方向分布,为每个关键点分配一个或多个方向,确保特征的旋转不变性。
  4. 关键点描述符生成

    • 在每个关键点的方向对齐的局部邻域内,计算多个方向梯度直方图(Histogram of Oriented Gradients, HOG),生成具有 128 维特征向量的描述符。
  5. 特征点匹配

    • 通过欧氏距离(或其他距离度量)匹配两个图像中的 SIFT 描述符,实现图像之间的特征点匹配。

cv2.SIFT_create() 输入参数

cv2.SIFT_create() 是 OpenCV 中创建 SIFT 特征检测器和描述符提取器的函数,用户可以根据需要调整多个参数来控制特征检测和描述符生成的过程。以下是该函数的主要输入参数及其含义:

  1. nfeatures (int, 默认值 0):

    • 描述:要保留的关键点的最大数量。
    • 作用:该参数控制算法保留的关键点数量。默认情况下检测所有特征点。
  2. nOctaveLayers (int, 默认值 3):

    • 描述:每组(Octave)中的层数(层间的图像数量)。
    • 作用:每个组中的层数越多,检测的关键点越多,描述符的计算也会更加详细。通常使用默认值 3
  3. contrastThreshold (float, 默认值 0.04):

    • 描述:对比度阈值,用于过滤掉低对比度的特征点。
    • 作用:这个参数影响检测到的特征点的数量,值越大,特征点越少且更稳定,值越小则可以检测到更多细节特征点,但可能会有更多噪声。
  4. edgeThreshold (float, 默认值 10):

    • 描述:边缘阈值,用于过滤掉位于边缘上的特征点。
    • 作用:较低的值会导致检测到的特征点数减少,较高的值会检测到更多的特征点。调整该参数可以改善检测到的特征点的质量。
  5. 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 算法的原理
  1. 积分图像(Integral Image)

    • 使用积分图像来快速计算不同尺度下的卷积操作,这是 SURF 提高计算效率的关键步骤。
  2. Hessian 矩阵行列式

    • SURF 使用 Hessian 矩阵的行列式来检测图像中的特征点。Hessian 矩阵反映了图像在某点的二阶导数信息,能有效检测出角点和斜率变化显著的区域。
  3. 方向分配

    • 在特征点的局部邻域内,SURF 计算梯度信息并通过加权直方图分配一个主方向,使得特征具有旋转不变性。
  4. 特征描述符

    • 在主方向的基础上,SURF 通过对特征点邻域内的梯度信息进行编码,生成 64 维或 128 维的描述符。SURF 的描述符与 SIFT 类似,但通过使用 Haar 小波响应加速了计算过程。
  5. 快速匹配

    • SURF 描述符可以通过欧氏距离或汉明距离进行快速匹配,适用于实时计算机视觉任务。

cv2.xfeatures2d.SURF_create() 输入参数

cv2.xfeatures2d.SURF_create() 是 OpenCV 中创建 SURF 特征检测器和描述符提取器的函数。以下是该函数的主要输入参数及其含义:

  1. hessianThreshold (float, 默认值 100):

    • 描述:Hessian 矩阵行列式的阈值。
    • 作用:该阈值控制了检测到的关键点数量,值越高检测到的关键点越少且更稳定,值越低则会检测到更多的特征点。通常在实际应用中需要根据图像内容和需求调整该参数。
  2. nOctaves (int, 默认值 4):

    • 描述:金字塔的层数(Octave 的数量)。
    • 作用:每个 Octave 是尺度空间的一层,层数越多可以检测到的特征点尺度范围越广,但计算开销也会增加。
  3. nOctaveLayers (int, 默认值 3):

    • 描述:每个 Octave 中的层数。
    • 作用:控制在每个尺度空间层中的图像采样数,层数越多可以检测到更多细节特征。
  4. extended (bool, 默认值 True):

    • 描述:控制描述符的维度。
    • 作用:如果为 True,生成的描述符为 128 维;如果为 False,生成的描述符为 64 维。128 维描述符虽然更加精确,但计算量也更大。
  5. 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)


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2110007.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

“释放CPU多核潜能,Linux线程技术助你一臂之力,创新无限!“#Linux系统编程之线程

"释放CPU多核潜能&#xff0c;Linux线程技术助你一臂之力&#xff0c;创新无限&#xff01;"#Linux系统编程之线程 前言预备知识一、 线程概述&#xff08;与进程的区别及线程的优势&#xff09;1.1 进程与线程的联系图1.2 进程与线程1.3 使用线程的理由 二、 线程创…

【在Linux世界中追寻伟大的One Piece】数据链路层

目录 1 -> 数据链路层 2 -> 对比理解“数据链路层”和“网络层” 3 -> 以太网 3.1 -> 以太网的帧格式 4 -> 认识MAC地址 4.1 -> 对比理解MAC地址和IP地址 5 -> 认识MTU 5.1 -> MTU对IP协议的影响 5.2 -> MTU对UDP协议的影响 5.3 -> MT…

如何用涡街流量计计量检测焦炉煤气?

涡街流量计在焦炉煤气计量检测之中仍广泛使用&#xff0c;但也存在一些问题。让我们谈谈这些问题的原因和解决办法。 现场计量检测系统发生故障的原因可归纳为两大原因&#xff0c;一是由流量计或其关联设备引起的。第二种是非流量仪表原因&#xff0c;即流量仪表正常&#xff…

递归求解斐波那契数列的时间复杂度——几种简洁证明

李春葆《算法设计与分析》绿皮--题库版---61页特征方程法&#xff1a;

【原创】java+springboot+mysql企业产品销售管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

动态面板模型

专题名称 第1讲(3 小时) 动态面板模型 面板 VAR 模型 授课内容 一阶差分GMM 估计量(FD-GMM) 序列相关检验、过度识别检验(Sargan 检验) 模型设定常见问题(弱工具变量问题) 面板 VAR 模型简介 允许外生变量的PVAR模型 冲击反应函数(IRF)、方差分解(FEVD) 应用实例(介绍2篇论文) …

无论是速卖通、敦煌网、国际站,自养号测评就是提高曝光的利器!

速卖通&#xff08;AliExpress&#xff09;这是阿里巴巴集团旗下的一个跨境电商平台&#xff0c;主要面向全球零售市场。速卖通店铺根据运营策略不同,可以分为精铺模式、精品模式和垂直模式三种。除了后两种模式需要自有货源外,大部分店铺采用的是“无货源电商”模式。这意味着…

Java栈和队列模拟实现及其方法使用

1. 栈(Stack) 1.1 概念 栈 &#xff1a;一种特殊的线性表&#xff0c;其 只允许在固定的一端进行插入和删除元素操作 。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO &#xff08; Last In First Out &#xff09;的原则…

BBR 与 AIMD 共存公平性探究

一个古已有之的结论&#xff1a; deep buffer 场景&#xff0c;bbr 相对 reno/cubic 等 aimd 有优势&#xff0c;侵占性强&#xff1b;shallow buffer 场景&#xff0c;aimd 有优势&#xff0c;bbr 带宽被挤占。 本文用实例分析 why 并给出 how。 先看 deep buffer 场景 bbr…

Rust的数据类型

【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust到底值不值得学&#xff0c;之一 -CSDN博客 Rust到底值不值得学&#xff0c;之二-CSDN博客 3.5 数据类型的定义和分类 在Rust…

使用html+css+layui实现动态表格组件

1、概述 需求,表格第一列指标可配置通过后端api传进来,表格显示数据以及鼠标触摸后气泡弹出层提示信息都是从后端传过来,实现动态表格的组件!!实现效果如下: 接口标准数据格式如下: {"data": {"date": ["8.20","8.21","…

Cmd终端

组策略停止更新 windows用户的分类 system&#xff08;系统用户&#xff09; administrator&#xff08;管理员用户&#xff09; 普通用户 访客用户 网络管理类命令练习 ping&#xff1a;用于测试网络连接是否正常。通过发送ICMP&#xff08;Internet Control Message Protoco…

力扣 | 递归 | 区间上的动态规划 | 486. 预测赢家

文章目录 一、递归二、区间动态规划 LeetCode&#xff1a;486. 预测赢家 一、递归 注意到本题数据范围为 1 < n < 20 1<n<20 1<n<20&#xff0c;因此可以使用递归枚举选择方式&#xff0c;时间复杂度为 2 20 1024 ∗ 1024 1048576 1.05 1 0 6 2^{20…

Linux--目录与文件操作函数

一、目录和&#xff08;硬&#xff09;链接 可在 shell 中利用 ln 命令为一个业已存在的文件创建新的硬链接 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 2. 同一文件的所有名字&#xff08;链接&#xff09;地位平等—没有一个名字&#xff08;比如…

计应8-01-作业1-静态网页

IP C:\Users\WL>ipconfig // win 查看 ip Windows IP 配置以太网适配器 以太网: //连接特定的 DNS 后缀 . . . . . . . :本地链接 IPv6 地址. . . . . . . . : fe80::6c95:9da6:140c:c59e%13IPv4 地址 . . . . . . . . . . . . : 192.168.51.243//子网掩码 . . . .…

mysql阿拉伯数字转换中文数字函数

函数如下 1.中间一部分代码可以提取出来作为公共方法&#xff0c;我这里并没有提取&#xff0c;因为我是在代码中动态添加的 2.样式目前只做了&#xff1a;123转为一百二十三这类的 drop function if EXISTS zz_convert_number_chinese; create FUNCTION zz_convert_number_…

ELK系列之四---如何通过Filebeat和Logstash优化K8S集群的日志收集和展示

前 言 上一篇文章《日志不再乱: 如何使用Logstash进行高效日志收集与存储》介绍了使用ELK收集通用应用的日志&#xff0c;在目前大多应用都已运行在K8S集群上的环境&#xff0c;需要考虑怎么收集K8S上的日志&#xff0c;本篇就介绍一下如何使用现有的ELK平台收集K8S集群上POD的…

新型供应链攻击手法 — “Revival Hijack”

JFrog 的网络安全研究人员发现了一种名为“Revival Hijack”的新型 PyPI 攻击技术&#xff0c;该技术利用包删除策略绕过安全检查。据统计&#xff0c;超过 22,000 个程序包处于风险之中&#xff0c;可能会影响数十万名用户。 JFrog 的网络安全研究人员发现了一种用于攻击 Pyth…

易灵思时钟输出问题记录

在添加 GPIO时&#xff0c;设置Mode为clkout,并在output Clock中输入时钟名。 这里需要 注意的是&#xff0c; 1. 时钟名不能从core直接输出&#xff0c;而只能使用interface中使用的时钟&#xff0c;如PLL输出的时钟或者GCLK输入的时钟。 2. 易灵思输出时钟不能做其他用途&a…

2024中国产业园区运营商50强榜单揭晓:行业洗牌加速,数智化是关键!

近日&#xff0c;备受瞩目的“2024年度中国产业园区运营商50强”榜单正式揭晓&#xff0c;不仅照亮了行业内的领军之星&#xff0c;更为我们揭示了产业园区运营管理平台在推动经济转型升级中的关键力量与未来趋势的璀璨图景。 从以上产业园区运营商 50 强的角度来看&#xff0…