piccolo
,之前做的东西,简单整理下,不是做图像方向的,写的不好轻喷
主要原理参看SIFT算法详解和SIFT特征匹配算法介绍——寻找图像特征点的原理
相应源码在基于SIFT特征的图像拼接融合(matlab+vlfeat实现)
下面简单说下:
主要思想:一种基于图像梯度分布的特征描述子。
特点:具备尺度不变性,抗干扰性好。但维数高,计算复杂度大。
图像 I ( x , y ) I(x, y) I(x,y)在不同尺度空间下的表示可以由图像与高斯核卷积得到Gaussian图像:
高斯金字塔建立方程:
L ( x , y , δ ) = G ( x , y , δ ) × I ( x , y ) L(x, y, \delta)=G(x, y, \delta) \times I(x, y) L(x,y,δ)=G(x,y,δ)×I(x,y)
G ( x , y , δ ) = 1 2 π δ 2 e − ( x 2 + y 2 ) / ( 2 a 2 ) G(x, y, \delta)=\frac{1}{2 \pi \delta^{2}} e^{-\left(x^{2}+y^{2}\right) /\left(2 a^{2}\right)} G(x,y,δ)=2πδ21e−(x2+y2)/(2a2)
其中, L L L—尺度空间, G ( x , y , δ ) G(x, y, \delta) G(x,y,δ)—二维高斯滤波函数
D ( x , y , δ ) = L ( x , y , k δ ) − L ( x , y , δ ) D(x, y, \delta)=L(x, y, k \delta)-L(x, y, \delta) D(x,y,δ)=L(x,y,kδ)−L(x,y,δ)
其中, δ \delta δ—尺度空间因子, k k k—同一阶相邻两个层次建的尺度因子比例
对于一幅图像I
,建立其在不同尺度(scale)
的图像,也称为子八度(octave)
,这是为了让其在任何尺度都能够有对应的特征点。第一个子八度的scale
为原图大小,后面每个octave
为上一个octave
降采样的结果,即原图的1/4
(长宽分别减半),构成下一个子八度(高一层金字塔)。
为了寻找尺度空间的极值点,每一个采样点要和它所有的相邻点比较,看其是否比它的图像域和尺度域的相邻点大或者小。如下图所示,中间的检测点和它同尺度的8
个相邻点和上下相邻尺度对应的9×2
个点共26
个点比较,以确保在尺度空间和二维图像空间都检测到极值点。 一个点如果在DOG
尺度空间本层以及上下两层的26
个领域中是最大或最小值时,就认为该点是图像在该尺度下的一个特征点。
DOG
算子会产生较强的边缘响应
高斯差分算子的极值在横跨边缘处有较大的主曲率,而在垂直边缘的方向有较小的主曲率。在这里,我们利用海森边缘检测方法求主曲率,并去除边缘点
H = [ D x x D x y D x y D y y ] H=\left[ \begin{array}{ll}{D_{x x}} & {D_{x y}} \\ {D_{x y}} & {D_{y y}}\end{array}\right] H=[DxxDxyDxyDyy]
tr ( H ) = D x x + D y y = α + β det ( H ) = D x x D y y − D x y 2 = α β \begin{array}{r}{\operatorname{tr}(H)=D_{x x}+D_{y y}=\alpha+\beta} \\ {\operatorname{det}(H)=D_{x x} D_{y y}-D_{x y}^{2}=\alpha \beta}\end{array} tr(H)=Dxx+Dyy=α+βdet(H)=DxxDyy−Dxy2=αβ
选取合适的主曲率阈值,去除不稳定的边缘响应点,如果满足
tr ( H ) det ( H ) = ( α + β ) 2 α β = ( r + 1 ) 2 r \frac{\operatorname{tr}(H)}{\operatorname{det}(H)}=\frac{(\alpha+\beta)^{2}}{\alpha \beta}=\frac{(r+1)^{2}}{r} det(H)tr(H)=αβ(α+β)2=r(r+1)2
α = r β \alpha=r \beta α=rβ
则将该关键点判定为特征点
edit startup.m
创建启动文件startup.m
,尽量创建在你的当前project
目录下。比如我的E:\matlabzyf\sift\startup.m
%vlfeat工具箱的导入,运行前准备工作
run('E:\matlabzyf\vlfeat-0.9.20\toolbox\vl_setup')
project
前,先运行startup.m
,有时候他没有自动加载(可能是我的bug)