OCR real-time scanning and identification of Chinese and English -- the use of tess_two in Android

This blog is based on the need for real-time scanning and identification, and then I saw a blog, based on which it was improved according to the needs of the project. Thanks to Si-Kang's contribution, based on the idea of ​​​​communicating and progressing, here are some of the problems I dealt with

Reprint address: http://blog.csdn.net/mr_sk/article/details/72877492#comments


This blog Demo address : http://download.csdn.net/detail/g_ying_jie/9883095


The first step of integration:

compile 'com.rmtheis:tess-two:7.0.0'

Step 2: Download the Chinese package of tess-two, which is already included in the Demo.

Step 3: Declare permissions, remember to apply for Android 6.0 dynamic permissions:

<uses-permission android:name="android.permission.CAMERA" />
    <!-- Declare the use of Camera intent-->
    <uses-feature android:name="android.hardware.camera" />
    <!-- Declare to call Camera auto focus function-->
    <uses-feature android:name="android.hardware.camera.autofocus" />

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Step 4: After obtaining read and write permissions, copy the font library from the assets directory of the project to the mobile phone storage. Note that the storage path must include the tessdata directory, because when TessBaseAPI is initialized, go back and look for this directory

/**
* datapath is the text library path you passed in, you can see that a "tessdata" directory is added after the passed in datapath
* Then verify whether the directory exists, if not, it will report an error "The data directory must contain the tessdata directory"
*/
 File tessdata = new File(datapath + "tessdata");
         //Whether tessdata exists and is a directory
        if (!tessdata.exists() || !tessdata.isDirectory())
            throw new IllegalArgumentException("Data path must contain subfolder tessdata!");

/**
     * Copy the identification library in assets to SD card
     *
     * @param path The full filename to be stored on the SD card. here is "/storage/emulated/0//tessdata/chi_sim.traineddata"
     * The file name in @param name assets here is "chi_sim.traineddata"
     */
    public void copyToSD(String path, String name) {

        // delete if it exists
        File f = new File(path);
        if (f.exists()) {
            f.delete();
        }
        if (!f.exists()) {
            File p = new File(f.getParent());
            if (!p.exists()) {
                p.mkdirs();
            }
            try {
                f.createNewFile();
            } catch (IOException e) {
                e.printStackTrace ();
            }
        }

        InputStream is = null;
        OutputStream os = null;
        try {
            is = this.getAssets().open(name);
            File file = new File(path);
            os = new FileOutputStream(file);
            byte[] bytes = new byte[2048];
            int len ​​= 0;
            while ((len = is.read(bytes)) != -1) {
                os.write(bytes, 0, len);
            }
            os.flush();
        } catch (IOException e) {
            e.printStackTrace ();
        } finally {
            try {
                if (is != null)
                    is.close();
                if (os != null)
                    os.close();
            } catch (IOException e) {
                e.printStackTrace ();
            }
        }
    }

Step 5: Use surfaceview and camera to preview the picture in real time, call back the previewed frame picture through onPreviewFrame, and then convert it into a bitmap and transfer it to TessBaseAPI for asynchronous identification. For the detailed process, please see the CameraView class in the Demo. Here are some problems I encountered.

①Testing needs, I want to display the real-time preview image and the parsed content through Imageview and TextView, then I get the two sub-controls of CameraActivity in CameraView, and the setTag method of CameraView is used here, many people may know How to pass one, then how to pass multiple?

First add two keys to the strings file

<resources>
    <string name="app_name">TestTessTwo</string>
    <item name="tag_img" type="id"></item>
    <item name="tag_text" type="id"></item>
</resources>
Then setTag in the following way

cameraView.setTag(R.id.tag_text, tv_content);
cameraView.setTag(R.id.tag_img, img);
Finally, get the corresponding control through the key

imageView = (ImageView) getTag(R.id.tag_img);
textView = (TextView) getTag(R.id.tag_text);


②The execution of the scanning animation TranslateAnimation is very stuck, mainly because the setPreviewCallback real-time callback onPreviewFrame consumes a lot of resources, and the cropping and parsing content of onPreviewFrame is too time-consuming.

First of all, the picture and recognition processing of onPreviewFrame should be all executed in the sub-thread. The result of the sub-thread can be called back by the handler and then processed in the main thread.

Then setPreviewCallback is replaced by setPreviewCallbackWithBuffer to avoid camera preview constantly opening and reclaiming memory. Note that this method should be used in conjunction with addCallbackBuffer, otherwise there will be only one callback onPreviewFrame, the specific use is as follows

Before starting the preview process, screenWidth and screenHeight are the preview size you determined. Available through camera.getParameters().getPreviewSize();

mCamera.addCallbackBuffer(new byte[((screenWidth * screenHeight) * ImageFormat.getBitsPerPixel(ImageFormat.NV21)) / 8]);
mCamera.setPreviewCallbackWithBuffer(this);
mCamera.setPreviewDisplay(mHolder);//set the surface to be used for live preview
mCamera.startPreview();

Then add camera.addCallbackBuffer(data) in onPreviewFrame;

/**
     * Camera frame data callback
     */
    @Override
    public void onPreviewFrame(final byte[] data, final Camera camera) {
        camera.addCallbackBuffer (date);
        new Thread(new Runnable() {
            @Override
            public void run() {


Okay, let’s talk about it so much. The specific application is available in the Demo. If you have any questions, please leave a message to discuss.




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325196813&siteId=291194637