使用 Tesseract 的 Android OCR 应用程序
Posted
技术标签:
【中文标题】使用 Tesseract 的 Android OCR 应用程序【英文标题】:Android OCR App using Tesseract 【发布时间】:2014-02-12 09:53:54 【问题描述】:我正在关注这个网站上提到的教程:
http://gaut.am/making-an-ocr-android-app-using-tesseract/
首先我从 github 导入 Tess-Two: https://github.com/rmtheis/tess-two
并将其链接到我的项目 https://github.com/GautamGupta/Simple-Android-OCR
应用程序编译并运行良好。但是当我点击保存时单击图像后,它会崩溃。
这里是主要活动的来源:
public class SimpleAndroidOCRActivity extends Activity
public static final String PACKAGE_NAME = "com.datumdroid.android.ocr.simple";
public static final String DATA_PATH = Environment
.getExternalStorageDirectory().toString() + "/SimpleAndroidOCR/";
// You should have the trained data file in assets folder
// You can get them at:
// http://code.google.com/p/tesseract-ocr/downloads/list
public static final String lang = "eng";
private static final String TAG = "SimpleAndroidOCR.java";
protected Button _button;
// protected ImageView _image;
protected EditText _field;
protected String _path;
protected boolean _taken;
protected static final String PHOTO_TAKEN = "photo_taken";
@Override
public void onCreate(Bundle savedInstanceState)
String[] paths = new String[] DATA_PATH, DATA_PATH + "tessdata/" ;
for (String path : paths)
File dir = new File(path);
if (!dir.exists())
if (!dir.mkdirs())
Log.v(TAG, "ERROR: Creation of directory " + path + " on sdcard failed");
return;
else
Log.v(TAG, "Created directory " + path + " on sdcard");
// lang.traineddata file with the app (in assets folder)
// You can get them at:
// http://code.google.com/p/tesseract-ocr/downloads/list
// This area needs work and optimization
if (!(new File(DATA_PATH + "tessdata/" + lang + ".traineddata")).exists())
try
AssetManager assetManager = getAssets();
InputStream in = assetManager.open("tessdata/" + lang + ".traineddata");
//GZIPInputStream gin = new GZIPInputStream(in);
OutputStream out = new FileOutputStream(DATA_PATH
+ "tessdata/" + lang + ".traineddata");
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
//while ((lenf = gin.read(buff)) > 0)
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
in.close();
//gin.close();
out.close();
Log.v(TAG, "Copied " + lang + " traineddata");
catch (IOException e)
Log.e(TAG, "Was unable to copy " + lang + " traineddata " + e.toString());
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// _image = (ImageView) findViewById(R.id.image);
_field = (EditText) findViewById(R.id.field);
_button = (Button) findViewById(R.id.button);
_button.setOnClickListener(new ButtonClickHandler());
_path = DATA_PATH + "/ocr.jpg";
public class ButtonClickHandler implements View.OnClickListener
public void onClick(View view)
Log.v(TAG, "Starting Camera app");
startCameraActivity();
// Simple android photo capture:
// http://labs.makemachine.net/2010/03/simple-android-photo-capture/
protected void startCameraActivity()
File file = new File(_path);
Uri outputFileUri = Uri.fromFile(file);
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(intent, 0);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
Log.i(TAG, "resultCode: " + resultCode);
if (resultCode == -1)
onPhotoTaken();
else
Log.v(TAG, "User cancelled");
@Override
protected void onSaveInstanceState(Bundle outState)
outState.putBoolean(SimpleAndroidOCRActivity.PHOTO_TAKEN, _taken);
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
Log.i(TAG, "onRestoreInstanceState()");
if (savedInstanceState.getBoolean(SimpleAndroidOCRActivity.PHOTO_TAKEN))
onPhotoTaken();
protected void onPhotoTaken()
_taken = true;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeFile(_path, options);
try
ExifInterface exif = new ExifInterface(_path);
int exifOrientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
Log.v(TAG, "Orient: " + exifOrientation);
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.v(TAG, "Rotation: " + rotate);
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);
// Convert to ARGB_8888, required by tess
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
catch (IOException e)
Log.e(TAG, "Couldn't correct orientation: " + e.toString());
// _image.setImageBitmap( bitmap );
Log.v(TAG, "Before baseApi");
TessBaseAPI baseApi = new TessBaseAPI();
baseApi.setDebug(true);
baseApi.init(DATA_PATH, lang);
baseApi.setImage(bitmap);
String recognizedText = baseApi.getUTF8Text();
baseApi.end();
// You now have the text in recognizedText var, you can do anything with it.
// We will display a stripped out trimmed alpha-numeric version of it (if lang is eng)
// so that garbage doesn't make it to the display.
Log.v(TAG, "OCRED TEXT: " + recognizedText);
if ( lang.equalsIgnoreCase("eng") )
recognizedText = recognizedText.replaceAll("[^a-zA-Z0-9]+", " ");
recognizedText = recognizedText.trim();
if ( recognizedText.length() != 0 )
_field.setText(_field.getText().toString().length() == 0 ? recognizedText : _field.getText() + " " + recognizedText);
_field.setSelection(_field.getText().toString().length());
// Cycle done.
// www.Gaut.am was here
// Thanks for reading!
而且我知道错误在以下部分接近尾声:
TessBaseAPI baseApi = new TessBaseAPI();
baseApi.setDebug(true);
baseApi.init(DATA_PATH, lang);
baseApi.setImage(bitmap);
String recognizedText = baseApi.getUTF8Text();
baseApi.end();
知道它为什么会崩溃吗?
【问题讨论】:
是否有堆栈跟踪? 没有可使用的 USB。通过蓝牙传输文件并运行它。没有堆栈跟踪。但想通了它的崩溃在哪条线 ***.com/q/601503/544198 是的。处理图像时似乎有一些错误。它可以毫无问题地保存在卡上 崩溃最有可能是调用set Image之后 【参考方案1】:解压你的目标 *.apk 文件,检查是否有一个包含 *.so 文件的libs
文件夹。如果这是你的问题,请查看我之前回答过的this 链接。
【讨论】:
【参考方案2】:您是否使用了正确的 tessdata 文件?如果不这样做。 https://github.com/tesseract-ocr/tesseract/wiki/Data-Files#data-files-for-version-304305
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
将文件保存到目录时可能存在权限问题。
或者检查代码目录的 lib 文件夹,可能是 libtess.so 文件不适用于 x86、x64、mips、armv7 等 CPU 架构的问题。
【讨论】:
【参考方案3】:问题出在你的路径上,你必须下载一种你想从 code.google.com/p/tesseract-ocr/downloads/list download
获得结果的语言(例如:tesseract-ocr-3.02.eng.tar.gz
)解压并找到文件“yourLanguage.traineddata”
(例如:“eng.traineddata”
) 并将这个文件放到你sd卡的存储路径中,然后你就可以把它作为路径获取了
TessBaseAPI mTess = new TessBaseAPI();
String datapath = Environment.getExternalStorageDirectory() + "/tesseract/";
String language = "eng";
File dir = new File(datapath + "tessdata/");
if (!dir.exists())
dir.mkdirs();
mTess.init(datapath, language);
mTess.setImage(yourBitmapImage);
String result = mTess.getUTF8Text();
Toast.makeText(tesswork.this, "Result : " + result, Toast.LENGTH_LONG).show();
【讨论】:
以上是关于使用 Tesseract 的 Android OCR 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
如何通过Tesseract开源OCR引擎创建Android OCR应用
如何在 Android 中使用 OpenCV+Tesseract 进行准确的文本识别?