Project Address
Https://github.com/979451341/OrcTest
Let's talk about the implementation of this project has realized the function, can be a piece of the phone interface, the bitmap of a piece of picture passed to Tess-two code to get the scan results
I'm sticking out tess-two. This is the address of the text recognition framework created specifically for Android
Https://github.com/rmtheis/tess-two
And then I'm going to tell you how I can implement the project step-by-step.
1. Implement the basic interface, I posted the finished interface here
This is to imitate scanning the interface of two-dimensional code, because the scan xxx number or mobile phone number as long as the number of long, will scan area also do growth bar, this scanning area is meaningful, because then will only scan the area of the picture information to take to scan, which is also to improve the scanning speed and accuracy.
First to implement this interface, we need to draw four gray box position size, up and down around.
Left is the scan area, the distance from the left side of the phone screen is the phone screen width of the 1/10,right is the scan area to the right of the phone screen to the left of the phone screen width of the 9/10,top is the top of the scanning area from the top of the phone screen is the width of the phone screen 1/ 3,bottom is the distance from the top of the phone screen at the bottom of the scan area is 4/9 of the phone's screen width
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);
Draw
@Overridepublic void onDraw(Canvas canvas) { int width = PMwidth; int height = PMheight; Rect frame = mFrameRect; // 绘制焦点框外边的暗色背景 mPaint.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);}
Not yet finished, there are layout files put Surfaceview and buttons, as well as the custom view you just made
2. Show camera preview and camera capture
Here Surfaceview how to show camera I don't say much, just how to make the camera preview clear, here is done by loop autofocus.
Setting the AF interface
Mcamera.autofocus (Autofocuscallback);
This interface initializes the incoming handler
Autofocuscallback.sethandler (HANDLER,MSG_AUTOFUCS);
Then in this interface implementation class, when autofocus is completed, a message is sent via handler
@Overridepublic 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 handler how to execute the following code, then one more autofocus, which completes the loop
case MSG_AUTOFUCS: cameraUtil.autoFocus(); break;
Then give the button a shooting function and stop focusing on the shot.
handler.removeCallbacksAndMessages(null); cameraUtil.takePicture(TwoActivity.this,TwoActivity.this,TwoActivity.this);
This function is called, and data is the image
One thing to note here is that the camera preview screen will stop after shooting because he stops focusing and we need to reset autofocus and turn on the preview
// 刷新相机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, complete local
Continue data data processing in the Onpicturetaken function
Because processing a picture is a time-consuming task, opening a child thread completes
Here, let's start with a wait dialog box.
if(!mypDialog.isShowing()) mypDialog.show();
Then turn on the child thread
if(data != null){ new Thread(new BitmapThread(bitmap,data,handler,TwoActivity.this)).start(); }
Convert data to Bitmap
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Rotate the picture 90 degrees
bitmap = rotateBitmap(bitmap,90);
This is a function of 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);}
Cutting the bitmap, cutting the picture of the scanned area
int PMwidth = bitmap.getWidth(); // 得到图片的宽,高 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 the results
In fact, the use of Tess-two framework is very simple, but the use of this framework needs to rely on training files to complete the scan, I put the raw folder in the Res directory, the Eng_traineddata file is the purpose, but we can not directly use them, We need to copy them to the phone store.
The following code means to create a file in the application's private path that tesseract/tessdata/eng.traineddata the associated path and use the input stream to read the file's data and then use the output stream to pass the data to the 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; }}
Okay, say it again. Use of the Tess-two framework
Create Tessbaseapi
TessBaseAPI tessBaseAPI = new TessBaseAPI();
Close Test
tessBaseAPI.setDebug(true);
Set the training data path and the recognition text is in English
tessBaseAPI.init(path, "eng");
Set up a white list
tessBaseAPI.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
Set blacklist
Setting the recognition mode
tessBaseAPI.setPageSegMode(TessBaseAPI.PageSegMode.PSM_AUTO_OSD);
Incoming bitmap data
tessBaseAPI.setImage(bitmap);
Get scan Results
String inspection = tessBaseAPI.getHOCRText(0);
End the use of TESTBASEAPI
tessBaseAPI.end();
The implementation of the scan XXX number, here is the regular expression to determine whether the results of the scan has a XXX number, that is, tess-two is actually just scanning out the bitmap file inside what text, and then use regular expressions to filter out the data we need. That means we can do it by exchanging regular expressions to scan the phone number, with some sort of regular number or letter.
This is the online tool address of the regular expression, you can try it yourself 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 via 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);
Cancels the load box and displays the local image and the results of the scan through dialogfragment
mypDialog.dismiss(); String strDecode = msg.getData().getString("decode","扫描失败"); if(strDecode == null ||strDecode.equals("")) strDecode = "扫描失败"; imageDialogFragment.setImage(bitmap); imageDialogFragment.setText(strDecode); imageDialogFragment.show(getFragmentManager(), "ImageDialogFragment");
5. Conclusion
It's not over yet because I wanted to make a project that would scan the entire XXX, I see that there are many APIs on the Internet to achieve this function, but all the money, if it is possible to achieve this function, and to GitHub, I would not become a great God .......... ....... 。。。。。。。。。。。。
Android orc character recognition xxx number, etc. (with source code)