【干货】计算机视觉实战系列09——用Python做图像处理

【导读】通过之前的学习,我们已经熟悉了python关于图像处理的基本操作和工具库,接下来我们将系统学习局部图像的描述子。这一阶段的学习旨在寻找图像间的对应点和对应区域。图像处理的很多内容都会用到局部特征,局部特征在很多应用中都有着重要的作用,比如创建全景图、增强现实技术以及计算图像的三维重建。


【干货】计算机视觉实战系列01——用Python做图像处理(基本的图像操作和处理)

【干货】计算机视觉实战系列02——用Python做图像处理(Matplotlib基本的图像操作和处理)

【干货】计算机视觉实战系列03——用Python做图像处理(Numpy基本操作和图像灰度变换)

【干货】计算机视觉实战系列04——用Python做图像处理(图像的缩放、均匀操作和直方图均衡化)

【干货】计算机视觉实战系列05——用Python做图像处理(主成分分析)

【干货】计算机视觉实战系列06——用Python做图像处理(图像高斯模糊分析)

【干货】计算机视觉实战系列07——用Python做图像处理(SciPy库的应用——图像导数实战)

【干货】计算机视觉实战系列08——用Python做图像处理



Harris角点检测器


Harris角点检测算法,(又称Harris&Stephens角点检测器)是极为简单的一种角点检测算法,该算法的主要思想是:如果某点存在多于一个方向的边,则认为该点是兴趣点,称为角点。算法基本思想是使用一个固定窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后两种情况,窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有着较大灰度变化,那么我们可以认为该窗口中存在角点。


角点通常被定义为两条边的交点,更严格的说,角点的局部邻域应该具有两个不同区域的不同方向的边界。而实际应用中,大多数所谓的角点检测方法检测的是拥有特定特征的图像点,而不仅仅是“角点”。这些特征点在图像中有具体的坐标,并具有某些数学特征,如局部最大或最小灰度、某些梯度特征等。

 

算法的数学原理




我们将图像上某点x上对称的半定矩阵定义为:


其中为包含方向导数的梯度(在之前的学习中我们 已经详细介绍了方向导数和梯度),由于该定义,的秩为1,特征值为。现在对于图像的每一个像素,我们可以计算出该矩阵。

 

选择权重矩阵W(通常为高斯滤波器),我们可以得到卷积


该卷积的目的是得到在周围像素上的局部平均。计算出的矩阵又称为Harris矩阵,W的宽度决定了像素x周围的感兴趣区域。像这样在区域附近对矩阵取平均的原因是,特征值会依赖于局部图像特征而变化。如果图像的梯度在该区域变化,那么的第二个特征值将不再为0,如果图像的梯度没有变化,的特征值也不会变化。

 

取决于该区域的的值,Harris矩阵的特征值有三种情况:

1. 如果都是很大的正数,则x点为角点;

2. 如果很大,,则该区域内存在一个边,该区域内的平均的特征值不会变化太大;

3. 如果,该区域内为空。

在不需要实际计算特征值的情况下,为了把重要的情况和其他情况分开,Harris和Stephens引入了指示函数


为了去除加权平均常数k,我们通常使用商数作为指示器。


代码




完整的代码如下:

from PIL import Image
import numpy as np
from pylab import *
from scipy.ndimage import filters


def compute_harris_response(im, sigma=3):
'''''
   对每个像素值计算Harris角点检测器响应函数
   :param im:
   :param sigma:
   :return:
   '''

   
# 计算导数  
   
im_x = np.zeros(im.shape)
im_y = np.zeros(im.shape)
filters.gaussian_filter(im, (sigma, sigma), (0, 1), im_x)
filters.gaussian_filter(im, (sigma, sigma), (1, 0), im_y)

# 计算Harris矩阵分量  
   
Ixx = filters.gaussian_filter(im_x * im_x, sigma)
Ixy = filters.gaussian_filter(im_x * im_y, sigma)
Iyy = filters.gaussian_filter(im_y * im_y, sigma)

