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

标签 java opencv tesseract tess4j automatic-license-plate-recognition

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

我的步骤:

1)源图片

True Image

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 步,检测板区域(现在可能甚至没有去偏移)。

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

plate region

然后我做了 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 文件夹放入您的项目文件夹中)

最佳答案

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

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

    Sobel(灰色, dst, -1, 1, 0)

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

a) 第 5 步后的结果

Result after Step 5

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

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

enter image description here

编辑

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

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

边缘密度 = 矩形中白色像素的数量/总数量。矩形中的像素数

  1. 选择边缘密度阈值。

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

关于java - 在进行字符识别(tesseract)之前使用 OpenCV 进行图像预处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37302098/

相关文章:

Java eDirectory 使用电子邮件获取用户数

java - Jenkins GitPlugin - 如何找出预构建 merge 失败的原因?

java - 如何获取 java 反射方法对象的 `signature` 字段

java - 在 Java 中将 BufferedImage 转换为 Mat (OpenCV)

android - android中最好的OCR(光学字符识别)示例

concurrency - Tesseract(OCR 引擎)是可重入的吗?

java - Spring Boot Hibernate 没有事务正在进行

arrays - 为什么 emgu 图像具有包含额外高度元素的数组?

opengl - 在 opengl 纹理中加载带有 alpha channel 的 opencv::mat 图像

c++ - 在启用 OpenCL 选项的情况下使用 Tesseract 时出错