學習身份證影象識別

weixin_34247155發表於2017-10-05

前言:

實名認證是網際網路的大趨勢.越來越多的地方需要使用者實名認證了.我目前所在的公司網站也有這個需求.可是公司之前一直使用的是人工後臺稽核.這樣做有幾個不好的地方

  1. 絕大多數使用者還是會上傳真實有效的身份資訊,所以審查結果往往都是通過
  2. 使用者在上傳後認證需要等待,可是等待的過程往往就是失去使用者的過程.
  3. 加大了我們網站工作人員的工作量,不利於後期發展
    通過分析這些問題.我決定使用百度的人工智慧提供的介面,來完成智慧實名認證.

目錄:

  1. 申請應用
  2. 獲取accessToken
  3. 呼叫識別介面,獲取資料
  4. 對比資料
  5. 業務邏輯介紹

1. 申請應用

6016628-14e96d7f9d669531.png
image.png

在百度雲的控制檯中找到,人工智慧部分,選擇你需要的服務

6016628-ceb3c0e4c1b99e29.png
image.png

然後建立你需要的應用,建立好了就可以獲得app_key 和app_secret(好像不叫這個名字,不過是什麼東西.大家都懂)

看到這兩個熟悉的東西.大家一定會想到第三方登入是吧.沒錯這裡的應用也是基於Oauth2.0協議.比較關注我的朋友應該看過,我之前寫的關於第三方登入的部落格.這裡就過多介紹原理了.直接講用法

2. 獲取access_token

拿到app_key和app_secret這兩個引數之後,我們就可以來獲取access_token了.
和其他Oauth2.0協議的應用相同,都是用curl的方式去請求這個token

class BaiduAiController extends Controller
{
    //公共的成員變數
    public $accessToken;

    /**
     * 在類成員變數中沒有accessToken,或者accessToken過期則調這個方法
     */
    public function getAccessToken()
    {
            //獲取配置引數
            $config=C('BAIDUAI');
            //百度ai的token請求地址
            $url='https://aip.baidubce.com/oauth/2.0/token';
            $post_data = [];
            //這個是引數是固定寫法
            $post_data['grant_type']  = 'client_credentials';
            //依次填入我們在配置中設定好的引數
            $post_data['client_id']   = $config['app_id'];
            $post_data['client_secret'] = $config['app_secret'];
            //呼叫公共的curl方法,第一個引數是url,第二個引數是請求型別,第三個引數是攜帶的資料
            $result=http($url,'POST',$post_data);
            //狀態無誤
            if ($result[0]==200) {
                //將返回的json資料轉換為陣列,並取出token存入類成員變數中
                $this->accessToken=json_decode($result[1],true)['access_token'];
                //返回token
                return $this->accessToken;
            }
    }
}

我將獲取token單獨寫了一個控制器,其實也可以不用寫,看個人習慣.通過這個方法,我們就能獲取到token,用於我們呼叫其它介面

3.呼叫識別身份證照片的介面

百度身份證識別可以識別身份證的正面,背面上面的文字.也就是說可以獲取到使用者的姓名,性別,生日,住址,身份證號,發證機關,有效期.

呼叫介面,需要傳入的資料有

  1. base64加密後的二進位制的圖片流
//沒懂沒關係,我們看程式碼
//獲取圖片的2進位制流$imgUrl是圖片的url
        $img = file_get_contents($imgUrl);
        //將字串進行base64加密
        $img = base64_encode($img);
  1. 傳入圖片的正面或則背面的資訊

其實就是你要檢測正面就傳入正面引數,背面就傳入背面引數

當前還有更多更高階的應用,需要傳入其他資料.由於本次應用沒有用到,就不展開了說了

6016628-5f326b9a3947a3a2.png
image.png

下面看完整的程式碼

