app ocr 功能实现说明

96 阅读7分钟

实现功能:使用app 模块 实现拍照身份证/营业执照,并对照片 OCR识别出内容

百度智能云-卡证OCR

 

一、apicloud集成卡证ocr方案

第一种,在app或者h5中,通过调用apicloud模块twoBaiDuOcr,由twoBaiDuOcr调用百度智能云卡证ocr服务

第二种,在app或者h5直接调用百度智能云卡证ocr服务api

二、优缺点

第一种方案

优点:已经封装好,提供交互界面,容易上手,文档简单

缺点:目前模块版本只支持银行卡、身份证、驾驶证(说明:1.apicloud模块库有支持营业执照的其他付费模块,上海本次功能需求没有营业执照,所以没有调研过;2.营业执照识别服务需要在百度智能云付费开通)

第二种方案

优点:功能全面,参数自定义程度高

缺点:需要熟读官方文档,全面把握

三、上海农村金融功能

本次上海农村金融功能采用方案一

具体调用:

1.百度智能云卡证ocr介绍(流程UML图)

方案一,twoBaiDuOcr对红框内做了封装,调用简单

image.png
方案二:所有请求需要根据文档一步一步执行

image.png 2.调用demo(基于方案一)

(1) 在apicloud添加模块(twoBaiDuOcr 已经添加)

(2) 配置 config.xml

