简介
本文深入解析2011年ICCV会议提出的BRISK(Binary Robust Invariant Scalable Keypoints)二进制特征提取算法,系统梳理其旋转/尺度不变性的实现逻辑、特征点检测与描述的完整流程,并通过Python结合OpenCV完成图像配准实验,验证其在模糊图像中的出色匹配性能。
一、BRISK算法核心特性
BRISK是一种二进制特征算子,相比SIFT、SURF等浮点型描述符,其64字节的二进制编码大幅提升匹配速度,同时保持三大关键特性:
- 旋转不变性:通过主方向对齐消除旋转影响;
- 尺度不变性:通过多尺度金字塔覆盖不同缩放比例;
- 鲁棒性:对模糊、光照变化有较强适应能力。
在图像配准任务中,速度表现为:SIFT < SURF < BRISK < FREAK < ORB,且对模糊图像的匹配精度优于其他算法。
二、特征点检测:从尺度空间到精确位置
特征点检测是BRISK的核心步骤,目标是找到图像中尺度一致、位置精确的角点。
1. 尺度空间构造
为实现尺度不变性,BRISK通过图像金字塔生成多尺度表示,包含两类层(n=4):
- Octave层(c i c_ici):原图像依次2倍下采样(c 0 c_0c0=原图像,c 1 = c 0 / 2 c_1=c_0/2c1=c0/2,c 2 = c 1 / 2 c_2=c_1/2c2=c1/2…);
- Intra-octave层(d i d_idi):原图像1.5倍下采样为d 0 d_0d0,再依次2倍下采样(d 1 = d 0 / 2 d_1=d_0/2d1=d0/2,d 2 = d 1 / 2 d_2=d_1/2d2=d1/2…)。
各层与原图像的尺度关系(缩放因子t tt):
t c i = 2 i , t d i = 1.5 × 2 i t_{c_i} = 2^i, \quad t_{d_i} = 1.5 \times 2^itci=2i,tdi=1.5×2i
尺寸关系(原图像尺寸W × H W \times HW×H):
Size ( c i ) = W × H 2 i , Size ( d i ) = W × H 1.5 × 2 i \text{Size}(c_i) = \frac{W \times H}{2^i}, \quad \text{Size}(d_i) = \frac{W \times H}{1.5 \times 2^i}Size(ci)=2iW×H,Size(di)=1.5×2iW×H
n=4时,共生成8张多尺度图像(4个c i c_ici+ 4个d i d_idi)。
2. 特征点初步检测
对8张多尺度图像使用FAST9-16算法检测角点(取圆周16个点中连续9个点的亮度与中心差异超过阈值);同时对原图像使用FAST5-8(连续5个点差异超过阈值)检测角点,作为虚拟层d − 1 d_{-1}d−1。最终得到9幅含角点信息的图像。
3. 非极大值抑制
为筛选最显著的特征点,需在位置空间和尺度空间进行非极大值抑制:
- 位置空间:特征点的8邻域点;
- 尺度空间:上下层对应位置的2×9个点;
共26个邻域点。仅当特征点的FAST得分(角点响应值)大于所有邻域点时,保留该点。
4. 亚像素精确插值
初步筛选的特征点位置和尺度较粗糙,需通过二次插值优化:
- 二维位置插值:对极值点所在层及上下层的FAST得分,进行x 、 y x、yx、y方向的二维二次函数插值,得到精确坐标;
- 一维尺度插值:对尺度方向的FAST得分进行一维二次插值,得到精确尺度。
三、特征描述:从采样到二进制编码
特征描述的目标是为每个特征点生成唯一、旋转/尺度不变的二进制码。
1. 高斯滤波的均匀采样
以特征点为中心,构建同心圆采样模式(N=60个采样点):
- 画多个不同半径的同心圆;
- 每个圆上均匀取等间隔点,形成60个采样点(含特征点本身)。
为消除混叠效应,对每个采样点进行高斯滤波:方差σ \sigmaσ与该点到特征点的距离成正比(σ = k × r \sigma = k \times rσ=k×r,k kk为比例系数),滤波后得到平滑的采样点值。
2. 局部梯度与主方向计算
对60个采样点,计算两两组合的梯度信息:
- 梯度幅值:$ g_{ij} = |I_i - I_j|( ((I$为像素值);
- 梯度方向:$ \theta_{ij} = \arctan\left(\frac{y_j - y_i}{x_j - x_i}\right)( (((x_i,y_i)$为采样点坐标)。
将采样点对分为两类:
- 短距离点对:距离 <t × t h t \times tht×th(t tt为特征点尺度,t h thth为阈值);
- 长距离点对:距离 ≥t × t h t \times tht×th。
主方向通过长距离点对的梯度加权平均计算:
θ = arctan ( ∑ g i j sin θ i j ∑ g i j cos θ i j ) \theta = \arctan\left( \frac{\sum g_{ij} \sin\theta_{ij}}{\sum g_{ij} \cos\theta_{ij}} \right)θ=arctan(∑gijcosθij∑gijsinθij)
该方向即为特征点的“主方向”,用于后续旋转对齐。
3. 二进制描述符生成
为实现旋转不变性,将采样区域旋转至主方向(旋转角度θ \thetaθ),然后对短距离点对进行二进制编码:
b k = { 1 , I ( p k a ) > I ( p k b ) 0 , otherwise b_k = \begin{cases} 1, & I(p_k^a) > I(p_k^b) \\ 0, & \text{otherwise} \end{cases}bk={1,0,I(pka)>I(pkb)otherwise
其中p k a p_k^apka、p k b p_k^bpkb为旋转后的短距离点对。共选取512个点对,生成512位二进制码(即BRISK64描述符,64字节)。
四、特征匹配:汉明距离的高效度量
BRISK使用汉明距离衡量两个描述符的相似性,汉明距离越小,特征点越匹配:
Hamming ( a , b ) = ∑ k = 0 511 ( a k ⊕ b k ) \text{Hamming}(a,b) = \sum_{k=0}^{511} (a_k \oplus b_k)Hamming(a,b)=k=0∑511(ak⊕bk)
其中⊕ \oplus⊕为异或运算(相同为0,不同为1)。
五、Python实现
1. 环境准备
安装OpenCV-Python:
pipinstallopencv-python2. 完整代码实现
importcv2importtimedefbrisk_image_matching(img_path1,img_path2):# 1. 加载图像并转灰度img1_color=cv2.imread(img_path1)img2_color=cv2.imread(img_path2)img1_gray=cv2.cvtColor(img1_color,cv2.COLOR_BGR2GRAY)img2_gray=cv2.cvtColor(img2_color,cv2.COLOR_BGR2GRAY)ifimg1_grayisNoneorimg2_grayisNone:print("错误:无法读取图像")return# 2. 初始化BRISK检测器(默认参数)brisk=cv2.BRISK_create()# 3. 检测特征点+计算描述符start_time=time.time()kp1,des1=brisk.detectAndCompute(img1_gray,None)kp2,des2=brisk.detectAndCompute(img2_gray,None)end_time=time.time()# 4. 暴力匹配(汉明距离)matcher=cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck=True)matches=matcher.match(des1,des2)# 5. 绘制结果img_kp1=cv2.drawKeypoints(img1_color,kp1,None,color=(0,255,0),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)img_kp2=cv2.drawKeypoints(img2_color,kp2,None,color=(0,255,0),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)img_matches=cv2.drawMatches(img1_color,kp1,img2_color,kp2,matches,None,flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)# 6. 输出结果print(f"图像1特征点数量:{len(kp1)}")print(f"图像2特征点数量:{len(kp2)}")print(f"匹配点数量:{len(matches)}")print(f"总耗时:{round(end_time-start_time,3)}秒")# 显示窗口cv2.imshow("IM1",img_kp1)cv2.imshow("IM2",img_kp2)cv2.imshow("Result",img_matches)cv2.waitKey(0)cv2.destroyAllWindows()# 测试代码if__name__=="__main__":img1="image/graf1.png"img2="image/graf3.png"brisk_image_matching(img1,img2)总结
BRISK算法通过多尺度金字塔、主方向对齐和二进制编码,实现了高效、鲁棒的特征提取与匹配。本文从原理到Python实现的完整指南,帮助读者快速掌握BRISK的核心逻辑,并应用于图像配准、目标跟踪等任务。
获取更多资料
欢迎下载学习资料,包含:机器学习,深度学习,大模型,CV方向,NLP方向,kaggle大赛,实战项目、自动驾驶等。
公众号搜 “机器视觉与数据” 免费获取。