目录
一、Harris角点检测算法
1.角点
角点具有的特征:
局部窗口沿各方向移动,均产生明显变化的点;图像局部曲率突变的点;轮廓之间的交点;
对于同一场景,即使视角发生变化,通常具备稳定性质的特征;
该点附近区域的像素点无论在梯度方向上还是其梯度幅值上有着较大变化;
2.角点检测算法基本思想
使用一个固定小窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后两种情况,窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有着较大灰度变化,那么我们可以认为该窗口中存在角点。
好的角点检测算法能够检测出图像中“真实的”角点,具有准确的定位性能,有很高的稳定性,具有对噪声的鲁棒性,具有较高的计算效率。
3.数学方法刻画角点特征
当窗口发生[u,v]移动的时候,滑动前和滑动后对应的窗口中的像素点灰度变化描述如下:
所以得到,当在平坦区域时,窗口向任意方向移动,无灰度变化;在边缘区域时,沿着边缘方向移动,无灰度变化;在角点区域时,沿着任意方向移动,有明显灰度变化。
经过一系列E(u,v)表达式的演化, E(u,v)表达式可以更新为:
其中矩阵M是2x2矩阵,可由图像的导数求得:
4.角点响应函数
Harris矩阵Mi的特征值有三种情况:
- 如果 λ1和 λ 2都是很大的正数,则该x点为角点;
- 如果λ1很大,λ 2 很小(接近于0),则该区域内存在一个边,该区域内的平均Mi的特征值不会变化太大;
- 如果λ1λ2 都是很小的数 (λ1≈λ2≈0), 则该区域为空。
5.Harris角点检测器的响应函数
Harris角点检测器的响应函数会返回像素值为 Harris 响应函数值的一幅图像
def compute_harris_response(im, sigma=3):
"""在一幅灰度图像中,对每个像素计算Harris角点检测器响应函数"""
# 计算导数
imx = zeros(im.shape)
filters.gaussian_filter(im, (sigma, sigma), (0,1), imx)
imy = zeros(im.shape)
filters.gaussian_filter(im, (sigma, sigma), (1,0), imy)
# 计算Harris矩阵的分量
Wxx = filters.gaussian_filter(imx*imx, sigma)
Wxy = filters.gaussian_filter(imx*imy, sigma)
Wyy = filters.gaussian_filter(imy*imy, sigma)
# 计算特征值和迹
Wdet = Wxx * Wyy - Wxy**2
Wtr = Wxx + Wyy
return Wdet / Wtr
我们需要从这幅图像中挑选出需要的信息
然后,选取像素值高于阈值的所有图像点
再加上额外的限制,即角点之间的间隔必须大于设定的最小距离
这种方法会产生很好的角点检测结果
为了实现该算法,我们获取所有的候选像素点,以角点响应值递减的顺序排序
然后将距离已标记为角点位置过近的区域从候选像素点中删除
def get_harris_points(harrisim, min_dist=10, threshold=0.1):
"""从一幅Harris响应图像中返回角点。min_dist为分割角点和图像边界的最小像素数目"""
# 寻找高于阈值的候选角点
corner_threshold = harrisim.max() * threshold
harrisim_t = (harrisim > corner_threshold) * 1
# 得到候选点的坐标
coords = array(harrisim_t.nonzero()).T
# 以及它们的Harris响应值
candidate_values = [harrisim[c[0], c[1]] for c in coords]
# 对候选点按照Harris响应值进行排序
index = argsort(candidate_values)
# 将可行点的位置保存到数组中
allowed_locations = zeros(harrisim.shape)
allowed_locations[min_dist:-min_dist,min_dist:-min_dist] = 1
# 按照min_distance原则,选择最佳Harris点
filtered_coords = []
for i in index:
if allowed_locations[coords[i,0], coords[i,1]] == 1:
filtered_coords.append(coords[i])
allowed_locations[(coords[i,0]-min_dist):(coords[i,0]+min_dist),
(coords[i,1]-min_dist):(coords[i,1]+min_dist)] = 0
return filtered_coords
6.代码实现
from pylab import *
from PIL import Image
from PCV.localdescriptors import harris
# 读入图像
im =