Android ORC文字識別之識別身份證號等(附源碼)

来源:https://www.cnblogs.com/jianpanwuzhe/archive/2018/03/06/8514789.html
-Advertisement-
Play Games

項目地址https://github.com/979451341/OrcTest我們說說實現這個項目已實現的功能,能夠截圖手機界面的某一塊,將這個某一塊圖片的Bitmap傳給tess-two的代碼來獲取掃描結果我這裡在貼出tess-two這個專為Android而創建的文字識別框架的地址https:/ ...


項目地址
https://github.com/979451341/OrcTest

我們說說實現這個項目已實現的功能,能夠截圖手機界面的某一塊,將這個某一塊圖片的Bitmap傳給tess-two的代碼來獲取掃描結果

我這裡在貼出tess-two這個專為Android而創建的文字識別框架的地址
https://github.com/rmtheis/tess-two

接下來我就說我如何一步一步的實現項目

1.實現基礎界面,我這裡貼出已完成的界面

 

這樣是為了模仿掃描二維碼的界面,因為掃描身份證號碼或者是手機號那樣長條的數字,就將掃描區域也做成長條狀,這個掃描區域是有意義的,因為到時候截圖會只將掃描區域里的圖片信息拿去掃描,這也是為了提高掃描速度和精度。

首先要實現這個界面,我們需要畫出四個灰色長方體的位置大小,上下左右。

left是掃描區域左邊離手機屏幕左邊的距離是手機屏幕寬度的1/10,right就是掃描區域右邊離手機屏幕左邊的距離是手機屏幕寬度的9/10,top是掃描區域頂部離手機屏幕頂部的距離是手機屏幕寬度的1/3,bottom是掃描區域底部離手機屏幕頂部的距離是手機屏幕寬度的4/9

        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);

 

畫畫

    @Override
    public 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);

    }

 

還沒有完,還有佈局文件放SurfaceView和按鈕,還有剛纔做的自定義View

2.顯示Camera預覽和Camera拍攝


這裡SurfaceView如何顯示Camera我不多說,只說如何把Camera預覽變清晰,這裡是通過迴圈自動對焦來完成。

設置自動對焦介面

mCamera.autoFocus(autoFocusCallback);

 

這個介面初始化傳入了Handler

autoFocusCallback.setHandler(handler,MSG_AUTOFUCS);

 

然後這個介面實現類里,當完成自動對焦,會通過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");
        }
    }

 

然後handler如何執行以下代碼,再進行一次自動對焦,這樣就完成了迴圈

                    case MSG_AUTOFUCS:
                        cameraUtil.autoFocus();
                        break;

 

然後給按鈕賦予拍攝功能,拍攝的還要停止聚焦

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

 

這個函數會被調用,data就是圖片數據

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

 

這裡要註意一件事,拍攝後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.處理圖片數據,完成局部截圖


繼續在onPictureTaken函數的data數據處理

因為處理圖片是耗時任務,所以開啟子線程完成

這裡先開啟一個等待對話框

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

 

然後開啟子線程

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

        }

 

將data轉換為Bitmap數據

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

 

將圖片旋轉90度

        bitmap = rotateBitmap(bitmap,90);

這是旋轉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);
    }

 

切割Bitmap,將掃描區域的圖片切割出來

        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.掃描出結果


其實tess-two框架的使用很簡單,但是使用這個框架需要依靠訓練文件來完成掃描,我在res目錄下放了raw文件夾,裡面的eng_traineddata文件就是這個用途,但是我們不能直接使用它們,我們需要將他們複製到手機存儲里

下麵的代碼意思是在應用私有路徑里創建tesseract/tessdata/eng.traineddata相關路徑的文件並使用輸入流將文件的數據讀出來,然後使用輸出流將數據傳入eng.traineddata文件

    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;
        }
    }

 

好了再說說tess-two框架的使用

創建TessBaseAPI

        TessBaseAPI tessBaseAPI = new TessBaseAPI();

 

關閉測試

        tessBaseAPI.setDebug(true);

 

設置訓練數據路徑和識別文字是英文

        tessBaseAPI.init(path, "eng");

 

 設置白名單

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

 

設置黑名單

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

 

設置識別模式

        tessBaseAPI.setPageSegMode(TessBaseAPI.PageSegMode.PSM_AUTO_OSD);

 

傳入bitmap數據

        tessBaseAPI.setImage(bitmap);

 

獲取掃描結果

        String inspection = tessBaseAPI.getHOCRText(0);

 

結束TestBaseAPI的使用

        tessBaseAPI.end();

 

實現掃描身份證號碼,這裡是通過正則表達式來判斷掃描出的結果是否有身份證號碼,也就是說tess-two其實是只是掃描出Bitmap文件裡面有哪些文字,然後使用正則表達式來篩選出我們需要的數據。也就是說我們通過換取正則表達式就能做到掃描手機號等,帶有某種規律的數字或者字母

這是正則表達式的線上工具地址,大家可以自己試試 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();
    }

 

然後通過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);

 

取消載入框,並將局部截圖的圖像和掃描的結果通過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.結論


其實還沒有結束因為我本想做出一個能夠掃描整張身份證的項目,我看一下網上有很多API都能實現這個功能,但都要錢,如果要是能夠實現這個功能,併發到github,我豈不是成為大神了。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 基礎數據/表結構 Sql 語句 結果 ...
  • 相同點 都是基於記憶體的數據存儲系統redis 和 memcached 的區別 1.1redis 支持 豐富的數據類型 string hash list set 有序集合 1.2.memcached 只支持 string 2.1 redis支持持久化操作 RDB快照 Redis支持將當前數據的快照存成 ...
  • 環境描述: 操作系統版本:CentOS release 6.5 (Final) phoenix版本:phoenix-4.10.0 hbase版本:hbase-1.2.6 現象描述: 通過phoenix客戶端連接hbase資料庫時,無法正常連接,報下麵的信息: [aiprd@host-10-191-5 ...
  • 開啟用戶管理auth = true在配置文件或者參數中設置為改選項 開啟認證服務,註意一點,很多人說在沒有設置用戶和配置用戶之前,應該先不要開啟,等設置完用戶後再開啟該參數,目前在win2008 x64 下,直接開啟該參數,第一次安裝的一個資料庫服務,可以正常添加用戶創建用戶db.createUse... ...
  • iOS開發者計劃是按年付費的,在過期前60天可以開始續費。如果你不續費的話,你將無法發佈應用。另外蘋果會吊銷你的開發者證書和發佈證書。最後,蘋果將你在iTunes App Store上的所有應用下架。 Ad hoc渠道發行允許你繞過App Store直接將應用發放給你的用戶。但是分發數量會限制在10 ...
  • 1 解決方案一 此處解決辦法參照自網友文章,對於輸入的地址信息要求:城市名+具體地址名。 如果輸入的地址信息只有具體地址名,而沒有城市名,可能解析不出經緯度信息。還有就是解析出的經緯度再反向解析顯示再地圖上作為一個地標標記時,會有較明顯的偏差,偏差的實際地理距離大概有一千米左右...,這是樓主自己實 ...
  • 因為Object-C是不支持多繼承的,所以很多時候都是用Protocol(協議)來代替。Protocol(協議)只能定義公用的一套介面,但不能提供具體的實現方法。也就是說,它只告訴你要做什麼,但具體怎麼做,它不關心。 當一個類要使用某一個Protocol(協議)時,都必須要遵守協議。比如有些必要實現 ...
  • One of the most important concepts in object-oriented programming is that of inheritance. Inheritance allows us to define a class in terms of another ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...