在工程文件:frp_company_app => config.xml 进行配置,根据(twoBaiDuOcr文档:docs.apicloud.com/Client-API/…

<feature name="twoBaiDuOcr"> 
    <param name="apiKey" value="填写百度文字识别API Key"/>  
    <param name="secretKey" value="填写百度文字识别Secret Key"/> 
  </feature>

(3) 新建测试页面(h5项目中)

比如:frp_company_app_client => src => view =>IdCardOCR.vue

<template>
  <div @click="handleIDCardFront()">上传身份证 人像面</div>
  <div>证件人像面识别信息:{{ idCardFront }}</div>
  <div @click="handleIDCardBack()">上传身份证 国徽面</div>
  <div>证件国徽面识别信息:{{ idCardBack }}</div>
</template>


<script>
import { requireModule, toast, setStatusBarStyle, systemType } from "@/utils/sdk";


const twoBaiDuOcr = requireModule("twoBaiDuOcr");
const trans = requireModule("trans");


export default {
  name: "IdCardOcr"
  data() {
    return {
      idCardFront: {},
      idCardBack: {}
    }
  },
  computed: {
    isIos() {
      return Boolean(systemType() === "ios");
    }
  },
  mounted() {
    this.initPage();
  },
  methods: {
    initPage() {
      this.initAccessTokenWithAkSk();
    },
    // 初始化 twoBaiDuOcr 
    initAccessTokenWithAkSk() {
      const _This = this;
      
      twoBaiDuOcr.initAccessToken({}, (ret) => {
        const result = JSON.parse(JSON.stringify(ret));
        if(!result.status) {
          return toast({
            msg: "OCR身份证识别SDK加载失败"
          });
        }
        
        if(!_This.isIos) {
          // 初始化身份证本地质量控制,只用android版本需要,如果不识别身份证,可以删除此方法
          twoBaiDuOcr.initCameraNative({}, () => {});
        }
      });
    },
    // 身份证 人像面
    handleIDCardFront() {
      const _This = this;
      twoBaiDuOcr.idCardFront({}, (ret) => {
        const result = JSON.parse(JSON.stringify(ret));
        if(!result.status) {
          return toast({
            msg: "身份证人像面识别失败"
          });
        }
        
        /**
         * 预防证件风险:
         * riskType: normal-正常身份证 | copy-复印件 | temporary-临时身份证 
         * | screen-翻拍 | unknown-其他未知情况
         * 
         * imageStatus: normal-识别正常 | reversed_side-身份证正反面颠倒 
         * | non_idcard-上传的图片中不包含身份证
         * blurred-身份证模糊 | other_type_card-其他类型证照 
         * | over_exposure-身份证关键字段反光或过曝 
         * | over_dark-身份证欠曝(亮度过低)|  unknown-未知状态
         * 
         * idCardSide: front-身份证含照片的一面 | back-身份证带国徽的一面
         */
        const riskType = ["copy", "temporary", "screen", "unknown"].includes(
          result.riskType
        );
        const imageStatus = [
          "reversed_side",
          "non_idcard",
          "blurred",
          "other_type_card",
          "over_exposure",
          "over_dark",
          "unknown"
        ].includes(result.imageStatus);
        const idCardSide = ["back"].includes(result.idCardSide);
        if (riskType || imageStatus || idCardSide) {
          return toast({
            msg: "身份证国徽面识别失败,请重新识别"
          });
        }
        
        // 身份证 人像面面识别成功
        _This.handleConvertBase64(result.imagePath).then(base64ImagePath => {
         
          /**
           * 返回身份证证件信息:
           * name: string, // 姓名
           * gender: string, // 性别
           * ethnic: string, // 民族
           * birthday: string, // 出生日期
           * idNumber: string, // 身份证号码
           * address: string, // 地址
           * imagePath: string // 照片保存路径
           */
          result.imagePath = base64ImagePath;
          _This.idCardFront = result;
        }).catch(e => {
          console.log(e);
        });
        
      });
    },
     
    // 身份证 国徽面
    handleIDCardBack() {
      const _This = this;
      const result = JSON.parse(JSON.stringify(ret));
      if(!result.status) {
         return toast({
           msg: "身份证国徽面识别失败"
         });
      }
      /**
       * 预防证件风险:
       * riskType: normal-正常身份证 | copy-复印件 | temporary-临时身份证 
       * | screen-翻拍 | unknown-其他未知情况
       * 
       * imageStatus: normal-识别正常 | reversed_side-身份证正反面颠倒 
       * | non_idcard-上传的图片中不包含身份证
       * blurred-身份证模糊 | other_type_card-其他类型证照 
       * | over_exposure-身份证关键字段反光或过曝 
       * | over_dark-身份证欠曝(亮度过低)|  unknown-未知状态
       * 
       * idCardSide: front-身份证含照片的一面 | back-身份证带国徽的一面
       */
       const riskType = ["copy", "temporary", "screen", "unknown"].includes(
         result.riskType
       );
       const imageStatus = [
         "reversed_side",
         "non_idcard",
         "blurred",
         "other_type_card",
         "over_exposure",
         "over_dark",
         "unknown"
       ].includes(result.imageStatus);
       const idCardSide = ["front"].includes(result.idCardSide);
       if (riskType || imageStatus || idCardSide) {
         return toast({
           msg: "身份证国徽面识别失败,请重新识别"
         });
       }
      
       // 身份证 人像面面识别成功
       _This.handleConvertBase64(result.imagePath).then(base64ImagePath => {
         /**
          * 返回身份证证件信息:
          * issueAuthority: string, // 身份证签发机关
          * expiryDate: string, // 身份证失效时间
          * signDate: string, // 发证日期
          * imagePath: string // 照片保存路径
          */
         result.imagePath = base64ImagePath;
         _This.idCardBack = result;
       }).catch(e => {
         console.log(e);
       });
    },
     
    // 图片转base64
    handleConvertBase64(imagePath) {
      return new Promise((resolve, reject) => {
        trans.decodeImgToBase64({
          imgPath: imagePath
        }, (ret, err) => {
          if (ret.status) {
            // 处理 img 标签能正常显示的 base64 格式
            const imageType = imagePath.match(/(?<=.)([^.]+)$/g).join();
            const base64Str = `data:image/${imageType};base64,${ret.base64Str}`;
            resolve(base64Str);
          } else {
            reject(err);
          }
        });
      });
    },


  }
}
</script>

(4) 生产nginx上配置转发或者开发环境配置代理

module.exports = {
  proxy: {
    "/oauth": {
      target: "https://aip.baidubce.com",
      ws: true,
      secure: true,
      changeOrigin: true,
      pathRewrite: {
        '^/oauth': '/oauth'
      }
    },
    "/rest": {
      target: "https://aip.baidubce.com",
      ws: true,
      secure: true,
      changeOrigin: true,
      pathRewrite: {
        "^/rest": "/rest"
      }
    }
  }
};

(5) 运行模拟器或手机真机加载自定义loader测试

 

四、营业执照识别功能

因为当前twoBaiDuOcr模块版本不支持营业执照识别,同时需要开动付费营业执照识别服务,所以按照百度智能云识别营业执照服务官方文档单独介绍下(UML图请看上文方案二)

官方文档:

1.百度智能云OCR卡证文档:cloud.baidu.com/doc/OCR/s/r…

2.百度智能云文字识别应用集成:console.bce.baidu.com/ai/?_=16692…

 

流程

(1)创建应用,拿到api key secret key (已经创建)

image.png
(2).封装 request.js

request.js

// 百度智能云
const baiduAIService = axios.create({
  timeout: 3000,
  baseURL: "/",
  headers: {
    "Content-Type": "application/json; charset=UTF-8"
  }
});
baiduAIService.interceptors.request.use(
  config => {
    return config;
  },
  error => Promise.error(error)
);
baiduAIService.interceptors.response.use(
  response => {
    const res = response;
    // isWhite = true; 由前端自定义提示
    if (res.status === 200) {
      return res.data;
    }
  },
  error => {
    console.log("err" + error); // for debug
  }
);


export { baiduAIService };

(3).添加百度智能云-文字识别API:api=> index.js

// 百度智能云
export const baiduSmartCloud = {
  卡证识别: {
    accessToken: "oauth/2.0/token",
    身份证识别: "rest/2.0/ocr/v1/idcard",
    营业执照识别: "rest/2.0/ocr/v1/business_license"
  }
};

(4).添加百度baiduAI.js: baiduAI.js

import { baiduAIService } from "@/utils/request";
import { baiduSmartCloud } from "@/api";


/**
 * grant_type: 百度智能云官方规定的固定值 client_credentials
 * client_id: 应用的API Key
 * client_secret: 应用的Secret Key
 * 
 *
 * 注:
 * API Key、Secret Key: 均可在百度智能云控制台 各技术方向概览页的应用列表 处获取,若无应用请先进行创建;
 * API Key、Secret Key: 用于接口调用鉴权,请务必注意保密,不可在公开文档或代码中以明文展示,否则可能导致账号被盗用。
 * 
 */
const grant_type = "client_credentials";
const client_id = "GtG1No84Hila2BykkTxAbptW";
const client_secret = "79VjpNCFoGDzU9HuwMOnb2KiiNpWGGEE";




export const 百度智能云卡证识别 = {
  获取access_token(params = {}) {
    return baiduAIService.post(
      baiduSmartCloud.卡证识别.accessToken,
      {
        ...params
      },
      {
        params: {
          grant_type,
          client_id,
          client_secret
        }
      }
    );
  },
  ......
}

(5)获取 Access Token

POST请求请求URL数据格式
aip.baidubce.com/oauth/2.0/t…grant_type: client_credentials client_id: 应用的API Key client_secret: 应用的Secret Key
服务器返回JSON文本如下: { "refresh_token": "25.b55fe1d287227ca97aab219bb249b8ab.315360000.1798284651.282335-8574074", "expires_in": 2592000, "scope": "public wise_adapt", "session_key": "9mzdDZXu3dENdFZQurfg0Vz8slgSgvvOAUebNFzyzcpQ5EnbxbF+hfG9DQkpUVQdh4p6HbQcAiz5RmuBAja1JJGgIdJI", "access_token": "24.6c5e1ff107f0e8bcef8c46d3424a0e78.2592000.1485516651.282335-8574074", "session_secret": "dfac94a3489fe9fca7c3221cbf7525ff" }access_token: 要获取的Access Token; expires_in: Access Token的有效期(秒为单位,有效期30天); 其他参数忽略,暂时不用;

(6)身份证识别(如果身份证识别也用方案一,可以看一下这里,营业执照识别在下面)

 请求示例

HTTP 方法:POST

请求URL: aip.baidubce.com/rest/2.0/oc…

URL参数:

参数
access_token通过API Key和Secret Key获取的access_token,参考“Access Token获取

header如下

参数
Content-Typeapplication/x-www-form-urlencoded

Body中放置请求参数,参数详情如下:

  这是部分参数,其它参数请自行参考文档:cloud.baidu.com/doc/OCR/s/r…

请求参数

image和url二选一string-图像数据,base64编码后进行urlencode,要求base64编码和urlencode后大小不超过4M,最短边至少15px,最长边最大4096px,支持jpg/jpeg/png/bmp格式
url和image二选一string-图片完整URL,URL长度不超过1024字节,URL对应的图片base64编码后大小不超过4M,最短边至少15px,最长边最大4096px,支持jpg/jpeg/png/bmp格式,当image字段存在时url字段失效 请注意关闭URL防盗链
id_card_sidestringfront/back-front:身份证含照片的一面 -back:身份证带国徽的一面 自动检测身份证正反面,如果传参指定方向与图片相反,支持正常识别,返回参数image_status字段为"reversed_side"
detect_riskstringtrue/false是否开启身份证风险类型(身份证复印件、临时身份证、身份证翻拍、修改过的身份证)检测功能,默认不开启,即:false。 - true:开启,请查看返回参数risk_type; - false:不开启

返回参数

{
    "words_result": {
        "姓名": {
            "location": {....},
            "words": "裴熙"
        },
        "民族": {
            "location": {...},
            "words": "汉"
        },
        "住址": {
            "location": {...},
            "words": "住址"
        },
        "公民身份号码": {
            "location": {
                "top": 1414,
                "left": 411,
                "width": 604,
                "height": 68
            },
            "words": "公民身份号码"
        },
        "出生": {
            "location": {...},
            "words": "出生"
        },
        "性别": {
            "location": {...},
            "words": "男"
        }
    },
    "risk_type": "normal",
    "words_result_num": 6,
    "idcard_number_type": 1,
    "image_status": "normal",
    "log_id": 1595647635211744681
}

(7)营业执照识别

 请求示例

HTTP 方法:POST

请求URL: aip.baidubce.com/rest/2.0/oc…

URL参数:

参数
access_token通过API Key和Secret Key获取的access_token,参考“Access Token获取

header如下

参数
Content-Typeapplication/x-www-form-urlencoded

Body中放置请求参数,参数详情如下:

这是部分参数,其它参数请自行参考文档:cloud.baidu.com/doc/OCR/s/r…
请求参数

参数类型是否必须说明
imagestring和url二选一图像数据,base64编码后进行urlencode,要求base64编码和urlencode后大小不超过4M,最短边至少15px,最长边最大4096px,支持jpg/jpeg/png/bmp格式
urlstring和image二选一图片完整URL,URL长度不超过1024字节,URL对应的图片base64编码后大小不超过4M,最短边至少15px,最长边最大4096px,支持jpg/jpeg/png/bmp格式,当image字段存在时url字段失效 请注意关闭URL防盗链
accuracystring此参数新版本无需传,可选值:normal,high
risk_warnstring是否开启风险类型功能,默认不开启,即:false。 - false:不开启 - true:开启

返回参数

{
    "words_result": {
        "社会信用代码": {
            "words": "10440119MA06M8503",
            "location": {....}
        },
        "组成形式": {
            "words": "无",
            "location": {...}
        },
        "经营范围": {
            "words": "商务服务业",
            "location": {...}
        },
        "成立日期": {
            "words": "2019年01月01日",
            "location": {...}
        },
        "法人": {
            "words": "方平",
            "location": {...}
        },
        "注册资本": {
            "words": "200万元",
            "location": {...}
        },
        "证件编号": {
            "words": "921MA190538210301",
            "location": {...}
        },
        "地址": {
            "words": "广州市",
            "location": {...}
        },
        "单位名称": {
            "words": "有限公司",
            "location": {...}
        },
        "有效期": {
            "words": "长期",
            "location": {...}
        },
        "核准日期": {
            "words": "2018年12月20日",
            "location": {...}
        },
        "类型": {
            "words": "有限责任公司(自然人投资或控股)",
            "location": {...}
        }
    },
    "log_id": 1310106134421438464,
    "words_result_num": 12,
    "direction": 0
}

(8)开发环境配置代理,生产环境配置nginx

module.exports = {
  proxy: {
    "/oauth": {
      target: "https://aip.baidubce.com",
      ws: true,
      secure: true,
      changeOrigin: true,
      pathRewrite: {
        '^/oauth': '/oauth'
      }
    },
    "/rest": {
      target: "https://aip.baidubce.com",
      ws: true,
      secure: true,
      changeOrigin: true,
      pathRewrite: {
        "^/rest": "/rest"
      }
    }
  }
};

注意事项:

  • 身份证识别 和 卡证识别 请求头参数和值一定要是:Content-Type: application/x-www-form-urlencoded;

  • 获取 Access Token 必须按照官方文档指定的来。请求URL数据格式  其中 grant_type 参数请固定为:grant_type: client_credentials;