/**
     * 呼叫身份證識別介面,返回識別後的資料
     * @param $imgUrl
     * @return array
     */
    private function checkID($imgUrl)
    {
        //例項化baiduai控制器物件
        $baiduObj = new BaiduAiController();
        //獲取到accesstoken
        $accessToken = isset($baiduObj->accessToken) ? $baiduObj->accessToken : $baiduObj->getAccessToken();
        $url = 'https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token=' . $accessToken;
        //獲取圖片的2進位制流$imgUrl是圖片的url
        $img = file_get_contents($imgUrl);
        //將字串進行base64加密
        $img = base64_encode($img);
        $bodys = array(
            //這個代表的是,識別身份證的正面
            'id_card_side' => 'front',
            "image" => $img
        );
        //使用curl方法 獲取介面返回的資料
        $res = http($url, 'POST', $bodys);
        //訪問狀態沒問題
        if ($res[0] == 200) {
            //access過期
            if (isset($res[1]['error_code'])==11) {
                //重新賦值,遞迴,返回資料
                $baiduObj->accessToken=null;
                return $this->checkID($imgUrl);
            }
            //將返回的資料,轉換為陣列
            $res = json_decode($res[1], true);
            //提取陣列中的身份證號碼
            $ID = $res['words_result']['公民身份號碼']['words'];
            //提取陣列中的姓名
            $realname = $res['words_result']['姓名']['words'];
            $result = [];
            //在兩個資料都識別出的情況下,存入返回陣列
            if (isset($ID) && isset($realname)) {
                $result['status'] = 1;
                $result['ID'] = $ID;
                $result['realname'] = $realname;
            } else {
                //沒有獲取到完整資料,返回狀態碼
                $result['status'] = 0;
            }
            //返回資料
            return $result;
        }
    }

下面是返回資料的示例,每個引數的定義,歡迎檢視官方手冊

{
    "log_id": 2648325511,//唯一id,方便定位錯誤
    "direction": 0,
    "image_status": "normal",
    "idcard_type": "normal",
    "edit_tool": "Adobe Photoshop CS3 Windows",
    "words_result": {
        "住址": {
            "location": {
                "left": 267,
                "top": 453,
                "width": 459,
                "height": 99
            },
            "words": "南京市江寧區弘景大道3889號"
        },
        "公民身份號碼": {
            "location": {
                "left": 443,
                "top": 681,
                "width": 589,
                "height": 45
            },
            "words": "330881199904173914"
        },
        "出生": {
            "location": {
                "left": 270,
                "top": 355,
                "width": 357,
                "height": 45
            },
            "words": "19990417"
        },
        "姓名": {
            "location": {
                "left": 267,
                "top": 176,
                "width": 152,
                "height": 50
            },
            "words": "伍雲龍"
        },
        "性別": {
            "location": {
                "left": 269,
                "top": 262,
                "width": 33,
                "height": 52
            },
            "words": "男"
        },
        "民族": {
            "location": {
                "left": 492,
                "top": 279,
                "width": 30,
                "height": 37
            },
            "words": "漢"
        }
    },
    "words_result_num": 6
}

4. 對比識別出的資料和 使用者的輸入的資料是否一致

這個就太簡單了 就不過多介紹了

    /**
     * 對比識別出的資料,和使用者填寫的資料是否一致
     * @param $idData
     * @param $userData
     * @return bool
     */
    private function comparisonID($idData, $userData)
    {
        if ($idData['realname'] == $userData['realname'] && $idData['ID'] == $userData['ID']) {
            return true;
        } else {
            return false;
        }
    }

注意,返回的資料,並不只有身份證號和姓名.大家可以按照自己的需求來獲取資料.還有就是那個acess_token過期部分,並沒有驗證.希望大神指正

5.下面介紹下我所經手的網站的業務流程

6016628-835490950e700743.png
自動認證身份證.png

注意:這個介面並非免費使用,每日免費500次呼叫.對於我現在所經手的網站那是搓搓有餘了.具體價格感興趣的朋友的到官網瞭解

好了,本次身份證影象識別的介紹了就寫到這裡了,如果有什麼地方不對,希望大神指正.謝謝

相關文章