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

2022-09-04 02:46:09

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

我的步骤:

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”(几乎为真)

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

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


答案 1

以下是我建议您应该如何执行此任务。

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

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

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

a) 步骤 5 后的结果

Result after Step 5

b) 步骤 7 之后的结果。绿色的都是minAreaRects,红色的是那些满足以下条件的:宽高比范围(2,12)和面积范围(300,10000)

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

enter image description here

编辑

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

  1. 将Canny Edge检测器直接应用于输入图像。让cannyED图像成为Ic
  2. 将 Sobel 滤波器和 Ic 的结果相乘。基本上,拍摄Sobel和Canny图像的AND。
  3. 高斯模糊使用大滤镜模糊生成的图像。我用了21x21。
  4. 使用 OTSU 的方法阈值生成的图像。您将获得一个二进制图像
  5. 对于每个红色矩形,旋转此矩形内的部分(在二进制图像中)以使其直立。遍历矩形的像素并计算白色像素。(如何旋转?)

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

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

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


答案 2

实际上,OpenCV已经专门为俄罗斯车牌预先训练了模型:haarcascade_russian_plate_number

此外,还有针对俄罗斯车牌的开源ANPR项目:plate_recognition。它不是使用tesseract,但它有相当好的预训练神经网络。


推荐