使用OpenCV在图像中寻找形状

5
我正在使用OpenCV 在图像中寻找形状。我知道我想要匹配的形状(有一些我不知道,但我不需要找到它们)和它们的方向。我不知道它们的大小(比例)和位置。
我的当前方法:
  1. 检测轮廓
  2. 对于每个轮廓,计算最大边界框
  3. 将每个边界框分别与已知形状之一进行匹配。在我的实际项目中,我会将区域缩放到模板大小并计算Sobel梯度的差异,但是对于这个演示,我只是使用了纵横比。
当形状相互接触时,这种方法就失效了。轮廓检测会将两个相邻的形状作为单个轮廓(单个边界框)捕获。然后匹配步骤显然会失败。
有没有办法修改我的方法以单独处理相邻的形状?还有更好的执行第3步的方法吗?
import cv
import sys
E = cv.LoadImage('e.png')
E_ratio = float(E.width)/E.height
Y = cv.LoadImage('y.png')
Y_ratio = float(Y.width)/Y.height
EPSILON = 0.1

im = cv.LoadImage(sys.argv[1], cv.CV_LOAD_IMAGE_GRAYSCALE)
storage = cv.CreateMemStorage(0)
seq = cv.FindContours(im, storage, cv.CV_RETR_EXTERNAL, 
        cv.CV_CHAIN_APPROX_SIMPLE)
regions = []
while seq:
    pts = [ pt for pt in seq ]
    x, y = zip(*pts)    
    min_x, min_y = min(x), min(y)
    width, height = max(x) - min_x + 1, max(y) - min_y + 1
    regions.append((min_x, min_y, width, height))
    seq = seq.h_next()

rgb = cv.LoadImage(sys.argv[1], cv.CV_LOAD_IMAGE_COLOR)
for x,y,width,height in regions:
    pt1 = x,y
    pt2 = x+width,y+height
    if abs(float(width)/height - E_ratio) < EPSILON:
        color = (0,255,0,0)
    elif abs(float(width)/height - Y_ratio) < EPSILON:
        color = (255,0,0,0)
    else:
        color = (0,0,255,0)
    cv.Rectangle(rgb, pt1, pt2, color, 2)

cv.ShowImage('rgb', rgb)
cv.WaitKey(0)

e.png:

输入图像描述

y.png:

输入图像描述

good:

输入图像描述

bad:

输入图像描述

在有人问之前,不,我是在试图破解验证码 :) OCR本身并不相关:在我的实际项目中,实际形状并不是字符——我只是懒惰,字符是最容易绘制(并且仍然可以被简单的方法检测到)。


你有没有考虑为高度/宽度比定义一个有效的区间?如果所有形状相互接触的情况下,边界框过宽或过高,那可能是一个线索。 - Jav_Rock
是的,我已经考虑过了。不过还是谢谢你提醒我。 - mpenkov
2个回答

4
由于您的形状可能会因大小和比例而异,因此您应该考虑缩放不变描述符。这样的描述符一堆将非常适合您的应用程序。
在测试模板上处理这些描述符,然后使用某种简单分类来提取它们。对于您展示的简单形状,这应该会给出相当好的结果。
我过去使用过 Zernike 和 Hu 矩,后者是最著名的。你可以在这里找到一个实现的例子:http://www.lengrand.fr/2011/11/classification-hu-and-zernike-moments-matlab/
另外:鉴于您的问题,您应该看一下 OCR 技术(光学字符识别):http://en.wikipedia.org/wiki/Optical_character_recognition
希望这有所帮助。
Julien

感谢您的评论。您能为每个轮廓计算矩吗?如果可以,那么如何解决合并形状的问题?提取出来的矩实际上并不会与训练形状的矩匹配,对吗?此外,OCR本身在这里并不是真正相关的:我的实际项目中的实际形状并不是字符-我只是懒惰,字符是最容易绘制(并且仍然可以通过简单的方法检测到)。由于您可能不是第一个也不是最后一个在看到问题时考虑OCR的人,因此我稍微添加了一些内容。 - mpenkov
是的。相关性方法的问题在于我不知道图像的确切大小。我可以尝试不同的模板大小,但这对我来说真的不够好——我需要知道形状的确切大小。 - mpenkov
有什么新闻吗?形状合并是计算机视觉中众所周知的问题之一 :) - jlengrand
我最终根据我对现有形状和其他图像特征的了解寻找最佳位置来分割CC。这是一个非常特定的算法,我并不完全满意,但它似乎暂时有效。 - mpenkov

2

你尝试过使用CCH作为描述符进行Chamfer匹配或轮廓匹配(对应)吗?

Chamfer匹配是使用目标图像和模板轮廓的距离变换。虽然不完全具有尺度不变性,但速度快。

后者比较慢,因为二分匹配问题的复杂度至少为二次方。另一方面,这种方法对于尺度、旋转和可能的局部扭曲(对于近似匹配而言)是不变的,这对于上述糟糕的示例来说非常好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接