【发布时间】:2012-02-05 19:48:14
【问题描述】:
我正在尝试使用 OpenCV 在图像中查找形状。我知道我想要匹配的形状(有些形状我不知道,但我不需要找到它们)和它们的方向。我不知道它们的大小(比例)和位置。
我目前的做法:
- 检测轮廓
- 对于每个轮廓,计算最大边界框
- 将每个边界框分别匹配到已知形状之一。在我的实际项目中,我将区域缩放到模板大小并计算 Sobel 梯度的差异,但对于这个演示,我只使用纵横比。
这种方法失败的地方是形状接触的地方。轮廓检测将两个相邻的形状作为单个轮廓(单个边界框)。匹配步骤显然会失败。
有没有办法修改我的方法来分别处理相邻的形状?另外,有没有更好的方法来执行第 3 步?
例如:(Es 为绿色,Ys 为蓝色)
失败案例:(红色为未知形状)
源代码:
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:
好:
不好:
在任何人问之前,不,我不是试图破解验证码 :) OCR 本身在这里并不真正相关:我的真实项目中的实际形状不是字符 -我只是懒惰,字符是最容易绘制的东西(并且仍然被琐碎的方法检测到)。
【问题讨论】:
-
您是否考虑过为比率高度/宽度定义一个有效区间。如果形状相互接触的所有情况都导致边界框太宽或太高,那么这可能是一个线索。
-
是的,我已经想到了。不过,谢谢你提到它。