Android ORC text recognition-identification ID card number (with source code), androidorc

Source: Internet
Author: User

Android ORC text recognition-identification ID card number (with source code), androidorc

Project address
Https://github.com/979451341/OrcTest

Let's talk about the functions implemented in this project. We can pass Bitmap of this image to the code of tess-two to get the scan result.

Here I will post the address of the text recognition framework created for Android, tess-two.
Https://github.com/rmtheis/tess-two

Next, let's talk about how to implement the project step by step.

1. Implement the basic interface. I have posted the completed interface here.

 

This is to simulate the scanning of the QR code interface, because scanning the ID card number or the number that is as long as the mobile phone number, the scanning area will also grow into a bar, this scanning area is meaningful, because at that time, only the image information in the scanning area will be taken for scanning, which is also to improve the scanning speed and accuracy.

To implement this interface, we need to draw the positions and sizes of the four gray cubes, up, down, and left.

Left indicates that the distance from the left side of the scan area to the left side of the mobile phone screen is 1/10 of the mobile phone screen width. right indicates that the distance from the right side of the scan area to the left side of the mobile phone screen is 9/10 of the mobile phone screen width, top is the distance from the top of the scan area to the top of the screen of the mobile phone is 1/3 of the screen width of the mobile phone, bottom is the distance from the bottom of the scan area to the top of the screen of the mobile phone is 4/9 of the screen width of the mobile phone

        WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);        Display display = manager.getDefaultDisplay();        PMwidth = display.getWidth();        PMheight = display.getHeight();        left = PMwidth/10;        top = PMheight/3;        right = PMwidth*9/10;        bottom = PMheight*4/9;        mFrameRect = new Rect(left,top,right,bottom);

 

Painting

