一、基本概念
角点corner:可以将角点看做两个边缘的交叉处,在两个方向上都有较大的变化。具体可由下图中分辨出来:
兴趣点interest point:兴趣点是图像中能够较鲁棒的检测出来的点,它不仅仅局限于角点. 也可以是灰度图像极大值或者极小值点等
二、Harris角点检测
Harris 算子是 Haris & Stephens 1988年在 "A Combined Corner and Edge Detector" 中提出的 提出的检测算法, 现在已经成为图像匹配中常用的算法.
对于一幅RGB图像我们很很容易得到corner 是各个方向梯度值较大的点, 定义 函数WSSD(Weighted Sum Squared Difference)为:
S(x,y)=∑u∑vw(u,v)(I((u+x,v+y)?I(u,v))2(1)
其中w(u,v)可以看作采样窗,可以选择矩形窗函数,也可以选择高斯窗函数:
I(u+x,v+y)?I(u,v)可以看作像素值变化量(梯度):
使用泰勒展开:I(u+x,v+y)≈I(u,v)+Ix(u,v)x+Iy(u,v)y(2)
(1)代入(2) S(x,y)≈∑u∑vw(u,v)(Ix(u,v)x+Iy(u,v)y)2
写成S(x,y)≈(x,y)A(x,y)T
其中 A 为 二阶梯度矩阵(structure tensor/ second-moment matrix)
A=∑u∑vw(u,v)[I2xIxIyIxIyI2y]
将A定义为Harris Matrix,A 的特征值有三种情况:
1. λ1≈0,λ2≈0,那么点x不是兴趣点
2. λ1≈0,λ2为一个较大的正数, 那么点x为边缘点(edge)
3. λ1,λ2都为一个较大的正数, 那么点x为角点(corner)
由于特征值的计算是 computationally expensive,引入如下函数
Mc=λ1λ2?κ(λ1+λ2)2=det(A)?κtrace2(A)
为了去除加权常数κ 直接计算
M′c=det(A)trace(A)+?
三、角点匹配
Harris角点检测仅仅检测出兴趣点位置,然而往往我们进行角点检测的目的是为了进行图像间的兴趣点匹配,我们在每一个兴趣点加入descriptors描述子信息,给出比较描述子信息的方法. Harris角点的,描述子是由周围像素值块batch的灰度值,以及用于比较归一化的相关矩阵构成。
通常,两个大小相同的像素块I_1(x)和I_2(x) 的相关矩阵为:
c(I1,I2)=∑xf(I1(x),I2(x))
f函数随着方法变化而变化,c(I1,I2)值越大,像素块相似度越高.
对互相关矩阵进行归一化得到normalized cross correlation :
ncc(I1,I2)=1n?2∑x(I1(x)?μ1)σ1?(I2(x)?μ2)σ2
其中μ为像素块的均值,\sigma为标准差. ncc对图像的亮度变化具有更好的稳健性.
四、python实现
python版本:2.7
依赖包: numpy,scipy,PIL, matplotlib
图片:
trees_002.jpg
trees003.jpg
PIL scipy.ndimage numpy * pylab * compute_harris_response(im,sigma=3 imx =1=1= filters.gaussian_filter(imx*= filters.gaussian_filter(imx*= filters.gaussian_filter(imy*= Wxx*Wyy-Wxy**2= Wxx+ Wdet/ get_harris_points(harrisim,min_dist=10,threshold=0.1 corner_threshold = harrisim.max()*= 1*(harrisim> coords = candicates_values = [harrisim[c[0],c[1]] c index = allowed_location =-min_dist,min_dist:-min_dist] = 1 filtered_coords = i allowed_location[coords[i,0],coords[i,1]]==1-min_dist):(coords[i,0]+1]-min_dist):(coords[i,1]+min_dist)]=1] p filtered_coords],[p[0] p filtered_coords], get_descriptors(image,filter_coords,wid=5= coords = image[coords[0]-wid:coords[0]+wid+11]-wid:coords[1]+wid+1 match(desc1,desc2,threshold=0.5= len(desc1[0]) d = - i j = (desc1[i]-mean(desc1[i]))/= (desc2[j]-mean(desc2[j]))/= sum(d1*d2)/(n-1 ncc_value>== argsort(-= match_twosided(desc1,desc2,threshold=0.5=== where(matches_12>= n matches_21[matches_12[n]] !== -1 rows1 == rows1<= concatenate((im1,zeros((rows2-rows1,im1.shape[1]))),axis= rows1<= concatenate((im2,zeros((rows1-rows2,im2.shape[1]))),axis= concatenate((im1,im2),axis=1 plot_matches(im1,im2,locs1,locs2,matchscores,show_below==== im1.shape[1 i,m m>1],locs2[m][1]+cols1],[locs1[i][0],locs2[m][0]],= array(Image.open().convert(= array(Image.open().convert(= 5= compute_harris_response(im1,5= get_harris_points(harrisim,wid+1== compute_harris_response(im2,5= get_harris_points(harrisim,wid+1= =
运行结果:
http://www.cnblogs.com/vincentcheng/p/7151614.htmlv