使用 tesseract 识别车牌
Posted
技术标签:
【中文标题】使用 tesseract 识别车牌【英文标题】:Using tesseract to recognize license plates 【发布时间】:2013-10-16 14:41:53 【问题描述】:我正在开发一个可以识别车牌 (ANPR) 的应用。第一步是从图像中提取车牌。我正在使用 OpenCV 根据宽度/高度比检测板块,效果很好:
但如您所见,OCR 结果非常糟糕。
我在我的Objective C
(ios) 环境中使用tesseract
。这些是我在启动引擎时的init
变量:
// init the tesseract engine.
tesseract = new tesseract::TessBaseAPI();
int initRet=tesseract->Init([dataPath cStringUsingEncoding:NSUTF8StringEncoding], [language UTF8String]);
tesseract->SetVariable("tessedit_char_whitelist", "BCDFGHJKLMNPQRSTVWXYZ0123456789-");
tesseract->SetVariable("language_model_penalty_non_freq_dict_word", "1");
tesseract->SetVariable("language_model_penalty_non_dict_word ", "1");
tesseract->SetVariable("load_system_dawg", "0");
如何改进结果?我需要让 OpenCV 做更多的图像处理吗?或者有什么我可以用 tesseract 改进的吗?
【问题讨论】:
我会尝试拉直车牌,即。 e.做一些图像处理,使它们成为一个边平行于图片边的矩形。如果字符倾斜,许多 OCR 工具都会出现问题。 我已经使用了这个教程:felix.abecassis.me/2011/10/opencv-rotation-deskewing。我没有在上面的图片中显示结果,但它没有帮助...... 您能否分享您的基于宽度/高度比检测板的opencv代码?我可以帮助你处理 tesseract OCR 部分,但不知道如何在 opencv 中编程。 为什么图像上的指示器正确显示了该区域,而您从中得到的只是一个包含边界框?沿着板边缘对齐这些蓝线应该可以始终为您提供正确剪辑的结果。 效果如何?很想知道您的解决方案是什么! 【参考方案1】:有两件事可以彻底解决这个问题:
从图像中删除所有非文本的内容。您需要使用一些 CV 来查找板块区域(例如通过颜色等),然后将背景的 all 遮盖掉。您希望 tesseract 的输入是黑白的,其中文本是黑色的,其他一切都是白色的
移除偏斜(如上面 FrankPI 所述)。 tesseract 实际上应该适用于倾斜(参见 R. Smith 的“Tesseract OCR Engine”概述),但另一方面它是doesn't always work,特别是如果您只有一行而不是几段。因此,如果您能可靠地做到这一点,首先手动消除倾斜总是好的。您可能会从步骤 1 中知道板的边界梯形的确切形状,因此这应该不会太难。在消除倾斜的过程中,您还可以消除透视:所有车牌(通常)具有相同的字体,如果将它们缩放到相同(无透视)的形状,字母形状将完全相同,这将有助于文本识别。
一些进一步的指示......
首先不要尝试编写代码:拍摄一张非常容易 OCR(即:从正面,无透视)的盘子图片,在 photoshop(或 gimp)中编辑,然后通过 tesseract 运行命令行。继续以不同的方式进行编辑,直到这有效。例如:按颜色选择(或泛洪选择字母形状),用黑色填充,反转选择,用白色填充,透视变换使板的角变成矩形等。拍一堆照片,一些更难的(可能是奇数)角度等)。对所有人都这样做。一旦这完全起作用,考虑如何制作一个与您在 Photoshop 中做的事情相同的 CV 算法:)
附:此外,如果可能,最好从更高分辨率的图像开始。看起来您示例中的文本大约 14 像素高。 tesseract 适用于 300 dpi 的 12 点文本,大约 50 像素高,在 600 dpi 时效果更好。尽量使您的字母大小至少为 50,最好是 100 像素。
附言你对train tesseract做了什么吗?我认为你必须这样做,这里的字体不同,足以成为一个问题。您可能还需要一些东西来识别(而不是惩罚)在您的文本中很常见的破折号,就像在第二个示例中“T-”被识别为 H.
【讨论】:
Ad hoc 训练显然是一个很好的建议,它甚至可以“学习”图像默认值的一部分(歪斜......)。 谢谢。已经做了第 1 步和第 2 步(尽管在我的示例中没有显示)。我使用了这个教程:felix.abecassis.me/2011/10/opencv-rotation-deskewing我用字体训练了 tesseract,但我并没有变得更好。 @inversivemedia:您能否在将它们提供给 tesseract 之前发布一些图像示例?另外,你从命令行 tesseract 得到什么结果? (以及您使用什么选项来运行它?)。我从经过训练的 tesseract 对大量相同字体的文本中获得了出色的结果(字符准确度为 99.9%),所以我很惊讶您遇到了问题。 很好,全面的答案。 @AlexI,我可以请你看看这里的 Tesseract 和 OpenCV 相关问题:github.com/yardstick17 吗?【参考方案2】:我不太了解tesseract,但我有一些关于OCR的信息。我们开始吧。
在 OCR 任务中,您需要确保您的训练数据与您尝试识别的字体相同。或者,如果您尝试识别多种字体,请确保您的训练数据中包含这些字体以获得最佳性能。 据我所知,tesseract 以几种不同的方式应用 OCR:第一,您提供一张包含多个字母的图像,然后让 tesseract 进行分割。其他的,你给 tesseract 提供分段的字母,只期望它识别字母。也许您可以尝试更改您正在使用的那个。 如果您自己训练识别器,请确保训练数据中每个字母的数量足够且数量相等。希望这会有所帮助。
【讨论】:
【参考方案3】:我一直在开发一个 iOS 应用程序,如果你需要改进结果,你应该训练 tesseract OCR,这对我来说提高了 90%。转之前,OCR 结果很差。
所以,我过去使用这个gist 来训练带有车牌字体的 tesseract ORC。
如果你有兴趣,我几周前在github开源了这个项目
【讨论】:
能否请您在这里查看一个 Tesseract 和 OpenCV 相关问题:***.com/questions/66946835/…?【参考方案4】:这是我在旧功率计中尝试 OCR 的真实示例。我想使用您的 OpenCV 代码,以便 OpenCV 自动裁剪图像,我将执行图像清理脚本。
第一张图片是原始图片(裁剪后的功率计编号) 第二张图片在 GIMP 中经过略微清理,在 tesseract 中的 OCR 准确率约为 50% 第三张图像是完全清洁的图像 - 100% OCR 识别,无需任何培训!【讨论】:
您是否使用 GIMP 清理过图像?我需要一种使用移动设备(opencv/ios)清理图像的方法 这个清理是在 GIMP 中手动完成的,如果我得到干净的图像来处理它,这是查看 tesseract 有多好的最快方法。现在有更多的工作来使用 imagemagic 和脚本使图像干净。我也会尝试 Scan Tailor 包,我发现它有一些清理图像的好选择。 @valentt: 可以分享一下使用opencv清理图片的代码吗? @ParthDoshi 图像清理是手动完成的,只是为了进行可行性测试......我们没有进一步推进该项目。【参考方案5】:现在车牌可以很容易地被 mlmodel 识别。我已经创建了核心模型,您可以在 here 找到它。您只需要通过视觉框架将字符拆分为 28*28 分辨率并将此图像发送到 VNImageRequestHandler,如下所示-
let handler = VNImageRequestHandler(cgImage: imageUI.cgImage!, options: [:])
您将通过使用我的核心 mlmodel 获得所需的结果。使用this 链接以获得更好的说明,但使用我的模型以获得更好的车牌识别结果。我还为车牌识别创建了mlmodel。
【讨论】:
以上是关于使用 tesseract 识别车牌的主要内容,如果未能解决你的问题,请参考以下文章
Python+OpenCV+Tesseract实现OCR字符识别
在进行字符识别之前使用 OpenCV 进行图像预处理(tesseract)