在 Python 中使用 OpenCV 筛选
特征提取是图像处理和机器学习中不可或缺的过程。 它是指通过提取有价值的信息位将原始数据转换为信息。
在图像处理中,我们找到有效的关键点及其描述符。
在 Python 中,我们使用 OpenCV 库来处理和操作图像。 我们可以使用这个库应用不同的技术和预定义的算法。
本教程将演示如何使用 OpenCV 实现 SIFT 算法并将其用于 Python 中的特征匹配。 我们还将学习在 Python 中使用 OpenCV 使用 SIFT 算法来匹配两个图像。
用于特征提取的SIFT算法
SIFT(尺度不变特征变换)是一种复杂而有用的特征提取技术。 它克服了其他算法的旋转变化或比例变化的问题,这意味着如果图像旋转或缩放到不同的大小,提取的信息可能会发生变化。
SIFT 算法通过提取有效的关键点及其描述符来避免这一切。 它是尺度和旋转不变的。
我们已经讨论过特征提取。 现在让我们讨论用于特征提取的 SIFT 算法所涉及的步骤。
总共有五个阶段。
尺度空间极值检测
第一阶段称为尺度空间极值检测。
正如所讨论的,我们需要在每个尺度上都存在的特征。 对于更大的尺度,我们需要更大的窗口。
此阶段涉及使用不同的缩放参数并计算高斯差分,即具有不同缩放参数值的高斯模糊的差异。 它将使用给定的缩放值选择一个坐标,并检查它是否存在具有更高和更低缩放值的坐标。
关键点定位
现在让我们进入第二阶段,即关键点定位。 该阶段将筛选出选定的关键点。
它将使用泰勒级数扩展来获得更精细的关键点并找到它们的强度。 如果强度小于指定的阈值,则拒绝。
方向分配
下一阶段称为方向分配。 正如所讨论的,关键点是旋转不变的,这个阶段确保相同。
它将使用关键点的周围区域来计算梯度及其方向。 创建了 36 个 bin 并绘制在直方图上以表示 360 度,高于 80% 的峰值被视为新关键点并用于确定所选关键点的方向。
关键点描述符
第四阶段旨在通过将与关键点相邻的 16x16 块分成 16 个 4x4 块来创建关键点描述符。 为包含 8 个 bin 的每个块构造方向直方图。
所有这些值都表示为关键点描述符向量。
关键点匹配
最后阶段涉及关键点匹配。 它通过寻找邻居来匹配两个关键点。
这用于消除错误匹配。
现在我们已经详细讨论了 SIFT 算法。 让我们看看如何使用 Python 的 OpenCV 库来实现它。
使用 SIFT 类在 Python 中使用 OpenCV 实现 SIFT
SIFT_create()
构造函数对象可用于创建可从图像中检测关键点的 SIFT 类对象。
我们可以指定不同的参数,尽管每个参数都有一些默认值。 参数是:nfeatures、nOctaveLayers、contrastThreshold、edgeThreshold、sigma 和 descriptorType。
nfeatures 参数可以指定要从结果中选择的最佳特征的数量。 可以使用 nOctaveLayers 参数指定每个八度音阶中的层,其默认值为 3。
contrastThreshold 和 edgeThreshold 值过滤掉弱的和类似边缘的特征。 Gaussian的sigma使用sigma参数指定,对于软镜头点击的图片可以调低。
最后一个参数指定描述符的类型,可以是 CV_32F 或 CV_8U。
让我们看看如何使用这个方法。
import numpy as np
import cv2 as cv
i = cv.imread('obj.png')
g = cv.cvtColor(i,cv.COLOR_BGR2GRAY)
sift_ob = cv.SIFT_create()
kp = sift_ob.detect(g,None)
img = cv.drawKeypoints(g,kp,i)
cv.imshow('Output', img)
cv.waitKey(0)
cv.destroyAllWindows()
输出:
让我们试着理解上面的例子。
我们使用 imread()
函数读取图像。 然后,我们使用可以改变任何图像颜色空间的 cvtColor 方法将该图像转换为灰度。
该算法适用于灰度图像。
我们使用具有默认值的 SIFT_create()
函数创建了一个对象。 我们对创建的对象使用 detect()
函数来识别给定图像中的点; 它返回一个存储结果的元组。
我们使用 drawKeypoints()
函数在图像上绘制关键点以获得更好的视觉表示。 我们在此函数中传递元组和图像。
使用 imshow()
函数显示最终图像。
waitKey()
函数阻止输出窗口自动关闭,等待用户按下某个键。 我们使用 destroyAllWindows()
函数关闭了窗口。
SIFT 较早存在于 OpenCV Contrib 库中,并在 2020 年专利到期时添加到 OpenCV。它在 OpenCV 3.4.2.16 版本中不再可用。
现在让我们讨论如何通过在 Python 中使用 OpenCV 实现 SIFT 算法来匹配两个图像。
通过在 Python 中使用 OpenCV 实现 SIFT 算法来匹配两个图像
如上所述,我们可以使用 SIFT 算法检测各种关键点和描述符。 为此,我们可以使用蛮力匹配器。
蛮力匹配器将一次获取一个关键点及其描述符,并尝试将其与另一幅图像的一组特征进行匹配,返回最接近的匹配。
因此,我们将使用 BFMatcher()
构造函数创建一个 Brute-Force 匹配器对象。 该对象接受两个参数。
第一个参数是 normType 参数,它是使用的距离。 对于基于字符串的,我们应该使用 NORM_HAMMING,但对于我们的案例 (SIFT),我们可以使用 NORM_L1 或 NORM_l2。
第二个参数是 crossCheck,如果设置为 True,将只返回任一集合中的相应匹配项。 创建BFMatcher对象后,我们可以使用 match()
函数传递两组描述符进行匹配。
在此之后,我们可以使用 drawMatches()
函数在两个图像上绘制相应的匹配项。 图像并排放置,匹配的关键点使用一条线连接。
每条线都有一个独特的颜色来标识特征。 让我们看一个这样的例子。
我们将匹配以下两张 Qutub Minar 图像的特征。
Image 1:
Image 2:
代码:
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
i1 = cv2.imread('q3.jpeg')
i2 = cv2.imread('q4.jpeg')
img1 = cv2.cvtColor(i1, cv2.COLOR_BGR2GRAY)
img2 = cv2.cvtColor(i2, cv2.COLOR_BGR2GRAY)
sift = cv2.SIFT_create()
k_1, des_1 = sift.detectAndCompute(img1,None)
k_2, des_2 = sift.detectAndCompute(img2,None)
bf = cv2.BFMatcher(cv2.NORM_L1, crossCheck=True)
matches = bf.match(des_1,des_2)
matches = sorted(matches, key = lambda x:x.distance)
img3 = cv2.drawMatches(img1, k_1, img2, k_2, matches[:50], img2, flags=2)
cv2.imshow('Output', img3)
cv2.waitKey(0)
cv2.destroyAllWindows()
输出:
在上面的例子中,我们使用 SIFT 算法和 Brute-Force 匹配器匹配了两个图像的特征。
首先,我们使用 SIFT 算法提取了两幅图像的特征。 然后我们使用 Brute-Force 匹配器对象匹配这些特征。
使用 drawMatches()
函数在两个图像上绘制结果匹配。
总结
本教程演示了在 Python 中使用 OpenCV 实现用于特征提取的 SIFT 算法。 详细讨论了 SIFT 算法背后的理论,并强调了它相对于其他技术的优势。
详细介绍了该算法的五个阶段。 这些是尺度空间极值检测、关键点定位、方向分配、关键点描述符和关键点匹配。
我们讨论了通过使用 SIFT_create()
对象创建 SIFT 类的对象来实现此技术。 我们突出显示了此类中 detect()
方法的使用,并使用 drawKeypoints()
函数绘制了关键点。
我们还讨论了在 Python 中使用 OpenCV 使用 SIFT 算法匹配两个图像。 为此,首先,我们使用SIFT算法提取特征; 然后,我们创建了一个 Brute-Force 匹配器的对象。
我们将描述符传递给对象的 match()
属性以查找匹配项。 使用 drawMatches()
函数在两个图像上绘制结果以提供视觉表示。
相关文章
OpenCV ArUco 标记
发布时间:2023/06/01 浏览次数:110 分类:Python
-
本篇文章将介绍使用 OpenCV 的 cv2.aruco.detectMarkers() 函数检测 ArUco 标记。使用 OpenCV 检测 ArUco 标记
OpenCV 包配置
发布时间:2023/06/01 浏览次数:159 分类:Python
-
OpenCV 是一个机器学习库,提供与计算机视觉应用程序相关的各种功能。 OpenCV 可以与 C++、Python、Java 和 MATLAB 一起使用。下面我们将列出安装和运行 OpenCV 时的一些常见问题以及如何解决这些问
使用 OpenCV 在图像上使用 Bitwise_AND
发布时间:2023/06/01 浏览次数:199 分类:Python
-
按位运算符通常用于对使用单个位操作的位或二进制数的模式执行按位运算。 OpenCV 使用相同的概念来处理和提取图像中的信息。在本文中,我们将具体了解如何使用 Python OpenCV 库来使用 Bitwi
OpenCV 中的图像遮罩
发布时间:2023/06/01 浏览次数:55 分类:Python
-
如果我们想过滤掉图像的某些部分,然后将这个过滤掉的部分与另一幅图像结合起来,那么这可以使用遮罩来完成。 在 OpenCV 中,按位与运算符用于将两个不同的图像合并为一个,或者它可以将
Mac 中 Python 没有名为 CV2 的模块
发布时间:2023/06/01 浏览次数:83 分类:Python
-
我们将通过示例介绍如何在Python中正确安装和导入OpenCV模块。在 Python 的 Mac 中没有名为 CV2 的模块 首先,我们必须了解什么是 OpenCV 以及为什么在 Python 中使用它。
用 Python 发送带附件的电子邮件
发布时间:2023/06/01 浏览次数:84 分类:Python
-
本篇文章将介绍如何使用Python发送带附件的邮件。 为此,我们不需要外部库来发送邮件。 相反,我们导入一个名为 smtplib 的模块并使用它,因为邮件是通过 SMTP 协议发送的。 让我们看看我们该
在 Python 中验证电子邮件地址
发布时间:2023/06/01 浏览次数:76 分类:Python
-
有一些内置功能(例如正则表达式)和库(例如 dnspython)可以帮助完成这些过程。 本文将解释如何使用这些功能和库在 Python 中验证电子邮件。在 Python 中使用正则表达式验证电子邮件
使用 Python 向多个地址发送电子邮件
发布时间:2023/06/01 浏览次数:125 分类:Python
-
在本文中,我们将演示如何使用 Python 编程语言向使用不同电子邮件地址的不同收件人发送电子邮件。 具体来说,我们将向许多不同的人发送电子邮件。使用 Python 向多个地址发送电子邮件
Python 中的 SendGrid
发布时间:2023/06/01 浏览次数:129 分类:Python
-
SendGrid 是一家 SMTP 服务提供商,提供 Web API 以允许客户处理集成信息。 通过该服务提供的 API 密钥,可以在很短的时间内轻松发送各种电子邮件。