一前言
今天我们这里下雪了,还挺大的,但是很美,大家可以听听雪落下的声音,雪景总是伴随别离,我和我的前女友就是分别于一场雪,而我们这个OPENCV的系列也即将结束,预计还有两次更新,我们就将开始yolov8代码学习,等我总结出来我会从搭建环境开始到做一个项目。我还报名了蓝桥杯,算促进我的学习了,大家也要努力呀。
二主要内容
一BRIEF(Binary Robust Independent Elementary Features)
理论
我们知道 SIFT 使用 128 维向量作为描述子。由于它使用浮点数,因此需要 512 个字节。类似地,SURF 也至少需要 256 个字节(对于 64 维描述子)。为数千个特征点创建这样的向量需要大量的内存,这在资源有限的情况下是不可行的,特别是嵌入式系统。内存越大,匹配所需的时间越长。
但实际匹配时可能不需要所有的维度。我们可以使用 PCA,LDA 等几种方法对其进行压缩。甚至使用 LSH(Locality Sensitive Hashing,局部敏感哈希)等其他方法也可以将浮点数格式的这些 SIFT 描述子转换为二进制字符串。对这些二进制字符串使用汉明距离进行匹配。这样速度更快,因为计算汉明距离只需要进行异或和位计数,这在具有 SSE 指令的现代 CPU 中非常快。但是我们仍然需要先找到描述符,然后才能应用哈希方法,这并不能解决我们在内存上的初始问题。
这就需要 BRIEF 算法。
它是一个二进制描述符 ,用于高效地描述图像中关键点(如角点)周围的局部外观。它不是特征检测器 (它不寻找关键点,你需要先用像FAST、SIFT、ORB等检测器找到关键点),而是特征描述器。而且 BREIF 算法对于 CenSurE 特征点的效果比 SURF 特征点稍微好
它提供了直接查找二进制字符串而无需找到描述子的快捷方式。它采用平滑后的图像,并以特定的方式(在文中解释)选择一组\(\(n_d\)\)(x,y)位置对。然后在这些位置对上进行一些像素强度比较。例如,让第一个位置对为\(\(p\)\)和\(\(q\)\)。如果\(\(I(p)\lt I(q)\)\),则其结果为 1,否则为 0。对所有\((n_d (\(位置对进行对比以获得\)\)n_d\)\)维二进制字符串。一个长度为 256 的描述符可能看起来像这样:11001011...0110。
OpenCV 中的 BRIEF
下面的代码展示了在 CenSurE 检测器的帮助下计算 BRIEF 描述子的方法。 (CenSurE 探测器在 OpenCV 中被称为 STAR 探测器)
请注意,您需要 opencv contrib 来使用它。(需要在虚拟下安装包pip install opencv-contrib-python 直接pip)
但是还有个问题就是你的opencv的版本是否兼容这个函数,我给出以下方法
1检查opencv版本是否兼容
python
import cv2 as cv
print(f"OpenCV 版本: {cv.__version__}")
print(f"构建信息中包含 contrib: {'contrib' in cv.getBuildInformation()}")
# 检查 xfeatures2d 是否可用
try:
# 尝试导入 xfeatures2d
from cv2 import xfeatures2d
print("xfeatures2d 模块可用")
# 测试具体函数
star = cv.xfeatures2d.StarDetector_create()
brief = cv.xfeatures2d.BriefDescriptorExtractor_create()
print("STAR 和 BRIEF 创建成功")
except ImportError:
print("xfeatures2d 模块不可用")
except AttributeError as e:
print(f"函数不可用: {e}")
2安装 opencv-contrib-python
# 卸载原有 opencv-python
pip uninstall opencv-python opencv-contrib-python -y
# 安装 contrib 版本
pip install opencv-contrib-python
# 或指定版本(确保兼容性)
pip install opencv-contrib-python==4.8.1.78
因为我的版本兼容,所以我就直接演示了
python
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
# 读取灰度图像
img = cv.imread(r'D:\python_code\pic\sumoiao.webp', 0)
# 初始化STAR特征检测器
star = cv.xfeatures2d.StarDetector_create()
# 初始化BRIEF描述符提取器
brief = cv.xfeatures2d.BriefDescriptorExtractor_create()
# 使用STAR检测关键点
kp = star.detect(img, None)
# 使用BRIEF计算描述符
kp, des = brief.compute(img, kp)
# 输出BRIEF描述符大小和描述符矩阵形状
print(brief.descriptorSize())
print(des.shape)
结果如下

