Red*_*eda 3 ocr android opencv tesseract opencv4android
我有点被这个问题困住了,我知道关于堆栈溢出有很多问题,但就我而言。什么都没有给出预期的结果。
上下文:
正在使用 Android OpenCV 和 Tesseract,因此我可以读取护照中的 MRZ 区域。当相机启动时,我将输入帧传递给 AsyncTask,处理帧,成功提取 MRZ 区域,我将提取的 MRZ 区域传递给函数 prepareForOCR(inputImage),该函数将 MRZ 区域作为灰色 Mat 并输出我将传递给 Tesseract 的带有阈值图像的位图。
问题:
问题是在对图像进行阈值处理时,我使用了 blockSize = 13 和 C = 15 的自适应阈值处理,但根据图像的照明和获取帧的一般条件,给出的结果并不总是相同。
我尝试过的:
首先,我将图像大小调整为特定大小 (871,108),因此输入图像始终相同且不依赖于使用的手机。调整大小后,我尝试使用不同的 BlockSize 和 C 值
//toOcr contains the extracted MRZ area
Bitmap toOCRBitmap = Bitmap.createBitmap(bitmap);
Mat inputFrame = new Mat();
Mat toOcr = new Mat();
Utils.bitmapToMat(toOCRBitmap, inputFrame);
Imgproc.cvtColor(inputFrame, inputFrame, Imgproc.COLOR_BGR2GRAY);
TesseractResult lastResult = null;
for (int B = 11; B < 70; B++) {
for (int C = 11; C < 70; C++){
if (IsPrime(B) && IsPrime(C)){
Imgproc.adaptiveThreshold(inputFrame, toOcr, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, B ,C);
Bitmap toOcrBitmap = OpenCVHelper.getBitmap(toOcr);
TesseractResult result = TesseractInstance.extractFrame(toOcrBitmap, "ocrba");
if (result.getMeanConfidence()> 70) {
if (MrzParser.tryParse(result.getText())){
Log.d("Main2Activity", "Best result with " + B + " : " + C);
return result;
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用下面的代码,阈值结果图像是黑白图像,其置信度大于 70,出于隐私原因,我无法真正发布整个图像,但这里有一个剪裁的图像和一个虚拟密码。
使用 MrzParser.tryParse 函数,该函数添加了对 MRZ 内字符位置及其有效性的检查,能够纠正一些出现的情况,例如名称包含 8 而不是 B,并获得良好的结果,但需要很多时间,这是正常,因为我在循环中对近 255 个图像进行了阈值处理,并添加了 Tesseract 调用。
我已经尝试获取出现次数最多的 C 和 B 值列表,但结果不同。
问题:
有没有办法定义一个 C 和 blocksize 值,以便它总是给出相同的结果,也许添加更多的 OpenCV 调用所以输入图像像增加对比度等等,我在网上搜索了 2 个星期现在我找不到一个可行的解决方案,这是唯一能够提供准确结果的解决方案
您可以使用聚类算法根据颜色对像素进行聚类。字符是黑暗,没有在机读区区域对比度好,所以聚类方法,将最有可能给你一个很好的分割,如果你将它应用到MRZ区域。
在这里,我使用从互联网上可以找到的示例图像中获得的 MRZ 区域来演示它。
我使用彩色图像,应用一些平滑处理,转换为Lab颜色空间,然后使用 kmeans (k=2) 对 a、b 通道数据进行聚类。代码在中,python但您可以轻松地将其调整为java. 由于 kmeans 算法的随机特性,分段字符将具有标签 0 或 1。您可以通过检查轻松将其分类cluster centers。与字符对应的簇中心应该dark在您使用的颜色空间中有一个值。我只是在这里使用了Lab色彩空间。您可以使用RGB、HSV甚至GRAY,看看哪个更适合您。
像这样分割后,我认为您甚至可以使用字符笔画宽度的属性找到自适应阈值的 B 和 C 的良好值(如果您认为自适应阈值提供更好的质量输出)。
import cv2
import numpy as np
im = cv2.imread('mrz1.png')
# convert to Lab
lab = cv2.cvtColor(cv2.GaussianBlur(im, (3, 3), 1), cv2.COLOR_BGR2Lab)
im32f = np.array(im[:, :, 1:3], dtype=np.float32)
k = 2 # 2 clusters
term_crit = (cv2.TERM_CRITERIA_EPS, 30, 0.1)
ret, labels, centers = cv2.kmeans(im32f.reshape([im.shape[0]*im.shape[1], -1]),
k, None, term_crit, 10, 0)
# segmented image
labels = labels.reshape([im.shape[0], im.shape[1]]) * 255
Run Code Online (Sandbox Code Playgroud)
一些结果: