在 Android 上使用 OpenCV 提高 Tesseract 性能
Posted
技术标签:
【中文标题】在 Android 上使用 OpenCV 提高 Tesseract 性能【英文标题】:improve Tesseract performance with OpenCV on Android 【发布时间】:2012-09-23 23:26:58 【问题描述】:我正在开发一个使用实时 OCR 的 android 应用程序。我使用 OpenCV 和 Tesseract 库。但性能很差,即使在我的 Galaxy SIII 上也是如此。有什么方法可以提高性能?这是我的代码:
Mat mGray = new Mat();
capture.retrieve(mGray);
Bitmap bmp = Bitmap.createBitmap(mGray.cols(), mGray.rows(), Bitmap.Config.ARGB_8888);
tessBaseApi.setImage(bmp);
String recognizedText = tessBaseApi.getUTF8Text();
Log.i("Reg", recognizedText);
将位图传递给 Tesseract API 会降低 tesseract OCR 的速度吗?在传递给 Tesseract API 之前我应该执行哪些预处理?
【问题讨论】:
你说的是速度还是识别准确率? 我正在考虑速度,它很慢。 嘿@QuiLlHoN 你有没有找到解决如此缓慢性能的任何解决方案?我遇到了同样的问题:/ 【参考方案1】:要尝试的一件事是使用自适应阈值(OpenCV 中的adaptiveThreshold)对图像进行二值化。
【讨论】:
Tesseract 已在内部执行此操作。它使用 Otsu 的阈值。 code.google.com/p/tesseract-ocr/source/browse/ccstruct/… Otsu 的方法使用单个全局阈值。如果照明不完全均匀,这与自适应阈值处理效果不一样(参见docs.opencv.org/trunk/doc/py_tutorials/py_imgproc/… 示例) 确实 Otsu 并没有那么好,但它仍然非常快。因此,虽然这可能会解决精度问题,但不会对性能产生很大影响。【参考方案2】:您可以让 Tesseract 只执行第 1 次识别,这样它就会跳过第 2 到第 9 次, 当它调用recog_all_words() 时。
更改baseapi.cpp中的以下行 并重建您的 Tesseract 库项目:
if (tesseract_->recog_all_words(page_res_, monitor, NULL, NULL, 0))
改成:
if (tesseract_->recog_all_words(page_res_, monitor, NULL, NULL, 1))
【讨论】:
我编辑了代码并重建了库。但是速度还是很慢。【参考方案3】:一些可能使它更快的事情是:
在 createBitmap 之前,从 mGray 中选择文本所在的较小区域 - 因此后面的较重的方法会处理较小的图像。 将 Bitmap.Config.ARGB_8888 更改为 Bitmap.Config.RGB_565 - 您的图像是灰度图像,不需要 ARGB 位图。【讨论】:
TessBaseAPI 只接受 ARGB_8888 图像。有没有找到文本区域的算法?谢谢。【参考方案4】:使用多线程,但请注意为 TessBaseAPI 的每个线程创建一个实例。不要在不同的线程之间共享它们。创建 N 个线程(N >= 核心数),java 将确保您至少加速核心数倍。
我所做的是创建 N 个线程,它们在自己的上下文中(在 run 方法中)创建 TessBaseAPI 对象,并在循环中等待 OCR 请求直到被中断。
...
...
@Override
public void run()
TessBaseAPI tessBaseApi = new TessBaseAPI();
tessBaseApi.init(Ocrrrer.DATA_PATH, "eng");
setTessVariable(tessBaseApi, "load_system_dawg", "0");
setTessVariable(tessBaseApi, "load_freq_dawg", "0");
setTessVariable(tessBaseApi, "load_unambig_dawg", "0");
setTessVariable(tessBaseApi, "load_punc_dawg", "0");
setTessVariable(tessBaseApi, "load_number_dawg", "0");
setTessVariable(tessBaseApi, "load_fixed_length_dawgs", "0");
setTessVariable(tessBaseApi, "load_bigram_dawg", "0");
setTessVariable(tessBaseApi, "wordrec_enable_assoc", "0");
setTessVariable(tessBaseApi, "tessedit_enable_bigram_correction", "0");
setTessVariable(tessBaseApi, "assume_fixed_pitch_char_segment", "1");
setTessVariable(tessBaseApi, TessBaseAPI.VAR_CHAR_WHITELIST, "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ<");
Log.d(TAG, "Training file loaded");
while (!interrupted())
reentrantLock.lock();
try
Log.d(TAG, this.getName() + " wait for OCR");
jobToDo.await();
Log.d(TAG, this.getName() + " input arrived. Do OCR");
this.ocrResult = doOcr(tessBaseApi);
ocrDone.signalAll();
catch (InterruptedException e)
return;
finally
try
reentrantLock.unlock();
catch (Exception ex)
...
...
您可以看到 tessBaseApi 对象是 run 方法的本地对象,因此绝对不共享。
【讨论】:
以上是关于在 Android 上使用 OpenCV 提高 Tesseract 性能的主要内容,如果未能解决你的问题,请参考以下文章