【14】DAISY特征描述符详解:从SIFT到高效稠密特征提取的进化
本文聚焦DAISY——一款为「稠密图像特征提取」定制的高效局部描述子,解析其基于SIFT的设计内核,对比两者在分块策略、计算效率与旋转鲁棒性上的差异;梳理「梯度方向直方图统计→高斯卷积加权→多方向投影」的核心步骤,并结合研究结论说明其特征汇聚策略的最优性,为理解稠密特征提取的工程实现提供清晰视角。尺度不变性:DAISY没有像SIFT那样构建尺度金字塔,因此对尺度变化的鲁棒性较弱;内存需求:稠密特征
本文简介
本文聚焦DAISY——一款为「稠密图像特征提取」定制的高效局部描述子,解析其基于SIFT的设计内核,对比两者在分块策略、计算效率与旋转鲁棒性上的差异;梳理「梯度方向直方图统计→高斯卷积加权→多方向投影」的核心步骤,并结合研究结论说明其特征汇聚策略的最优性,为理解稠密特征提取的工程实现提供清晰视角。
DAISY 局部图像描述符基于类似于 SIFT 描述符的梯度方向直方图。它的制定方式允许快速密集提取,这对于例如词袋图像表示很有用。如下图,为了说明目的,以较大的比例提取了有限数量的 DAISY 描述符。
一、从SIFT的局限到DAISY的诞生
在计算机视觉任务(如立体匹配、三维重建)中,稠密特征提取(为每一个像素点生成特征向量)能提供更完整的图像结构信息,但传统SIFT算法却难以高效应对:SIFT通过「分块加权梯度直方图」描述特征——对每个特征点,将周围区域划分为固定网格,统计每个网格内的梯度方向分布。但当提取稠密特征时,每移动一个像素都要重新计算网格内的直方图,导致计算量呈线性爆炸;此外,SIFT的直方图对旋转敏感,旋转后直方图的bin分布会完全改变,进一步增加了适配成本。
为解决这两个痛点,DAISY应运而生:它继承了SIFT「梯度直方图」的核心思想,但用高斯卷积替代了「固定网格分块」,彻底重构了特征汇聚的方式。
二、DAISY的核心设计:高斯卷积赋能高效稠密提取
DAISY的本质是「用高斯核对梯度方向直方图进行连续加权」,而非SIFT的「离散网格分块」。这种改进带来两个关键优势:旋转不变性(高斯核的各向同性)和计算高效性(高斯核的可分离性)。
1. 第一步:统计梯度方向直方图
与SIFT一致,DAISY首先计算图像中每个像素的梯度方向(θ)和梯度幅值(m):
- 梯度方向:θ(x,y)=arctan(Iy(x,y)Ix(x,y))\theta(x,y) = \arctan\left(\frac{I_y(x,y)}{I_x(x,y)}\right)θ(x,y)=arctan(Ix(x,y)Iy(x,y)),其中IxI_xIx、IyI_yIy是像素(x,y)(x,y)(x,y)在x、y方向的灰度梯度(可通过Sobel算子计算)。
- 梯度幅值:m(x,y)=Ix2(x,y)+Iy2(x,y)m(x,y) = \sqrt{I_x^2(x,y) + I_y^2(x,y)}m(x,y)=Ix2(x,y)+Iy2(x,y),反映梯度的强度。
随后,将梯度方向量化为8个等宽的bin(每45°一个,覆盖0°~360°),得到每个像素的初始梯度方向直方图H0(x,y)H_0(x,y)H0(x,y):H0(x,y)[k]=∑(u,v)∈Ωm(u,v)⋅δ(⌊θ(u,v)45°⌋=k) H_0(x,y)[k] = \sum_{(u,v)\in\Omega} m(u,v) \cdot \delta\left(\lfloor \frac{\theta(u,v)}{45°} \rfloor = k\right) H0(x,y)[k]=(u,v)∈Ω∑m(u,v)⋅δ(⌊45°θ(u,v)⌋=k)其中Ω\OmegaΩ是像素(x,y)(x,y)(x,y)的局部邻域,δ(⋅)\delta(\cdot)δ(⋅)是指示函数(条件满足时为1,否则为0),k=0,1,...,7k=0,1,...,7k=0,1,...,7对应8个方向bin。
2. 第二步:高斯卷积计算权重层
DAISY的关键改进在于——用不同尺度的高斯核对H0H_0H0进行卷积,生成多层权重化的直方图。
高斯核的选择:各向同性与可分离性
DAISY使用二维高斯核G(σ,x,y)G(\sigma, x, y)G(σ,x,y),其公式为:G(σ,x,y)=12πσ2e−x2+y22σ2 G(\sigma, x, y) = \frac{1}{2\pi\sigma^2} e^{-\frac{x^2 + y^2}{2\sigma^2}} G(σ,x,y)=2πσ21e−2σ2x2+y2
- 各向同性:高斯核在所有方向上的权重分布一致,因此卷积后的直方图对旋转不敏感(旋转后权重分布不变)。
- 可分离性:二维高斯核可分解为两个一维高斯核的乘积:G(σ,x,y)=G(σ,x)⋅G(σ,y)G(\sigma, x, y) = G(\sigma, x) \cdot G(\sigma, y)G(σ,x,y)=G(σ,x)⋅G(σ,y),其中G(σ,x)=12πσe−x22σ2G(\sigma, x) = \frac{1}{\sqrt{2\pi}\sigma} e^{-\frac{x^2}{2\sigma^2}}G(σ,x)=2πσ1e−2σ2x2。这种分解将二维卷积的计算量从O(N2)O(N^2)O(N2)降低到O(N)O(N)O(N)(先沿x方向卷积,再沿y方向卷积),为稠密提取奠定了效率基础。
多层权重的设计
DAISY通常围绕中心点设计3层同心圆(对应3个不同的σ\sigmaσ值,如σ1=1\sigma_1=1σ1=1、σ2=2\sigma_2=2σ2=2、σ3=3\sigma_3=3σ3=3),每层用对应尺度的高斯核对H0H_0H0卷积,得到3个加权后的直方图层H1,H2,H3H_1, H_2, H_3H1,H2,H3:Hi(x,y)=H0∗G(σi,x,y)(i=1,2,3) H_i(x,y) = H_0 \ast G(\sigma_i, x, y) \quad (i=1,2,3) Hi(x,y)=H0∗G(σi,x,y)(i=1,2,3)其中∗\ast∗表示卷积操作。
【在此处插入DAISY特征采样结构示意图:围绕中心点的3层同心圆,每层均匀分布8个采样点(对应8个方向bin)】
3. 第三步:投影到8个方向,生成最终特征
最后,将3层加权直方图H1,H2,H3H_1, H_2, H_3H1,H2,H3与初始直方图H0H_0H0拼接,并投影到8个方向,形成每个像素的DAISY特征向量:DAISY(x,y)=[H0(x,y)[0],...,H0(x,y)[7],H1(x,y)[0],...,H3(x,y)[7]] \text{DAISY}(x,y) = \left[ H_0(x,y)[0], ..., H_0(x,y)[7], H_1(x,y)[0], ..., H_3(x,y)[7] \right] DAISY(x,y)=[H0(x,y)[0],...,H0(x,y)[7],H1(x,y)[0],...,H3(x,y)[7]]
每个DAISY特征的维度为4×8=324\times8=324×8=32维(3层+初始层,每层8个bin),远小于SIFT的128维,但保留了足够的判别性。
三、DAISY的优势:为什么它是最优的?
DAISY的特征汇聚策略并非拍脑袋设计——研究者Matthen Brown、Gang Hua和Simon Winder通过机器学习实验(对比笛卡尔分块、极坐标分块、高斯卷积三种策略),证明DAISY的「高斯卷积汇聚」在特征匹配精度和计算效率上均优于其他方案:
- 精度上:高斯卷积的连续加权能更好地保留局部结构信息,匹配错误率比离散分块低15%~20%;
- 效率上:可分离高斯卷积的计算速度是离散分块的3~5倍,尤其适合稠密特征提取。
import cv2
import numpy as np
from matplotlib import pyplot as plt
plt.rcParams['font.family'] = 'SimHei' # 选择一个支持中文的字体
def demo_daisy_feature_matching():
# 读取两张图片
img1 = cv2.imread('images/im1.png')
img2 = cv2.imread('images/im2.png')
# 转换为灰度图
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 方法1: 使用SIFT检测关键点,DAISY计算描述符
try:
# 创建关键点检测器 (SIFT)
detector = cv2.SIFT_create()
# 检测关键点
kp1 = detector.detect(gray1, None)
kp2 = detector.detect(gray2, None)
# 创建DAISY描述符提取器
daisy = cv2.xfeatures2d.DAISY_create()
# 使用DAISY计算描述符
kp1, des1 = daisy.compute(gray1, kp1)
kp2, des2 = daisy.compute(gray2, kp2)
method = "SIFT关键点 + DAISY描述符"
except Exception as e:
print(f"DAISY不可用: {e}")
print("使用SIFT作为替代...")
# 方法2: 完全使用SIFT
sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(gray1, None)
kp2, des2 = sift.detectAndCompute(gray2, None)
method = "SIFT"
print(f"使用方法: {method}")
print(f"图片1检测到 {len(kp1)} 个关键点")
print(f"图片2检测到 {len(kp2)} 个关键点")
# 检查描述符是否有效
if des1 is None or des2 is None or len(des1) == 0 or len(des2) == 0:
print("错误:无法计算特征描述符")
return
# 使用FLANN匹配器进行特征匹配
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
# 应用Lowe's比率测试来筛选好的匹配点
good_matches = []
for match_pair in matches:
if len(match_pair) == 2:
m, n = match_pair
if m.distance < 0.7 * n.distance:
good_matches.append(m)
print(f"找到 {len(good_matches)} 个好的匹配点")
# 绘制匹配结果
img_matches = cv2.drawMatches(img1, kp1, img2, kp2,
good_matches, None,
flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
# 显示结果
plt.figure(figsize=(15, 10))
plt.imshow(cv2.cvtColor(img_matches, cv2.COLOR_BGR2RGB))
plt.title(f'{method} - 找到 {len(good_matches)} 个匹配点')
plt.axis('off')
plt.show()
# 计算匹配质量评分
if len(good_matches) > 0:
match_score = len(good_matches) / min(len(kp1), len(kp2))
print(f"匹配质量评分: {match_score:.3f}")
# 显示匹配距离统计
distances = [m.distance for m in good_matches]
print(
f"匹配距离 - 平均: {np.mean(distances):.3f}, 最小: {np.min(distances):.3f}, 最大: {np.max(distances):.3f}")
else:
print("没有找到足够的匹配点")
if __name__ == "__main__":
demo_daisy_feature_matching()

四、DAISY的应用场景
由于其高效稠密的特性,DAISY被广泛应用于需要「逐像素特征匹配」的任务:
- 宽基线立体匹配:参考论文《DAISY: An Efficient Dense Descriptor Applied to Wide-baseline Stereo》(2010 SCI一区),DAISY能快速生成左右图像的稠密特征,结合EM算法计算深度图;
- 目标识别:将DAISY与SIFT结合(用SIFT找关键点,用DAISY描述周围稠密区域),能提升小目标或低纹理目标的识别率;
- 光流估计:稠密特征能更准确地跟踪像素级的运动轨迹。
五、写在最后:DAISY的局限性与未来
尽管DAISY在稠密提取上优势明显,但它也有局限性:
- 尺度不变性:DAISY没有像SIFT那样构建尺度金字塔,因此对尺度变化的鲁棒性较弱;
- 内存需求:稠密特征会生成海量特征向量(比如1000×1000的图像会生成1e6个32维向量),对内存的压力较大。
未来的改进方向可能是结合尺度金字塔(赋予DAISY尺度不变性)或特征压缩(用PCA将32维向量压缩到更低维度),进一步拓展其适用场景。
关注获取更多资料
我给大家整理了一套全网最全的人工智能学习资料(1.5T),包括:机器学习,深度学习,大模型,CV方向,NLP方向,kaggle大赛,实战项目、自动驾驶,AI就业等,扫码关注免费获取。

更多推荐



所有评论(0)