# 计算特征值和迹  
   
Idet = Ixx * Iyy - Ixy ** 2
   
Itrace = Ixx + Iyy

result = Idet / Itrace
result[isnan(result)] = 0
   
return result


def get_harris_points(harrisim, min_dist=10, threshold=0.1):
'''''
   从Harrris响应图像中筛选角点
   :param harrisim:
   :param min_dist:
   :param threshold:
   :return:
   '''

   
corner_threshold = harrisim.max() * threshold
harrisim_t = (harrisim > corner_threshold) * 1

   
# 获得候选点的坐标和对应的值  
   
coords = np.array(harrisim_t.nonzero()).T
candidate_values = [harrisim[c[0], c[1]] for c in coords]

# 对候选点排序  
   
index = np.argsort(candidate_values)

# 将可行点存储在数组中  
   
allowed_locations = np.zeros(harrisim.shape)
allowed_locations[min_dist:-min_dist, min_dist:-min_dist] = 1

   
# 按照最小间距原则选择最佳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


def plot_corner_points(image, filtered_coords):
'''''
   绘制图像中的角点
   :param image:
   :param filtered_coords:
   :return:
   '''
   
imshow(image)
plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')
axis('off')


if __name__ == '__main__':
im = array(Image.open('test.jpg').convert('L'))
harrsim = compute_harris_response(im)
filter_coords1 = get_harris_points(harrsim, 10, 0.1)
filter_coords2 = get_harris_points(harrsim, 10, 0.2)
filter_coords3 = get_harris_points(harrsim, 10, 0.7)
figure()
gray()
fig = plt.figure(figsize=(30, 30))
subplot(131)

plot_corner_points(im, filter_coords1)
title('threshold = 0.1')
subplot(132)
plot_corner_points(im, filter_coords2)
title('threshold = 0.2')
subplot(133)
plot_corner_points(im, filter_coords3)
title('threshold = 0.7')
show()


输出的结果如下图所示:

 

上面我们写出了Harris角点检测程序。对于这个函数,我们需要使用scipy.ndimage.filters模块中的高斯导数滤波器来计算导数。使用高斯滤波器的道理同样是我们需要在角点检测过程中抑制噪声强度。

 

首先我们定义了一个compute_harris_response()函数。在角点相应函数使用高斯导数实现,同样地,参数定义了使用高斯滤波器的尺度大小。你也可以修改这个函数,对x和y方向上不同的尺度参数,以及尝试平均操作中的不同尺度,计算Harris矩阵。

 

这个函数会返回像素值为Harris响应函数值的一幅图像。现在,我们需要从这幅图像中挑选出需要的信息,为此,我们定义了get_harris_points()函数。选取出像素值高于阈值的所有图像点;再加上额外的限制,即角点之间的间隔必须大于设定的最小距离。这种方法会产生很好的角点检测结果。为了实现该算法,我们获取所有的候选像素点,以角点响应值递减的顺序排序,然后将距离已标记为角点位置过近的区域从候选像素点中删除。

 

当我么你有了检测图像中角点所需要的所有函数,为了显示图像中的角点,你可以使用Matplotlib模块绘制函数。


参考文献:

python计算机视觉编程:http://yongyuan.name/pcvwithpython/


更多教程资料请访问:专知AI会员计划

-END-

专 · 知

人工智能领域主题知识资料查看与加入专知人工智能服务群

【专知AI服务计划】专知AI知识技术服务会员群加入人工智能领域26个主题知识资料全集获取

[点击上面图片加入会员]

请PC登录www.zhuanzhi.ai或者点击阅读原文,注册登录专知,获取更多AI知识资料

请加专知小助手微信(扫一扫如下二维码添加),加入专知主题群(请备注主题类型:AI、NLP、CV、 KG等)交流~

关注专知公众号,获取人工智能的专业知识!

点击“阅读原文”,使用专知

展开全文
Top
微信扫码咨询专知VIP会员