使用Tesseract识别车牌

39

我正在开发一款可以识别车牌(ANPR)的应用程序。第一步是从图像中提取车牌。我使用OpenCV根据宽高比来检测车牌,效果还不错:

extracting license plates

extracting license plates

但是,正如你所看到的,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来改进一些东西?


我会尝试将车牌变形成矩形,即进行图像处理,使其成为与图片边缘平行的矩形。许多OCR工具在字符倾斜时会出现问题。 - FrankPl
我已经使用了这个教程:http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/。虽然上面的图片没有展示结果,但这并没有帮助... - unicorn80
请问你能分享一下基于宽高比例检测车牌的OpenCV代码吗?我可以帮你处理Tesseract OCR部分,但对OpenCV编程一窍不通。 - valentt
1
为什么图像上的指示器可以正确显示区域,但你只能得到一个包含边界框的结果?让那些蓝线沿着板块边缘对齐应该总是给你正确的剪切结果。 - Rekin
它是如何运作的?好奇看看你的解决方案是什么! - Roelant
5个回答

58

这两件事将完全解决这个问题:

  1. 从图像中删除所有非文本内容。您需要使用一些计算机视觉技术来找到车牌区域(例如通过颜色等),然后遮盖掉所有的背景。您希望tesseract的输入为黑白色,其中文本为黑色,其他所有都是白色。

  2. 消除偏斜(如FrankPI所述)。 tesseract实际上应该可以处理偏斜(请参见R. Smith的“ Tesseract OCR Engine”概述),但另一方面它不总是有效,特别是如果您只有一行而不是几段落。因此,如果您可以可靠地这样做,首先手动消除偏斜总是很好的。您可能已经知道了第1步中车牌的边界梯形的确切形状,因此这应该不太难。在消除偏斜的过程中,您还可以消除透视:所有车牌(通常)具有相同的字体,如果您将它们缩放到相同的(无透视)形状,则字母形状将完全相同,这有助于文本识别。

以下是一些进一步的指导...

不要一开始就尝试编写代码:先拍一个非常容易识别(即:正前方拍摄,没有透视效果)的车牌照片,在Photoshop(或Gimp)中进行编辑,然后通过命令行运行tesseract。以不同方式进行编辑,直到成功为止。例如:按颜色选择(或漫水选择字母形状),填充黑色,反选,填充白色,透视变换使车牌的角落成为一个矩形等。拍摄一堆照片,有些较难(也许从奇怪的角度等)。对所有照片都这样做。一旦完全成功,考虑如何制作一个与你在Photoshop中所做的相同的CV算法 :)

P.S. 此外,如果可能的话,最好从高分辨率图像开始。你的示例中的文本大约是14个像素高。tesseract在300 dpi下使用12点字体效果很好,这大约是50个像素高,并且在600 dpi下效果更好。尽量使字母大小至少为50,最好为100个像素。

P.P.S. 你是否正在进行训练tesseract?我认为你需要这样做,因为这里的字体不同,可能会成为一个问题。你可能还需要一些方法来识别(并且不惩罚)破折号,在你的文本中这将非常常见,看起来在第二个例子中“T-”被识别为H。


临时培训显然是一个好建议,它甚至可以“学习”图像默认值的一部分(倾斜...)。 - sansuiso
谢谢。我已经完成了步骤1和2(虽然在我的示例中没有显示)。我使用了这个教程:http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/我用字体训练了Tesseract,但是效果并没有变得更好。 - unicorn80
@inversivemedia:你能发布一些在输入到tesseract之前的图像示例吗?另外,命令行tesseract给出了什么结果?(你用了哪些选项来运行它?)我曾经使用过经过训练的tesseract在同一字体下的大量文本上取得了极好的结果(字符准确率为99.9%),所以我对你遇到问题感到惊讶。 - Alex I
非常好的,全面性的回答。 - Christian Ternus
@AlexI,可以请您看一下这里关于Tesseract和OpenCV的问题:https://github.com/yardstick17吗? - Istiaque Ahmed

13

我对tesseract并不是很了解,但是我有一些关于OCR的信息。下面就让我们来看看。

  • 在OCR任务中,你需要确保你的训练数据具有与你尝试识别的字体相同的字体,或者如果你正在尝试识别多种字体,则确保你的训练数据中包含这些字体以获得最佳性能。
  • 据我所知,Tesseract有几种不同的OCR应用方式:一种是给出一个图像,其中包含多个字母,并让Tesseract进行分割。另一种是将分割后的字母提供给Tesseract,并期望它仅识别字母。也许你可以尝试更改你正在使用的方式。
  • 如果你要自己训练识别器,请确保你的训练数据中每个字母的数量足够且相等。

希望这对你有所帮助。


9
我一直在开发一个iOS应用程序,如果您想要改善结果,您应该训练Tesseract OCR,这对我来说提高了90%的效果。在进行训练之前,OCR的结果相当糟糕。
因此,我以前使用过gist来训练带有车牌字体的Tesseract ORC。
如果您感兴趣,我几周前在github上开源了这个项目。

请问您能否在这里查看一个与Tesseract和OpenCV相关的问题:https://dev59.com/ZGAKtIcB2Jgan1zneSex? - Istiaque Ahmed

2
现在,车牌可以通过mlmodel轻松识别。我已经创建了核心模型,您可以在这里找到它。您只需要通过视觉框架将28*28分辨率的字符分割,并像下面所示将此图像发送到VNImageRequestHandler-
let handler = VNImageRequestHandler(cgImage: imageUI.cgImage!, options: [:])

你可以使用我的核心ML模型来获得所需的结果。请使用此链接以便更好地理解,但是请使用我的模型以获得更好的车牌识别结果。我还为车牌识别创建了mlmodel

2
这是一个实际的例子,我尝试从我的旧电表中使用OCR。我想使用你的OpenCV代码,让OpenCV自动裁剪图像,然后我将使用图像清理脚本。
  • 第一张图片是原始图像(裁剪的电表数字)
  • 第二张图片是在GIMP中稍微清理过的图像,在tesseract中大约有50%的OCR准确率
  • 第三张图片是完全清理的图像 - 100%的OCR识别率,无需任何训练!

enter image description here enter image description here enter image description here


你用GIMP清理了图片吗?我需要一种使用移动设备(OpenCV / iOS)来清理图像的方法。 - unicorn80
这次清理工作是在GIMP中手动完成的,这是最快的方式,可以看到如果我提供干净的图像给tesseract处理,它可以有多好。现在需要更多的工作来使用imagemagic和脚本使图像变得干净。我还将尝试Scan Tailor软件包,因为它具有一些清理图像的绝佳选项。 - valentt
@valentt:你能分享一下使用OpenCV清理图像的代码吗? - Parth Doshi
@ParthDoshi 图像清理是手动完成的,仅用于可行性测试...我们没有继续进行该项目。 - valentt

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