手写计算机视觉算法:Harris角点检测算子

Jan 23,2019   3407 words   13 min


在上一篇博客中介绍了计算机视觉领域的开山角点描述子——Moravec算子。但同时也看到,它还存在着很多问题,例如只能在指定方向上对灰度进行计算、对边缘有较强响应等。 本篇博客主要学习实现Moravec算子的升级版——Harris算子。相比于Moravec算子,Harris算子在实际中有非常广泛的应用。

小小的吐槽一下,如果想对某些算法原理追根溯源,还是建议去国外网站上查相关资料吧。为了找Harris的论文,百度了好久,各种CSDN博客几乎翻了个遍,一个引用原始论文的都没看见。只是感叹CSDN博客质量确实良莠不齐。在WiKi上一搜Corner Detection词条,查下Harris算子的相关引用,很方便的就找到论文了。

1.Harris算子介绍

Harris角点算子的简历如下:

  • 提出者:Harris and Stephens
  • 提出时间:1988
  • 相关论文:A combined corner and edge detector(相比于Moravec的那篇,这篇文档质量好太多了)
  • 一句话总结: Moravec算子的改进版,更加稳定

2.Harris算子原理

在之前介绍Moravec算子的时候说过,它的缺点主要有三个方面:

  • 一是Moravec算子各向异性响应(Anisotropic Response),简单来说就是它只在4个方向对梯度进行了计算,无法获取任意方向梯度
  • 二是Moravec算子在计算CRF时由于采用等权求和,导致其对噪声较为敏感,易受噪声干扰(Noise Response)
  • 三是Moravec算子对边缘有较强响应(Large Response of Edge),容易出现误检。

针对这三点,Harris依次提出了三个方法来改进Moravec算子。

(1)灰度梯度近似

相比于Moravec算子固定方向上的梯度感知,Harris算子在数学上对灰度变化进行了更为精确的逼近,与Moravec算子中灰度变化不同的是通过合理的选择(u,v)可以对任何方向的灰度变化进行测度。论文原文截图如下:

(2)高斯权重

相较于Moravec的方形窗口,Harris通过采用二维高斯分布的权重,使得形成了一个圆形窗口。离中心越近的像素权重越大,而离中心越远,权重越小。

一个二维高斯分布的示意图如下所示。

论文中相关表述如下。

(3)改进的角点测度函数

为了减轻Moravec算子中对边缘的强响应,Harris提出了一个全新的角点测度方法。通过将灰度变化写成矩阵形式进而从矩阵运算角度提出了方案。由于M是对称阵,所以主对角线元素即为特征值,通过比较两个特征值之间的关系对角点进行判断。论文相关部分如下:

在实际计算中,采用如下方法会更快一些。

3.Harris算子实现

Harris算子的实现相对简单。相对复杂的是指定大小的二维高斯模板生成。难点在于小数的取整,对于一些常用的高斯模板会有一定的出入,并不严格的是向上、向下或四舍五入取整。而且与参数也有关,收集了几个常用参数如下:

# win_size=5, sigma=1.4
# win_size=5, sigma=1
# win_size=7, sigma=0.84089642
# win_size=3, sigma=0.8

获取指定大小及σ的高斯模板函数如下。

def getGaussianFilter(win_size=3, sigma=0.8):
    xs = []
    ys = []
    g_xys = []
    g_xys_normal = []
    g_xys_int = []
    cen_x = win_size / 2
    cen_y = win_size / 2
    for i in range(win_size):
        for j in range(win_size):
            cen_i = i - cen_x
            cen_j = j - cen_y
            g_xy = (1 / (2.0 * math.pi * sigma * sigma)) * \
                   math.pow(math.e, -(cen_i * cen_i + cen_j * cen_j) / (2.0 * sigma * sigma))
            xs.append(i)
            ys.append(j)
            g_xys.append(g_xy)
    scale_num = 1.0 / sum(g_xys)

    for i in range(g_xys.__len__()):
        g_xys_normal.append(g_xys[i] * scale_num)

    filter = np.zeros([win_size, win_size])
    for i in range(win_size):
        for j in range(win_size):
            filter[i, j] = g_xys_normal[i * win_size + j]

    min_num = min(g_xys_normal)
    for i in range(g_xys_normal.__len__()):
        g_xys_int.append(int(g_xys_normal[i] / min_num))

    filter_int = np.zeros([win_size, win_size])
    for i in range(win_size):
        for j in range(win_size):
            filter_int[i, j] = g_xys_int[i * win_size + j]

    return filter, filter_int

依据论文中的公式依次计算A、B、C以及R。k一般取0.04-0.06之间。K越大计算出的R越小,相同阈值下提取的角点越少。

def calcIx(win):
    win = np.int32(win)
    size = win.shape[1] - 2
    Ix = np.zeros([size, size], np.int32)
    for j in range(win.shape[0]):
        for i in range(1, win.shape[1] - 1):
            Ix[j, i - 1] = win[j, i + 1] - win[j, i - 1]
    return Ix


def calcIy(win):
    win = np.int32(win)
    size = win.shape[0] - 2
    Iy = np.zeros([size, size], np.int32)
    for j in range(1, win.shape[0] - 1):
        for i in range(win.shape[1]):
            Iy[j - 1, i] = win[j + 1, i] - win[j - 1, i]
    return Iy


def calcCornerResponse(img, i, j, gauss_kernel, win_size=3, k=0.04):
    winX = getXWindow(img, i, j, win_size)
    Ix = calcIx(winX)
    winY = getYWindow(img, i, j, win_size)
    Iy = calcIy(winY)
    Ix2 = Ix * Ix
    Iy2 = Iy * Iy
    IxIy = Ix * Iy
    A = np.sum((gauss_kernel * Ix2) / np.sum(gauss_kernel))
    B = np.sum((gauss_kernel * Iy2) / np.sum(gauss_kernel))
    C = np.sum((gauss_kernel * IxIy) / np.sum(gauss_kernel))
    det_M = A * B - C * C
    trace_M = A + B
    R = det_M - k * trace_M * trace_M
    return R

完整代码及测试数据见Github项目,点击查看

4.测试

相较于Moravec,Harris的效果好很多,但依然也会存在一些问题,需要后续其它的改进。

5.参考资料

  • [1]https://en.wikipedia.org/wiki/Corner_detection
  • [2]https://en.wikipedia.org/wiki/Harris_Corner_Detector
  • [3]http://www.bmva.org/bmvc/1988/avc-88-023.pdf
  • [4]https://blog.csdn.net/kezunhai/article/details/11265167
  • [5]http://www.360doc.com/content/15/1114/16/25664332_513168246.shtml
  • [6]https://blog.csdn.net/luoshixian099/article/details/48244255

本文作者原创,未经许可不得转载,谢谢配合

返回顶部