在进行字符识别(tesseract)之前使用 OpenCV 进行图像预处理

Image preprocessing with OpenCV before doing character recognition (tesseract)

我正在尝试开发用于车牌识别的简单 PC 应用程序 (Java + OpenCV + Tess4j)。图像不是很好(进一步它们会很好)。我想为 tesseract 预处理图像,但我卡在车牌检测(矩形检测)上。

我的步数:

1) 源图片

Mat img = new Mat();
img = Imgcodecs.imread("sample_photo.jpg"); 
Imgcodecs.imwrite("preprocess/True_Image.png", img);

2) 灰度

Mat imgGray = new Mat();
Imgproc.cvtColor(img, imgGray, Imgproc.COLOR_BGR2GRAY);
Imgcodecs.imwrite("preprocess/Gray.png", imgGray);

3) 高斯模糊

Mat imgGaussianBlur = new Mat(); 
Imgproc.GaussianBlur(imgGray,imgGaussianBlur,new Size(3, 3),0);
Imgcodecs.imwrite("preprocess/gaussian_blur.png", imgGaussianBlur);  

4) 自适应阈值

Mat imgAdaptiveThreshold = new Mat();
Imgproc.adaptiveThreshold(imgGaussianBlur, imgAdaptiveThreshold, 255, CV_ADAPTIVE_THRESH_MEAN_C ,CV_THRESH_BINARY, 99, 4);
Imgcodecs.imwrite("preprocess/adaptive_threshold.png", imgAdaptiveThreshold);

这里应该是第5步,检测板块区域(现在可能连deskewing都没有)。

我使用 Paint 从图像(第 4 步之后)裁剪了所需的区域,并得到:

然后我做了 OCR(通过 tesseract,tess4j):

File imageFile = new File("preprocess/adaptive_threshold_AFTER_PAINT.png");
ITesseract instance = new Tesseract();
instance.setLanguage("eng");
instance.setTessVariable("tessedit_char_whitelist", "acekopxyABCEHKMOPTXY0123456789");
String result = instance.doOCR(imageFile); 
System.out.println(result);

得到(足够好?)结果 - "Y841ox EH"(几乎正确)

如何在第 4 步后检测和裁剪板区域?我必须在 1-4 个步骤中进行一些更改(改进)吗?希望看到一些通过 Java + OpenCV(不是 JavaCV)实现的示例。
提前致谢。

编辑(感谢@Abdul Fatir 的回答) 好吧,我为对此问题感兴趣的人提供了工作(至少对我而言)代码示例 (Netbeans+Java+OpenCV+Tess4j)。代码不是最好的,但我只是为了学习而制作它。
http://pastebin.com/H46wuXWn(不要忘记将 tessdata 文件夹放入您的项目文件夹)

  • 您找到所有连接的组件(白色区域)并确定它们的轮廓。
  • 如果您根据大小(作为图像的一部分)、比例(宽度-高度)和 white/black 比例过滤它们以检索候选车牌。
  • 撤销矩形的变换
  • 拆下螺栓
  • 将图像传入 OCR 引擎。

以下是我建议您执行此任务的方法。

  1. 转换为灰度。
  2. 带 3x3 或 5x5 滤镜的高斯模糊。
  3. 应用 Sobel 过滤器查找垂直边缘。

    Sobel(gray, dst, -1, 1, 0)

  4. 对生成的图像进行阈值处理以获得二值图像。
  5. 使用合适的结构元素应用形态闭运算。
  6. 查找结果图像的轮廓。
  7. 找到每个轮廓的 minAreaRect。 Select 基于纵横比以及最小和最大面积的矩形。
  8. 对于每个选定的轮廓,找出边缘密度。设置边缘密度的阈值并选择超出该阈值的矩形作为可能的板区域。
  9. 此后将剩下几个矩形。您可以根据方向或您认为合适的任何条件过滤它们。
  10. adaptiveThreshold 之后的图像中剪下这些检测到的矩形部分并应用 OCR。

a) 第 5 步后的结果

b) 步骤 7 后的结果。绿色的是所有 minAreaRects,红色的是满足以下条件的那些:纵横比范围 (2,12) & 面积范围 (300,10000)

c) 第 9 步后的结果。Selected 矩形。标准:边缘密度 > 0.5

编辑

对于边缘密度,我在上面的例子中所做的如下。

  1. 将 Canny 边缘检测器直接应用于输入图像。设cannyED图像为Ic.
  2. 将 Sobel 滤波器的结果与 Ic 相乘。基本上,采用 Sobel 和 Canny 图像的 AND。
  3. 高斯模糊使用大过滤器生成的图像。我用了 21x21.
  4. 使用 OTSU 的方法对生成的图像进行阈值处理。你会得到一个二值图像
  5. 对于每个红色矩形,旋转该矩形内的部分(在二值图像中)使其直立。遍历矩形的像素并计算白色像素。 ()

边缘密度 = Rectangle/Total 中的白色像素数矩形中的像素数

  1. 选择边缘密度的阈值。

注意:除了执行步骤 1 到 3,您还可以使用步骤 5 中的二值图像来计算边缘密度。

实际上OpenCV有专门针对俄罗斯车牌的预训练模型:haarcascade_russian_plate_number

还有一个用于俄罗斯车牌的开源 ANPR 项目:plate_recognition。它不是使用tesseract,但它有很好的预训练神经网络。