我试图在图像中找到文本的边界框,目前正在使用这种方法:
// calculate the local variances of the grayscale image
Mat t_mean, t_mean_2;
Mat grayF;
outImg_gray.convertTo(grayF, CV_32F);
int winSize = 35;
blur(grayF, t_mean, cv::Size(winSize,winSize));
blur(grayF.mul(grayF), t_mean_2, cv::Size(winSize,winSize));
Mat varMat = t_mean_2 - t_mean.mul(t_mean);
varMat.convertTo(varMat, CV_8U);
// threshold the high variance regions
Mat varMatRegions = varMat > 100;
给出这样的图像时:
然后,当我显示 varMatRegions
时,我得到这个图像:
正如你所看到的那样,它将左侧的文本块与卡片的 Headers 结合起来,对于大多数卡片而言,这种方法效果很好,但在较繁忙的卡片上它可能会导致问题 .
这些轮廓连接不好的原因是它使得轮廓的边界框几乎占据了整个卡片 .
任何人都可以建议一种不同的方式来查找文本以确保正确检测文本吗?
200 points to whoever can find the text in the card above the these two.
7 回答
您可以通过查找近边元素(灵感来自LPD)来检测文本:
用法:
结果:
一个 . element = getStructuringElement(cv :: MORPH_RECT,cv :: Size(17,3));
湾element = getStructuringElement(cv :: MORPH_RECT,cv :: Size(30,30));
对于所提到的其他图像,结果类似 .
我在下面的程序中使用了基于渐变的方法 . 添加了生成的图像 . 请注意,我正在使用图像的缩小版本进行处理 .
c版
python版本
这是我用来检测文本块的另一种方法:
将图像转换为灰度
应用threshold(简单二进制阈值,精选值为150作为阈值)
应用dilation来加粗图像中的线条,从而产生更紧凑的对象和更少的空白碎片 . 使用较高的迭代次数值,因此扩张非常繁重(13次迭代,也可以精心挑选以获得最佳结果) .
使用opencv findContours函数识别结果图像中对象的轮廓 .
画了一个bounding box(矩形)包围每个轮廓对象 - 每个对象构成一个文本块 .
可选地丢弃不太可能是您要搜索的对象的区域(例如文本块),因为上面的算法也可以找到相交或嵌套的对象(如第一张卡的整个顶部区域),其中一些可以对你的目的无趣 .
下面是使用pyopencv在python中编写的代码,它应该很容易移植到C语言 .
原始图片是您帖子中的第一张图片 .
在预处理(灰度,阈值和扩展 - 所以在第3步之后)后,图像看起来像这样:
下面是结果图像(最后一行中的“contoured.jpg”);图像中对象的最终边界框如下所示:
您可以看到左侧的文本块被检测为一个单独的块,与周围环境分隔 .
使用具有相同参数的相同脚本(除了为第二个图像更改的阈值类型,如下所述),以下是其他2张卡的结果:
调整参数
参数(阈值,扩张参数)针对该图像和该任务(查找文本块)进行了优化,并且如果需要,可以针对其他卡片图像或要找到的其他类型的对象进行调整 .
对于阈值处理(步骤2),我使用黑色阈值 . 对于文本比背景浅的图像(例如帖子中的第二个图像),应使用白色阈值,因此请使用
cv2.THRESH_BINARY
替换剪贴类型 . 对于第二个图像,我还使用略高的阈值值(180) . 改变阈值的参数和扩张的迭代次数将导致在限定图像中的对象时的不同灵敏度 .Finding other object types:
例如,在第一张图像中将膨胀减少到5次迭代,可以让我们对图像中的对象进行更精细的定界,粗略地找到图像中的所有单词(而不是文本块):
知道一个单词的粗略大小,在这里我丢弃了太小(宽度或高度低于20像素)或太大(超过100像素宽度或高度)的区域,以忽略不太可能是单词的对象,以获得结果上面的图片 .
@dhanushka的方法显示了最大的希望,但我想在Python中玩游戏,所以继续并将它翻译为有趣的:
现在显示图像:
不是最恐怖的剧本,但我试图尽可能地与原始的C代码相似读者可以关注 .
它的工作原理几乎和原版一样好 . 我很乐意阅读建议如何改进/修复它以完全类似于原始结果 .
您可以尝试由Chucai Yi和Yingli Tian开发的this method .
他们还共享一个软件(基于Opencv-1.0,它应该在Windows平台下运行 . ),你可以使用(虽然没有可用的源代码) . 它将生成图像中的所有文本边界框(以彩色阴影显示) . 通过应用于您的样本图像,您将获得以下结果:
注意:为了使结果更加健壮,您可以进一步将相邻的框合并在一起 .
Update: 如果您的最终目标是识别图像中的文本,则可以进一步查看gttext,这是一个OCR免费软件和带有文本的彩色图像的地面分析工具 . 源代码也可用 .
有了这个,您可以获得如下认可的文本:
以上代码JAVA版本:谢谢@William
并在实践中使用此代码:
@ dhanushka解决方案的Python实现: