角检测(Corner detection)是指检测图像中具有代表性的(我们感兴趣的)角点,一般讲为形状或边缘的拐角处,这些点可以大略标记对象在图像中的轮廓和位置,如果从一个图像序列中检测每个图像的角点,就可以找出图像之间存在的相关和相对应的角点,这对比如全景拼接(多张图片拼接成一张全景图片)很有用。
角检测还可以用在运动检测、物体识别等方面。

Harris角检测

Harris角检测(也叫Harris & Stephens角检测)是目前可用的最简单的角检测算法。它的基本思路是这样的:对于图像中的一个点,如果它周围存在1个以上不同方向的边缘,这个点所在处就是角。

下面需要粗略地介绍一下其中的数学原理,以便理解Harris滤波器函数参数的作用。

我们之前学习边缘检测的时候知道,边缘上的点,水平和垂直两个方向的梯度幅度(一阶导数)较周围高,如果要检测点所在处是否具有1个方向以上的边缘,就必须要综合它周围点的梯度一起考虑,那么问题就变成了需要计算周围区域,像素两两之间的梯度关系,我们在学习PCA算法的时候知道协方差矩阵能体现这种关系,设Ix为点x在它周围一小块区域内的水平方向梯度,同样,设Iy为点y垂直方向梯度,组成一个协方差矩阵:

在点(x,y)附近一小块区域内,离(x,y)越近,关系越大,这就需要考虑加权计算,设加权算子为W(典型值使用高斯核,之前笔记介绍过),得到:
A = W * M

A被称为Harris矩阵,它两个特征值λ1和λ2,如果:

  • λ1和λ2都为较大的正数,表示对应的(x,y)点处是角

  • 若λ1较大,而且λ2约等于0,表示所在点只有一条边,非角

  • 若λ1和λ2都约等于0,表示所在处没有边角

求Harris矩阵的特征值计算量较大,Harris给出了一个方程:

上式只要计算矩阵的行列式(det)和迹(trace)即可,计算方便,得到的结果可作为角的检测,其中系数k是一个经验值,它的设置跟边缘的粗细有关。我们暂且把这种方法称为k方法。

为使得计算更方便,Noble角测量(Noble’s corner measure)给出了去除k系数的方法,只要计算:

eps(或ϵ)为一个很小的正的常量,我们暂且称此为eps方法。

Harris代码实现
根据以上所介绍的eps方法,下面实现一个Harris角检测函数:

def harris_eps(im, sigma=3):imx = np.zeros(im.shape)filters.gaussian_filter(im, (sigma,sigma), (0,1), imx)imy = np.zeros(im.shape)filters.gaussian_filter(im, (sigma,sigma), (1,0), imy)#计算两两之间的一阶导数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#按eps公式计算return Wdet * 2 / (Wtr + 1e-06)

注意:书上并没有严格按照公式计算返回值,经测试,对某些图片会出现无法除的情况,所以上面的代码进行了改正

确定坐标
Harris返回的结果是一个与原图像大小相同的矩阵,要判断是否是角点,还需要做如下的工作:

  • 设定一个阈值,只考虑高于阈值的点,这样可以过滤掉无用的或不感兴趣的点

  • 一个角处一般会有多个点,在标记角坐标的时候,应该设定一个最小距离,在此距离内只需要一个点进行标记即可

这个判断函数可以使用skimage库中的corner_peaks函数,其中参数min_distance指上述的最小距离,threshold_rel则为阈值,函数原型:

skimage.feature.corner_peaks(harrisim, min_distance=10, threshold_abs=0, threshold_rel=0.1, ...)

函数默认返回由所有角点在原图像中的坐标组成的数组。

skimage库的Harris函数

skimage库也提供了Harris角检测函数:

skimage.feature.corner_harris(image, method='k', k=0.05, eps=1e-06, sigma=1)method: 'k'或'eps',对应上述的两种计算方法
k: k方法中的k系数,取值区间为[0, 0.2],k的值越小,表示将检测越锐利的角
eps: eps方法中的系数,默认即可
sigma: 高斯核的标准差