@ Override public void onDraw (Canvas canvas) {int width = PMwidth; int height = PMheight; Rect frame = mFrameRect; // draw the dark background mPaint outside the focus frame. setColor (mMaskColor); canvas. drawRect (0, 0, width, frame. top, mPaint); canvas. drawRect (0, frame. top, frame. left, frame. bottom + 1, mPaint); canvas. drawRect (frame. right + 1, frame. top, width, frame. bottom + 1, mPaint); canvas. drawRect (0, frame. bottom + 1, width, height, mPaint );}

 

There are still layout files, SurfaceView and buttons, and the custom View just made.

2. Show Camera preview and Camera shooting


Here, SurfaceView shows how Camera is displayed. I will not talk about how to make the Camera preview clearer. Here we will do this by repeating autofocus.

Set auto focus interface

mCamera.autoFocus(autoFocusCallback);

 

This interface is passed in Handler during initialization.

autoFocusCallback.setHandler(handler,MSG_AUTOFUCS);

 

In this interface implementation class, when auto focus is completed, a message is sent through handler.

    @Override    public void onAutoFocus(boolean success, Camera camera) {        Log.v("zzw", "autof focus "+success);        if (mAutoFocusHandler != null) {            mAutoFocusHandler.sendEmptyMessageDelayed(mAutoFocusMessage,AUTO_FOCUS_INTERVAL_MS);//            mAutoFocusHandler = null;        } else {            Log.v(TAG, "Got auto-focus callback, but no handler for it");        }    }

 

Then, how does handler Execute the following code and then perform auto focus? This completes the loop.

                    case MSG_AUTOFUCS:                        cameraUtil.autoFocus();                        break;

 

Then, assign the shooting function to the button and stop focusing for the shooting.

                handler.removeCallbacksAndMessages(null);                cameraUtil.takePicture(TwoActivity.this,TwoActivity.this,TwoActivity.this);

 

This function will be called. data is the image data.

    @Override    public void onPictureTaken(byte[] data, Camera camera) 

 

One thing to pay attention to here is that the Camera preview interface will stop after shooting, because it stops focusing. We need to reset auto focus and enable preview.

// Refresh the camera public void refreshCamera () {if (surfaceHolder. getSurface () = null) {// preview surface does not exist return;} // stop preview before making changes try {mCamera. stopPreview ();} catch (Exception e) {// ignore: tried to stop a non-existent preview} // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings try {mCamera. setPreviewDisplay (surfaceHolder); mCamera. startPreview (); mCamera. autoFocus (autoFocusCallback);} catch (Exception e) {} surfaceHolder. setType (SurfaceHolder. SURFACE_TYPE_PUSH_BUFFERS );}

 

3. process image data to complete partial processing


Continue data processing in the onPictureTaken Function

Because image processing is a time-consuming task, subthreads are enabled to complete

Here, a waiting dialog box is opened first.

        if(!mypDialog.isShowing())        mypDialog.show();

 

Then enable the sub-Thread

        if(data != null){            new Thread(new BitmapThread(bitmap,data,handler,TwoActivity.this)).start();        }

 

Convert data to Bitmap data

        bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

 

Rotate the image 90 degrees

        bitmap = rotateBitmap(bitmap,90);

This is a function for rotating Bitmap.

    public static Bitmap rotateBitmap(Bitmap source, float angle) {        Matrix matrix = new Matrix();        matrix.postRotate(angle);        return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);    }

 

Cut Bitmap to cut out the images in the scan area

Int PMwidth = bitmap. getWidth (); // obtain the image width. The height is int PMheight = bitmap. getHeight (); int left = PMwidth/10; int top = PMheight/3; int right = PMwidth * 9/10; int bottom = PMheight * 4/9; int width = right-left; int height = bottom-top; Log. v ("zzw", PMheight + "" + PMwidth); bitmap = Bitmap. createBitmap (bitmap, left, top, width, height, null, false );

 

4. scan results


In fact, the use of the tess-two framework is very simple, but the use of this framework needs to rely on the training file to complete the scan, I put the raw folder in the res directory, the eng_traineddata file inside is this purpose, but we cannot use them directly. We need to copy them to the mobile storage.

The following code creates tesseract/tessdata/eng in the application private path. traineddata-related path file, read the file data using the input stream, and then use the output stream to pass the data to eng. traineddata File

    public static void initTessTrainedData(Context context){        if(initiated){            return;        }        File appFolder = context.getFilesDir();        File folder = new File(appFolder, tessdir);        if(!folder.exists()){            folder.mkdir();        }                    tesseractFolder = folder.getAbsolutePath();        File subfolder = new File(folder, subdir);        if(!subfolder.exists()){            subfolder.mkdir();        }        File file = new File(subfolder, filename);        trainedDataPath = file.getAbsolutePath();        Log.d(TAG, "Trained data filepath: " + trainedDataPath);        if(!file.exists()) {            try {                FileOutputStream fileOutputStream;                byte[] bytes = readRawTrainingData(context);                if (bytes == null){                    return;                }                                    fileOutputStream = new FileOutputStream(file);                fileOutputStream.write(bytes);                fileOutputStream.close();                initiated = true;                Log.d(TAG, "Prepared training data file");            } catch (FileNotFoundException e) {                Log.e(TAG, "Error opening training data file\n" + e.getMessage());            } catch (IOException e) {                Log.e(TAG, "Error opening training data file\n" + e.getMessage());            }        }        else{            initiated = true;        }    }

 

Let's talk about the use of the tess-two framework.

Create TessBaseAPI

        TessBaseAPI tessBaseAPI = new TessBaseAPI();

 

Close test

        tessBaseAPI.setDebug(true);

 

Set the training data path and recognition text to English

        tessBaseAPI.init(path, "eng");

 

Set whitelist

        tessBaseAPI.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");

 

Set blacklist

        tessBaseAPI.setVariable(TessBaseAPI.VAR_CHAR_BLACKLIST, "!@#$%^&*()_+=-[]}{;:'\"\\|~`,./<>?"); 

 

Set recognition Mode

        tessBaseAPI.setPageSegMode(TessBaseAPI.PageSegMode.PSM_AUTO_OSD);

 

Incoming bitmap data

        tessBaseAPI.setImage(bitmap);

 

Obtain scan results

        String inspection = tessBaseAPI.getHOCRText(0);

 

End the use of TestBaseAPI

        tessBaseAPI.end();

 

The ID card number is scanned. Here, the regular expression is used to determine whether the scanned result has an ID card number. That is to say, tess-two only scans the words in the Bitmap file, then use the regular expression to filter out the data we need. In other words, by exchanging regular expressions, we can scan mobile phone numbers and other regular numbers or letters.

This is the regular expression of online tool address, you can try your own http://tool.oschina.net/regex /#

    private static Pattern pattern = Pattern.compile("\\d{17}[\\d|x]|\\d{15}");    public static String getTelNum(String sParam){        if(TextUtils.isEmpty(sParam)){            return "";        }        Matcher matcher = pattern.matcher(sParam);        StringBuilder bf = new StringBuilder();        while (matcher.find()) {            bf.append(matcher.group()).append(",");        }        int len = bf.length();        if (len > 0) {            bf.deleteCharAt(len - 1);        }        return bf.toString();    }

 

Then return the result through handler

        Message message = Message.obtain();        message.what = 1;        Bundle bundle = new Bundle();        bundle.putString("decode",strDecode);        message.setData(bundle);        message.what = TwoActivity.MSG_BITMAP;        handler.sendMessage(message);

 

Unload the box and display the local images and scan results through DialogFragment.

MypDialog. dismiss (); String strDecode = msg. getData (). getString ("decode", "Scan failed"); if (strDecode = null | strDecode. equals ("") strDecode = "Scan failed"; imageDialogFragment. setImage (bitmap); imageDialogFragment. setText (strDecode); imageDialogFragment. show (getFragmentManager (), "ImageDialogFragment ");

 

 

5. Conclusion


In fact, it is not over yet because I wanted to make a project that could scan the entire ID card. I think there are many APIs on the Internet that can implement this function, but I am asking for money. If I can implement this function, concurrency to github, I am not a great god ................................... ...........

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.