Programming Computer Vision with Python (学习笔记九)
来源:互联网 发布:sql character 编辑:程序博客网 时间:2024/06/06 03:06
角检测(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 npfrom skimage.feature import corner_harris, corner_peakssquare = np.zeros([10, 10])square[2:8, 2:8] = 1square.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 Imageimport matplotlib.pyplot as pltimport numpy as npfrom skimage.feature import corner_harris, corner_peaksfrom 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 = 321plot_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 (学习笔记九)
- Programming Computer Vision with Python (学习笔记一)
- Programming Computer Vision with Python (学习笔记二)
- Programming Computer Vision with Python (学习笔记三)
- Programming Computer Vision with Python (学习笔记四)
- Programming Computer Vision with Python (学习笔记五)
- Programming Computer Vision with Python (学习笔记六)
- Programming Computer Vision with Python (学习笔记七)
- Programming Computer Vision with Python (学习笔记八)
- Programming Computer Vision with Python (学习笔记十)
- Programming Computer Vision with Python (学习笔记十一)
- Programming Computer Vision with Python (学习笔记十二)
- Python Computer Vision Programming学习笔记(一)——Python以及各Package安装
- Python Computer Vision Programming学习笔记(二)——基本的图像操作与处理
- Mastering OpenCV with Practical Computer Vision Projects 学习笔记 - Cartoonifier
- <<python computer vision with opencv>> chapter 2
- 《OpenCV Computer Vision with Python》pdf
- computer vision笔记(二)
- 【设计模式】依赖倒转原则
- 基于Spark的机器学习经验
- navicat for mysql 10.1.7注册码
- Programming Computer Vision with Python (学习笔记八)
- 1.scala(一)
- Programming Computer Vision with Python (学习笔记九)
- Spark Streaming 数据产生与导入相关的内存分析
- Android 中Activity,Window和View之间的关系 - 2
- eclipse(ini)
- Programming Computer Vision with Python (学习笔记十)
- Programming Computer Vision with Python (学习笔记十一)
- ORA-03113: End-of-file on Communication Channel Upon Startup of Database
- MySQL Replication 常用架构
- spring01 环境搭建、控制反转、依赖注入、springIOC和DI实现MVC模式