无法显示 OCR 的结果

Unable to display the results of OCR

我有这个 mainActivity java 文件,我想显示 OCR 的结果。

  1. 错误:创建目录/storage/emulated/0/TesseractSample/tessdata失败,检查Android清单是否具有写入外部存储的权限。

  2. 无法将文件复制到 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(权限被拒绝)

  1. 数据路径必须包含子文件夹 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 或更低版本。