函数 brief.getDescriptorSize()给出以字节为单位的\(\(n_d\)\)大小。默认情况下为 32。下一步是匹配,这将在另一章中完成。
二ORB(Oriented FAST and Rotated BRIEF)
理论(太理论,不用看)
作为 OpenCV 爱好者,关于 ORB 最重要的是它来自"OpenCV Labs"。这个算法在 2011 年由 Ethan Rublee,Vincent Rabaud,Kurt Konolige 和 Gary R. Bradski 在他们的论文 ORB: An efficient alternative to SIFT or SURF 中提出的。如标题所述,它是一个很好的 SIFT 和 SURF 的替代,在计算成本,匹配性能,尤其是专利方面。是的,SIFT 和 SURF 已获得专利,您应该支付它们的使用费用。但是 ORB 不是!!!
ORB 基本上是 FAST 特征点检测器和 Brief 描述子的融合,并进行了许多修改以增强性能。首先,它使用 FAST 查找特征点,然后应用 Harris 角点的测量方法来查找其中的前 N 个点。它还使用金字塔来生成多尺度特征。但有一个问题是,FAST 不计算方向。那么旋转不变性呢?作者提出了以下修改。
它计算以角点为中心的图像块的强度加权质心。从该角点到质心的矢量方向给出了方向。为了改善旋转不变性,使用 x 和 y 计算矩,该 x 和 y 应该在半径为$$r \(的圆形区域中,其中\)r $$是图像块的大小。
BRIEF 具有一个重要特性,即每个位特征具有较大的方差,平均值接近 0.5。但是一旦它沿着特征点方向定向,它就会失去这个特性并变得更加分散。高的方差使得特征更易于分辨,因为它对输入有不同的响应。另一个理想的特性是使测试不相关,因为每次测试都会对结果产生影响。为了解决所有这些问题,ORB 在所有可能的二进制测试中运行贪婪搜索,以找到具有高方差和意味着接近 0.5 的那些,以及不相关的。结果称为 rBRIEF 。
对于描述子匹配,使用对传统 LSH 进行改善后的多探针 LSH。该论文称 ORB 比 SURF 和 SIFT 快得多,并且 ORB 描述子比 SURF 效果更好。 ORB 是用于全景拼接等的低功率设备的不错选择。
OpenCV 中的 ORB
像往常一样,我们必须使用函数 cv.ORB()
ORB 参数详解
| 参数 | 默认值 | 说明 |
|---|---|---|
nfeatures |
500 | 要保留的最大特征点数量 |
scaleFactor |
1.2 | 金字塔缩放因子,>1.0 |
nlevels |
8 | 金字塔层数 |
edgeThreshold |
31 | 不检测边界的像素数 |
firstLevel |
0 | 第一层金字塔 |
WTA_K |
2 | 产生描述子的点数(2,3,4) |
scoreType |
ORB_HARRIS_SCORE | 评分类型:HARRIS 或 FAST |
patchSize |
31 | 描述符使用的 patch 大小 |
fastThreshold |
20 | FAST 阈值 |
它有许多可选参数。最有用的是 nFeatures,表示要保留的最大要素数量(默认为 500),scoreType 表示对特征点进行排序使用 Harris 得分或 FAST 得分(默认情况下为 Harris 得分)等。另一个参数 WTA_K 决定生成一个 oriented BRIEF 描述子的所用的像素点数目。默认情况下它是 2,即一次选择两个点。在这种情况下进行匹配,使用 NORM_HAMMING 距离。如果 WTA_K 为 3 或 4,则需要 3 或 4 个点来产生 BRIEF 描述子,匹配距离由 NORM_HAMMING2 定义。
代码如下
python
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
# 读取灰度图像
img = cv.imread(r'D:\python_code\pic\sumoiao.webp', 0)
# 初始化ORB检测器
orb = cv.ORB_create()
# 检测图像中的ORB关键点
kp = orb.detect(img, None)
# 计算关键点描述符
kp, des = orb.compute(img, kp)
# 绘制关键点(仅位置,不包含大小和方向)
img2 = cv.drawKeypoints(img, kp, None, color=(0, 255, 0), flags=0)
# 显示结果图像
plt.imshow(img2)
plt.show()
效果如下

三最后一语
今天就写这么多吧,写的时候一直在下雪,还是挺有意境的,大家记得保暖,注意身体
余拏一小舟,拥毳衣炉火,独往湖心亭看雪。--张岱
崇祯五年的雪就这么下了三百年
感谢观看,共勉!!