Tess-Two(Android 中的 Tesseract OCR)显示非常不准确的结果
Posted
技术标签:
【中文标题】Tess-Two(Android 中的 Tesseract OCR)显示非常不准确的结果【英文标题】:Tess-Two (Tesseract OCR in Android) shows very inaccurate results 【发布时间】:2017-03-23 02:08:45 【问题描述】:我使用以下函数使用 Tesseract OCR 的 android fork Tess-Two 执行离线 OCR:
private String startOCR(Uri imgUri)
try
ExifInterface exif = new ExifInterface(imgUri.getPath());
int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int rotate = 0;
switch(exifOrientation)
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
Log.d(TAG, "Rotation: " + rotate);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4; // 1 - means max size. 4 - means maxsize/4 size. Don't use value <4, because you need more memory in the heap to store your data.
// set to 300 dpi
options.inTargetDensity = 300;
Bitmap bitmap = BitmapFactory.decodeFile(imgUri.getPath(), options);
// Change Orientation via EXIF
if (rotate != 0)
// Getting width & height of the given image.
int w = bitmap.getWidth();
int h = bitmap.getHeight();
// Setting pre rotate
Matrix mtx = new Matrix();
mtx.preRotate(rotate);
// Rotating Bitmap
bitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, false);
// To Grayscale
bitmap = toGrayscale(bitmap);
final Bitmap b = bitmap;
final ImageView ivResult = (ImageView)findViewById(R.id.ivResult);
if(ivResult != null)
runOnUiThread(new Runnable()
@Override
public void run()
ivResult.setImageBitmap(b);
);
return extractText(bitmap);
catch (Exception e)
Log.e(TAG, e.getMessage());
return "";
这里是extractText()
方法:
private String extractText(Bitmap bitmap)
//Log.d(TAG, "extractText");
try
tessBaseApi = new TessBaseAPI();
catch (Exception e)
Log.e(TAG, e.getMessage());
if (tessBaseApi == null)
Log.e(TAG, "TessBaseAPI is null. TessFactory not returning tess object.");
tessBaseApi.init(DATA_PATH, lang);
//EXTRA SETTINGS
tessBaseApi.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "abcdefghijklmnopqrstuvwxyz1234567890',.?;/ ");
Log.d(TAG, "Training file loaded");
tessBaseApi.setDebug(true);
tessBaseApi.setPageSegMode(TessBaseAPI.PageSegMode.PSM_AUTO_OSD);
tessBaseApi.setImage(bitmap);
String extractedText = "empty result";
try
extractedText = tessBaseApi.getUTF8Text();
catch (Exception e)
Log.e(TAG, "Error in recognizing text.");
tessBaseApi.end();
return extractedText;
extractText()
返回的值如下截图所示:
精度超低,尽管我在执行 OCR 之前将图像灰度和放大到 300 dpi。我怎样才能改善结果?训练出来的数据是不是不够好?
【问题讨论】:
【参考方案1】:我做了一些测试,但是,我有一些观点和结论可以改善你的结果。
-
尝试在您的 VAR_WHITE_CHARLIST 变量参数中传递小写和大写字母:
查看我的输入结果:
a) 仅小写:
参数:
baseApi.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "abcdefghijklmnopqrstuvwxyz1234567890',.?;/ ");
结果:
05 atenienses nnito, hdeleto e laicao, os principais acusadores de gocrates, nao defendiam apenas que o filosofo corrompia a juventude; eles lutavam tama bern pelas virtudes da tradigao pointica vinculada a 里奥内罗。 nristofanes, um dos responsaveis, segundo socrates, dos 先入为主的反对 o filosofo,时代 outro grande defensor dessa 美德。
socrates, de certa forma, estava em guerra com a tradieao pointica 格雷加0 meodo de socrates era o opposto a narrativa epica de 特洛内罗。 sua dialetica nao tinha nada de semideuses 玉米 superpoderes 6
b) 大写和小写字母:
参数:
baseApi.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ1234567890',.?;/ ");
结果:
Os atenienenses Anito, Meleto e Licao, os principais acusadores de 苏格拉底,nao defendiam apenas que o filosofo corrompia a juventude; eles lutavam tama bern pelas virtudes da tradigao pointica vinculada a 荷马。 Aristofanes, um dos responsaveis, segundo socrates, dos 先入为主的反对 o filosofo,时代 outro grande defensor dessa 美德。
socrates, de certa forma, estava em guerra com a tradieao pointica 格雷加O metodo de socrates era o Oposto a narrativa epica de Homero。 Sua dialetica nao tinha nada de semideuses corn superpoderes 6
PS:我已经使用葡萄牙语运行了这个示例,检查一些需要不同字符的单词,例如:'é ó ç' 它不起作用,因为它没有作为字符传递到白名单中。
我也试过用你的图跑,结果有改善(没那么多):
字体 20;哪个 polrlrcran 已经捕获了 Ihe 曲线,总结了一个不断增长的 情绪。在一个可怕的演讲中? “你们的钢铁工业已经死了。死了 穆农。你的煤 yum mono 大大对铁 Vbur Ilk Mary 是和。 ○ 你的羊毛产业是为什么。您的经典 Wilding 先生的行业。发送邮件
所以我检查了 tesseract 如何二值化图像:
您的图像有很多噪音,然后 api 尝试对您的图像进行二值化,这使您的图片的很大一部分难以辨认。我建议您再次尝试运行,但不要通过灰度,并尝试研究如何减少图像中的噪点。
为了帮助您完成调试任务,您可以保存保留的图像:
WriteFile.writeBitmap(baseApi.getThresholdedImage())
希望对你有用!感谢您分享您的问题!
阿布拉索斯!
【讨论】:
感谢您提供如此详细的回答。我想知道训练过的数据是否也不够好。也许数据需要训练更多? 你从哪里得到你的训练数据?我正在使用 tess-data 存储库:github.com/tesseract-ocr/tessdata。我从 swe、por 和 eng 得到的结果对这些数据非常准确。 :) 我在答案中添加了更多考虑因素:为了帮助您完成调试任务,您可以保存保留的图像:WriteFile.writeBitmap(baseApi.getThresholdedImage()); (WriteFile 来自 leptonica lib -> com.googlecode.leptonica.android.WriteFile)【参考方案2】:在这一行 选项.inSampleSize = 4; 将数字从 4 更改为 1 并尝试再次执行 ocr
【讨论】:
以上是关于Tess-Two(Android 中的 Tesseract OCR)显示非常不准确的结果的主要内容,如果未能解决你的问题,请参考以下文章
Android Tess-Two OCR 不可映射字符 'fi'
Android OCR 仅使用流行的 tessercat fork tess-two 检测数字