计算机视觉2—Harris角点检测

目录

 

一、Harris 角点检测算法简介

二、涉及函数

1.compute_harris_response

2.get_harris_points

三、harris算法不同场景的实现

1.边缘丰富场景

2.角点丰富场景

3.纹理平坦场景

四、小结

五、代码


一、Harris 角点检测算法简介

1.角点:①局部窗口沿各方向移动,均产生明显变化的点    ②图像局部曲率突变的点

2.Harris 角点检测算法(Harris & Stephens 角点检测器)是一个极为简单的角点检测算法。该算法是利用移动的窗口在图像中计算灰度变化值,应用邻近像素点灰度差值概念,从而进行判断是否为角点、边缘、平滑区域。

3.角点检测基本思想:

边缘:沿着边缘方向移动,无灰度变化

角点:沿任意方向移动,明显灰度变化

平坦:任意方向移动,无灰度变化

二、涉及函数

1.compute_harris_response

该函数在 harris.py 文件中,该函数在一幅灰度图像中,对每个像素计算Harris角点检测器响应函数。因在角点检测中需要抑制噪声,使用了 scipy.ndimage.filters 模块中的高斯导数滤波器来计算导数。

from pylab import *
from numpy import *
# 使用 scipy.ndimage.filters 模块中的高斯导数滤波器来计算导数
from scipy.ndimage import filters

该函数有两个参数(im, sigma),im为传入图像,sigma则定义了高斯滤波器的尺度大小,该函数返回像素值为Harris响应函数的一幅图像 。

对图像中的每一个像素,计算Harris矩阵时,Harris矩阵的特征值有三种情况:

  • 都是很大的正数,则该点是角点
  • 一个很大,一个约等于0,则该区域存在一个边
  • 都约等于0,该区域为空
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

    # 返回像素值为 Harris 响应函数值的一幅图像
    return Wdet / Wtr

2.get_harris_points

该函数同样是在 harris.py 文件中,上面的compute_harris_response函数返回了像素值为 Harris 响应函数值的一幅图像,我们需要从这幅图像中挑选出需要的信息,选取像素值高于阈值的所有图像点,再加上额外的限制,即角点之间的间隔必须大于设定的最小距离。

如下函数示,获取所有的候选像素点,以角点响应值递减的顺序排序,然后将距离已标记为角点位置过近的区域从候选像素点中删除。

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)[::-1]
    
    # 将可行点的位置保存到数组中
    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

三、harris算法不同场景的实现

1.边缘丰富场景

该场景选取的是一个建筑群五个不同角度原图:正面和近面光线较暗,远面、侧面和旋转的面光线较好,五个不同角度的图片,背景各不相同。

五个不同角度结果图:

正面
侧面
远面

 

近面
旋转

小结:五个场景的对比可以看出,harris算法可以将每个场景下的建筑群都能识别出来,但是正面和侧面的图中天空中的云朵也有部分被识别出来,应该是光线较亮的缘故,在该场景中,光线对于识别建筑群没有较大阻碍,因为两张较暗面下的建筑群也被很好的识别出来了。

2.角点丰富场景

该场景选取的是书桌上的一堆杂物,光线不一,角度不一:

五个不同角度结果图:

正面
侧面
远面
近面
旋转

小结:从五个角度的图片对比来看,近面得到的角点较少,在该场景下,近面是某一区域的大图,囊括的物体相对较少,角点也就相对少了,五个角度的物体都能识别出来,但是远面的背景也有几个角点,可能存在是我的图片墙壁背景不够干净,但是瓶子的手提带子有在正面图中很明显却并未识别出来,而墙壁倒是有几个角点,结果不是很精确。

3.纹理平坦场景

该场景选取的是一个问了平坦的背景,选取了四个角度和一个曝光面:

五个不同角度结果图:

正面
曝光
侧面
近面
远面

小结:五个不同角度下的角点,光线因素影响不大,从曝光图片和其他图片的对比可知,近面下的角点较少,因为是物体的大图,轮廓比较清晰,其他四图都是将平坦场景下的物体整个识别出来覆盖了角点。

四、小结

通过边缘丰富、角点丰富和纹理平坦三个场景,每个场景五个角度的对比可知,近面下的角点数都是较少的,因近面下的物体轮廓清晰,可以很好地分析物体轮廓精确的检测角点;平坦的界面相对于边缘、角点丰富的画面也更有利于角点的检测,因复杂背景对检测有一点的阻碍;在边缘丰富的场景下,沿边缘移动,尤其是有垂直限定线段的边缘,角点的分布还是可以看出一定的物体轮廓,而在角点丰富的场景下,任意移动,角点分布就相对杂乱。

五、代码

# -*- coding: utf-8 -*-
from pylab import *
from PIL import Image
from PCV.localdescriptors import harris

"""
Example of detecting Harris corner points (Figure 2-1 in the book).
"""

# 读入图像为im,转换为灰度图convert('L')
im = array(Image.open('data/pic/j1.jpg').convert('L'))

# 检测harris角点
harrisim = harris.compute_harris_response(im)


# Harris响应函数
harrisim1 = 255 - harrisim


figure()
gray()

#画出Harris响应图
subplot(141)
imshow(harrisim1)
print harrisim1.shape
axis('off')
axis('equal')

threshold = [0.01, 0.05, 0.1]
for i, thres in enumerate(threshold):
    filtered_coords = harris.get_harris_points(harrisim, 6, thres)
    subplot(1, 4, i+2)
    imshow(im)
    print im.shape
    plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')
    axis('off')


show()
发布了13 篇原创文章 · 获赞 5 · 访问量 1204

猜你喜欢

转载自blog.csdn.net/qq_43653930/article/details/104494651