我正在尝试开发用于车牌识别的简单 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 步,检测板区域(现在可能甚至没有去偏移)。
我使用 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 文件夹放入您的项目文件夹中)
最佳答案
以下是我建议您执行此任务的方法。
- 转换为灰度。
- 使用 3x3 或 5x5 过滤器的高斯模糊。
应用 Sobel 过滤器查找垂直边缘。
Sobel(灰色, dst, -1, 1, 0)
- 对生成的图像进行阈值处理以获得二值图像。
- 使用合适的结构元素应用形态闭运算。
- 找到生成图像的轮廓。
- 找到每个轮廓的
minAreaRect
。根据纵横比以及最小和最大面积选择矩形。 - 对于每个选定的轮廓,找出边缘密度。设置边缘密度阈值,并选择超出该阈值的矩形作为可能的板区域。
- 此后将剩下几个矩形。您可以根据方向或您认为合适的任何标准过滤它们。
- 在
adaptiveThreshold
之后从图像中剪下这些检测到的矩形部分并应用 OCR。
a) 第 5 步后的结果
b) 步骤 7 后的结果。绿色的是所有 minAreaRect
,红色的是满足以下条件的:纵横比范围 (2,12) 和面积范围(300,10000)
c) 第 9 步后的结果。选定的矩形。标准:边缘密度 > 0.5
编辑
对于边缘密度,我在上面的例子中所做的如下。
- 将 Canny 边缘检测器直接应用于输入图像。让 cannyED 图像为 Ic。
- 将 Sobel 滤波器的结果与 Ic 相乘。基本上,采用 Sobel 和 Canny 图像的 AND。
- 使用大过滤器对合成图像进行高斯模糊处理。我用的是 21x21。
- 使用 OTSU 的方法对生成的图像进行阈值处理。你会得到一个二值图像
- 对于每个红色矩形,旋转该矩形内的部分(在二值图像中)使其直立。遍历矩形的像素并计算白色像素。 ( How to rotate? )
边缘密度 = 矩形中白色像素的数量/总数量。矩形中的像素数
- 选择边缘密度阈值。
注意:除了执行步骤 1 到 3,您还可以使用步骤 5 中的二值图像来计算边缘密度。
关于java - 在进行字符识别(tesseract)之前使用 OpenCV 进行图像预处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37302098/