无法显示 OCR 的结果
Unable to display the results of OCR
我有这个 mainActivity java 文件,我想显示 OCR 的结果。
错误:创建目录/storage/emulated/0/TesseractSample/tessdata失败,检查Android清单是否具有写入外部存储的权限。
无法将文件复制到 tessdata java.io.FileNotFoundException:/storage/emulated/0/TesseractSample/tessdata/eng.traineddata:打开失败:ENOENT(没有那个文件或目录)
3.Unable 解码流:java.io.FileNotFoundException:/storage/emulated/0/TesseractSample/imgs/ocr.jpg:打开失败:EACCES(权限被拒绝)
数据路径必须包含子文件夹 tessdata!
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.googlecode.tesseract.android.TessBaseAPI;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
static final int PHOTO_REQUEST_CODE = 1;
private TessBaseAPI tessBaseApi;
TextView textView;
Uri outputFileUri;
private static final String lang = "eng";
String result = "empty";
private static final String DATA_PATH = Environment.getExternalStorageDirectory().toString() + "/TesseractSample/";
private static final String TESSDATA = "tessdata";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button captureImg = (Button) findViewById(R.id.action_btn);
if (captureImg != null) {
captureImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startCameraActivity();
}
});
}
textView = (TextView) findViewById(R.id.textResult);
}
/**
* to get high resolution image from camera
*/
private void startCameraActivity() {
try {
String IMGS_PATH = Environment.getExternalStorageDirectory().toString() + "/TesseractSample/imgs";
prepareDirectory(IMGS_PATH);
String img_path = IMGS_PATH + "/ocr.jpg";
outputFileUri = Uri.fromFile(new File(img_path));
final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, PHOTO_REQUEST_CODE);
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
@Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
//making photo
if (requestCode == PHOTO_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
prepareTesseract();
startOCR(outputFileUri);
} else {
Toast.makeText(this, "ERROR: Image was not obtained.", Toast.LENGTH_SHORT).show();
}
}
/**
* Prepare directory on external storage
*
* @param path
* @throws Exception
*/
private void prepareDirectory(String path) {
File dir = new File(path);
if (!dir.exists()) {
if (!dir.mkdirs()) {
Log.e(TAG, "ERROR: Creation of directory " + path + " failed, check does Android Manifest have permission to write to external storage.");
}
} else {
Log.i(TAG, "Created directory " + path);
}
}
private void prepareTesseract() {
try {
prepareDirectory(DATA_PATH + TESSDATA);
} catch (Exception e) {
e.printStackTrace();
}
copyTessDataFiles(TESSDATA);
}
/**
* Copy tessdata files (located on assets/tessdata) to destination directory
*
* @param path - name of directory with .traineddata files
*/
private void copyTessDataFiles(String path) {
try {
String fileList[] = getAssets().list(path);
for (String fileName : fileList) {
// open file within the assets folder
// if it is not already there copy it to the sdcard
String pathToDataFile = DATA_PATH + path + "/" + fileName;
if (!(new File(pathToDataFile)).exists()) {
InputStream in = getAssets().open(path + "/" + fileName);
OutputStream out = new FileOutputStream(pathToDataFile);
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
Log.d(TAG, "Copied " + fileName + "to tessdata");
}
}
} catch (IOException e) {
Log.e(TAG, "Unable to copy files to tessdata " + e.toString());
}
}
/**
* don't run this code in main thread - it stops UI thread. Create AsyncTask instead.
* https://developer.android.com/reference/android/os/AsyncTask.html
*
* @param imgUri
*/
private void startOCR(Uri imgUri) {
try {
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.
Bitmap bitmap = BitmapFactory.decodeFile(imgUri.getPath(), options);
result = extractText(bitmap);
textView.setText(result);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
private String extractText(Bitmap bitmap) {
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
// //For example if we only want to detect numbers
// tessBaseApi.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "1234567890");
//
// //blackList Example
// tessBaseApi.setVariable(TessBaseAPI.VAR_CHAR_BLACKLIST, "!@#$%^&*()_+=-qwertyuiop[]}{POIU" +
// "YTRWQasdASDfghFGHjklJKLl;L:'\"\|~`xcvXCVbnmBNM,./<>?");
Log.d(TAG, "Training file loaded");
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;
}
}
如果您的目标是 Android SDK 23 或更高版本,除了在 Android 清单文件中请求权限外,您还必须 request permissions from the user at run time。
或者,您可以通过更改 build.gradle 中的 targetSdkVersion
值来定位 SDK 22 或更低版本。
我有这个 mainActivity java 文件,我想显示 OCR 的结果。
错误:创建目录/storage/emulated/0/TesseractSample/tessdata失败,检查Android清单是否具有写入外部存储的权限。
无法将文件复制到 tessdata java.io.FileNotFoundException:/storage/emulated/0/TesseractSample/tessdata/eng.traineddata:打开失败:ENOENT(没有那个文件或目录)
3.Unable 解码流:java.io.FileNotFoundException:/storage/emulated/0/TesseractSample/imgs/ocr.jpg:打开失败:EACCES(权限被拒绝)
数据路径必须包含子文件夹 tessdata!
import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Environment; import android.os.Bundle; import android.provider.MediaStore; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.googlecode.tesseract.android.TessBaseAPI; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class MainActivity extends Activity { private static final String TAG = MainActivity.class.getSimpleName(); static final int PHOTO_REQUEST_CODE = 1; private TessBaseAPI tessBaseApi; TextView textView; Uri outputFileUri; private static final String lang = "eng"; String result = "empty"; private static final String DATA_PATH = Environment.getExternalStorageDirectory().toString() + "/TesseractSample/"; private static final String TESSDATA = "tessdata"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button captureImg = (Button) findViewById(R.id.action_btn); if (captureImg != null) { captureImg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startCameraActivity(); } }); } textView = (TextView) findViewById(R.id.textResult); } /** * to get high resolution image from camera */ private void startCameraActivity() { try { String IMGS_PATH = Environment.getExternalStorageDirectory().toString() + "/TesseractSample/imgs"; prepareDirectory(IMGS_PATH); String img_path = IMGS_PATH + "/ocr.jpg"; outputFileUri = Uri.fromFile(new File(img_path)); final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri); if (takePictureIntent.resolveActivity(getPackageManager()) != null) { startActivityForResult(takePictureIntent, PHOTO_REQUEST_CODE); } } catch (Exception e) { Log.e(TAG, e.getMessage()); } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { //making photo if (requestCode == PHOTO_REQUEST_CODE && resultCode == Activity.RESULT_OK) { prepareTesseract(); startOCR(outputFileUri); } else { Toast.makeText(this, "ERROR: Image was not obtained.", Toast.LENGTH_SHORT).show(); } } /** * Prepare directory on external storage * * @param path * @throws Exception */ private void prepareDirectory(String path) { File dir = new File(path); if (!dir.exists()) { if (!dir.mkdirs()) { Log.e(TAG, "ERROR: Creation of directory " + path + " failed, check does Android Manifest have permission to write to external storage."); } } else { Log.i(TAG, "Created directory " + path); } } private void prepareTesseract() { try { prepareDirectory(DATA_PATH + TESSDATA); } catch (Exception e) { e.printStackTrace(); } copyTessDataFiles(TESSDATA); } /** * Copy tessdata files (located on assets/tessdata) to destination directory * * @param path - name of directory with .traineddata files */ private void copyTessDataFiles(String path) { try { String fileList[] = getAssets().list(path); for (String fileName : fileList) { // open file within the assets folder // if it is not already there copy it to the sdcard String pathToDataFile = DATA_PATH + path + "/" + fileName; if (!(new File(pathToDataFile)).exists()) { InputStream in = getAssets().open(path + "/" + fileName); OutputStream out = new FileOutputStream(pathToDataFile); // Transfer bytes from in to out byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } in.close(); out.close(); Log.d(TAG, "Copied " + fileName + "to tessdata"); } } } catch (IOException e) { Log.e(TAG, "Unable to copy files to tessdata " + e.toString()); } } /** * don't run this code in main thread - it stops UI thread. Create AsyncTask instead. * https://developer.android.com/reference/android/os/AsyncTask.html * * @param imgUri */ private void startOCR(Uri imgUri) { try { 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. Bitmap bitmap = BitmapFactory.decodeFile(imgUri.getPath(), options); result = extractText(bitmap); textView.setText(result); } catch (Exception e) { Log.e(TAG, e.getMessage()); } } private String extractText(Bitmap bitmap) { 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 // //For example if we only want to detect numbers // tessBaseApi.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "1234567890"); // // //blackList Example // tessBaseApi.setVariable(TessBaseAPI.VAR_CHAR_BLACKLIST, "!@#$%^&*()_+=-qwertyuiop[]}{POIU" + // "YTRWQasdASDfghFGHjklJKLl;L:'\"\|~`xcvXCVbnmBNM,./<>?"); Log.d(TAG, "Training file loaded"); 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; } }
如果您的目标是 Android SDK 23 或更高版本,除了在 Android 清单文件中请求权限外,您还必须 request permissions from the user at run time。
或者,您可以通过更改 build.gradle 中的 targetSdkVersion
值来定位 SDK 22 或更低版本。