资讯专栏INFORMATION COLUMN

Programming Computer Vision with Python (学习笔记九)

focusj / 1584人阅读

摘要:角检测还可以用在运动检测物体识别等方面。角检测角检测也叫角检测是目前可用的最简单的角检测算法。为使得计算更方便,角测量给出了去除系数的方法,只要计算或为一个很小的正的常量,我们暂且称此为方法。你还可以查看我的其它笔记参考资料

角检测(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_peaks

square = 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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37656.html

相关文章

  • SegmentFault 技术周刊 Vol.30 - 学习 Python 来做一些神奇好玩的事情吧

    摘要:学习笔记七数学形态学关注的是图像中的形状,它提供了一些方法用于检测形状和改变形状。学习笔记十一尺度不变特征变换,简称是图像局部特征提取的现代方法基于区域图像块的分析。本文的目的是简明扼要地说明的编码机制,并给出一些建议。 showImg(https://segmentfault.com/img/bVRJbz?w=900&h=385); 前言 开始之前,我们先来看这样一个提问: pyth...

    lifesimple 评论0 收藏0
  • Programming Computer Vision with Python学习笔记一)

    摘要:接下来的学习笔记本人都将使用来代替。库中提供的很多图像操作都是分别作用于某个通道的数据。是最流行的开源色彩管理库之一。目前只支持在增加和。模块支持从图像对象创建或的对象,方便被使用和显示。模块对图像或指定区域的每个通道进行统计,包括等。 介绍 《Programming Computer Vision with Python》是一本介绍计算机视觉底层基本理论和算法的入门书,通过这本收可以...

    huashiou 评论0 收藏0
  • Programming Computer Vision with Python学习笔记五)

    摘要:下面是二维空间的高斯分布函数公式这个公式被称作高斯核。高斯模糊使用高斯平均算子来实现的图像模糊叫高斯模糊,也叫高斯平滑被认为是一种最优的图像平滑处理。 SciPy库 SciPy库,与之前我们使用的NumPy和Matplotlib,都是scipy.org提供的用于科学计算方面的核心库。相对NumPy,SciPy库提供了面向更高层应用的算法和函数(其实也是基于NumPy实现的),并以子模块...

    Rocko 评论0 收藏0
  • Programming Computer Vision with Python学习笔记八)

    摘要:简称库是从扩展下来的,提供了更丰富的图像处理函数,去噪函数除了还有算法,比如边缘检测还有以前简单提过的算子滤波器。下面我用看具体的例子,将和高斯平滑进行对比效果对比如下明显感觉使用的效果要比高斯平滑好很多。 图像去噪(Image Denoising)的过程就是将噪点从图像中去除的同时尽可能的保留原图像的细节和结构。这里讲的去噪跟前面笔记提过的去噪不一样,这里是指高级去噪技术,前面提过的...

    FleyX 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<