4

关于我的问题的一些细节:

我正在尝试在 openCV 中实现角检测器(另一种内置算法:Canny、Harris 等)。

我有一个填充了响应值的矩阵。最大的响应值是 - 检测到角点的最大概率是。

我有一个问题,在一个点附近检测到几个角(但只有一个)。我需要减少错误检测到的角落的数量。

确切的问题:

我需要用内核遍历矩阵,计算每个内核的最大值,留下最大值,但内核中的其他值等于零。

是否有内置的 openCV 函数可以做到这一点?

4

3 回答 3

17

我会这样做:

  1. 创建一个内核,它定义了一个像素邻域。
  2. 通过使用此内核扩展图像来创建新图像。该膨胀图像包含每个点的最大邻域值。
  3. 在这两个数组之间进行相等比较。它们相等的地方是一个有效的邻域最大值,并255在比较数组中设置为。
  4. 将比较数组和原始数组相乘(适当缩放)。
  5. 这是您的最终数组,仅包含邻域最大值。

这些放大的图像说明了这一点:

9 像素 x 9 像素原始图像:

在此处输入图像描述

使用 5 x 5 像素内核处理后,仅保留局部邻域最大值(即,最大值与具有更大值的像素相隔超过 2 个像素):

在此处输入图像描述

有一个警告。如果两个附近的最大值具有相同的值,那么它们都将出现在最终图像中。

这是一些 Python 代码,它应该很容易转换为 c++:

import cv

im = cv.LoadImage('fish2.png',cv.CV_LOAD_IMAGE_GRAYSCALE)
maxed = cv.CreateImage((im.width, im.height), cv.IPL_DEPTH_8U, 1)
comp = cv.CreateImage((im.width, im.height), cv.IPL_DEPTH_8U, 1)
#Create a 5*5 kernel anchored at 2,2
kernel = cv.CreateStructuringElementEx(5, 5, 2, 2, cv.CV_SHAPE_RECT)

cv.Dilate(im, maxed, element=kernel, iterations=1)
cv.Cmp(im, maxed, comp, cv.CV_CMP_EQ)
cv.Mul(im, comp, im, 1/255.0)

cv.ShowImage("local max only", im)
cv.WaitKey(0)

直到现在我才意识到,但这就是@sansuiso 在他/她的回答中所建议的。

之前用这张图片可能会更好地说明这一点:

在此处输入图像描述

使用 5 x 5 内核处理后:

在此处输入图像描述

实心区域是由于共享的局部最大值。

于 2012-05-25T15:26:36.030 回答
3

我建议使用 opencv 内置函数的原始两步程序(可能存在更有效的方法):

  1. 第 1 步:使用方形核(对应于您的邻域)进行形态膨胀。在将每个像素值替换为内核中的最大值之后,此步骤会为您提供另一个图像。

  2. 步骤2:测试原始响应图像的每个像素的角点值是否等于膨胀步骤给出的最大值。如果不是,那么显然附近有一个更好的角落。

于 2012-05-24T21:06:41.693 回答
2

如果您正在寻找一些内置功能,FilterEngine 将帮助您制作自定义过滤器(内核)。

http://docs.opencv.org/modules/imgproc/doc/filtering.html#filterengine

另外,我建议在所有处理之前进行某种降噪,通常是模糊处理。那是除非你真的想要原始图像。

于 2012-05-30T09:36:47.683 回答