简单示例:

import numpy as np
from skimage.feature import corner_harris, corner_peakssquare = np.zeros([10, 10])
square[2:8, 2:8] = 1
square.astype(int)print square
>>[[ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.][ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.][ 0.  0.  1.  1.  1.  1.  1.  1.  0.  0.][ 0.  0.  1.  1.  1.  1.  1.  1.  0.  0.][ 0.  0.  1.  1.  1.  1.  1.  1.  0.  0.][ 0.  0.  1.  1.  1.  1.  1.  1.  0.  0.][ 0.  0.  1.  1.  1.  1.  1.  1.  0.  0.][ 0.  0.  1.  1.  1.  1.  1.  1.  0.  0.][ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.][ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]harris_result = corner_harris(square)
print corner_peaks(harris_result, min_distance=1) #此函数能够从harris结果中检测角的坐标位置
>>[[2 2][2 7][7 2][7 7]]

上面harris_result如图,观察一下角处的值与周围的不同:

对比示例

我分别用我们自己实现的harris_eps函数,跟skimage中的corner_harris函数进行效果对比,发现两者存在差异,有使用了两张图像进行了测试,一张是内容比较简单的矢量图,一张是写实图,效果如下:

可以看到,使用简单的房子的图像时,通过微调参数,三种方法都可以达到比较接近的效果。但使用写实的图像(第二列)时,三者差异较大,skiamge库的版本检测出的角结果不是我们期望的。而且我通过调整参数也很难达到效果。原因还不清楚,有空再回头分析一下corner_harris函数的源代码。

以上示例的代码:

from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
from skimage.feature import corner_harris, corner_peaks
from scipy.ndimage import filters#harris_eps函数此处省略,见上文im1 = np.array(Image.open('house.jpg').convert('L'))
im2 = np.array(Image.open('tower-left.jpg').convert('L'))my_coords1 = corner_peaks(harris_eps(im1, sigma=1), min_distance=12, threshold_rel=0)
eps_coords1 = corner_peaks(corner_harris(im1, method='eps', sigma=1), min_distance=20, threshold_rel=0)
k_coords1 = corner_peaks(corner_harris(im1, method='k', sigma=1), min_distance=20, threshold_rel=0)my_coords2 = corner_peaks(harris_eps(im2, sigma=1), min_distance=5, threshold_rel=0.01)
eps_coords2 = corner_peaks(corner_harris(im2, method='eps', sigma=1), min_distance=5, threshold_rel=0.01)
k_coords2 = corner_peaks(corner_harris(im2, method='k', sigma=1), min_distance=5, threshold_rel=0.01)def plot_coords(index, title, im, coords):plt.subplot(index)plt.imshow(im)plt.plot(coords[:, 1], coords[:, 0], '+r', markersize=5)plt.title(title)plt.axis('off')plt.gray()
index = 321
plot_coords(index, 'my', im1, my_coords1)
plot_coords(index + 1, 'my', im2, my_coords2)
plot_coords(index + 2, 'skimage-eps', im1, eps_coords1)
plot_coords(index + 3, 'skimage-eps', im2, eps_coords2)
plot_coords(index + 4, 'skimage-k', im1, k_coords1)
plot_coords(index + 5, 'skimage-k', im2, k_coords2)
plt.tight_layout(w_pad=0)
plt.show()

小结

下一笔记学习如何从图像间找出相关的对应点。
你还可以查看我的其它笔记

参考资料

wiki: Corner detection
skimage corner example

Programming Computer Vision with Python (学习笔记九)相关推荐

  1. Programming Computer Vision with Python (学习笔记一)

    转载自:http://segmentfault.com/a/1190000003941588 介绍 <Programming Computer Vision with Python>是一本 ...

  2. Programming Computer Vision with Python【学习笔记】【第一章】

    第1章 基本的图像操作和处理 1.1 PIL:Python图像处理类库 1.1.1 转换图像格式--save()函数 1.1.2 创建缩略图 1.1.3 复制并粘贴图像区域 1.1.4 调整尺寸和旋转 ...

  3. Programming Computer Vision with Python (学习笔记四)

    上一个笔记主要是讲了PCA的原理,并给出了二维图像降一维的示例代码.但还遗留了以下几个问题: 在计算协方差和特征向量的方法上,书上使用的是一种被作者称为compact trick的技巧,以及奇异值分解 ...

  4. Programming Computer Vision with Python (学习笔记十二)

    ORB(Oriented FAST and Rotated BRIEF)可用来替代SIFT(或SURF),它对图像更具有抗噪特性,是一种特征检测高效算法,其速度满足实时要求,可用于增强图像匹配应用. ...

  5. Programming Computer Vision with Python (学习笔记十一)

    尺度不变特征变换(Scale-invariant feature transform, 简称SIFT)是图像局部特征提取的现代方法--基于区域/图像块的分析.在上篇笔记里我们使用的图像之间对应点的匹配 ...

  6. Programming Computer Vision with Python (学习笔记八)

    图像去噪(Image Denoising)的过程就是将噪点从图像中去除的同时尽可能的保留原图像的细节和结构.这里讲的去噪跟前面笔记提过的去噪不一样,这里是指高级去噪技术,前面提过的高斯平滑也能去噪,但 ...

  7. Programming Computer Vision with Python (学习笔记七)

    数学形态学(mathematical morphology)关注的是图像中的形状,它提供了一些方法用于检测形状和改变形状.起初是基于二值图像提出的,后来扩展到灰度图像.二值图像就是:每个像素的值只能是 ...

  8. Programming Computer Vision with Python (学习笔记五)

    SciPy库 SciPy库,与之前我们使用的NumPy和Matplotlib,都是scipy.org提供的用于科学计算方面的核心库.相对NumPy,SciPy库提供了面向更高层应用的算法和函数(其实也 ...

  9. Programming Computer Vision with Python (学习笔记二)

    首先介绍跟图像处理.显示有关两个库:NumPy和Matplotlib,然后介绍增强图像对比度的实现原理. NumPy NumPy是Python用于科学计算的基础库,提供了一些很有用的概念,如:N维数组 ...

最新文章

  1. Spring Boot实现定时任务的动态增删启停
  2. Visual Studio Xamarin中找不到iOS模拟器
  3. 数据结构和算法之稀疏数组
  4. Docker框架的使用系列教程(二)
  5. oracle := 和=,oracle a:=100 和 b=:c 区别
  6. Linux内存管理:知识点总结(ARM64)
  7. 无需搭建和训练模型,87行代码搞定文章摘要生成
  8. Chrome浏览器的翻译插件开发
  9. 磁共振成像(MRI)影像心脏组织分割
  10. 江苏小高考计算机什么时候考,2021江苏小高考时间 什么时候考试
  11. 下载美国气候数据中心地址
  12. 最新百度云不限速软件
  13. CUPS学习五:打印机基础
  14. markdown的基本使用方法 1
  15. 树莓派3b+和 intel movidius 神经元计算棒2代 跑yolo v3 tiny
  16. Vue如何使用ECharts
  17. On release of batch it still contained JDBC statements
  18. 网红王思聪数字时钟动态壁纸【电脑壁纸】
  19. 2018hdu个人排位赛:涮羊肉
  20. `泷泽萝拉.png .exe`

热门文章

  1. java中如何忽略字符串中的转义字符--转载
  2. 项目中使用Quartz集群分享--转载
  3. javascript-for-loop-example--reference
  4. Linux服务器集群系统(一)--转
  5. 金融风控实战——信贷评分卡
  6. 李开复:天才将占领创业领域
  7. MySQL - 高效的设计MySQL库表
  8. Spring-注入参数详解-[简化配置方式]
  9. Imageloader8-压缩图片
  10. python模块的函数_Python模块及函数的使用