Java实现身份证OCR--疫情之下“小思考”

272 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

前言

最近背景期间疫情;大家最近也频繁核算检测。检测时使用身份证的OCR识别,可以通过自己的想法实现 OCR的识别。

开始

基本思路:通过调用百度OCR接口,实现OCR识别。

申请

cloud.baidu.com/product/ocr…

百度提供免费接口;刚好可以够我们测试使用;申请之后API Key、Secret Key需要记录一下,如下图

代码开发过程

使用基础的SpringBoot项目快速测试。

文档:cloud.baidu.com/doc/OCR/ind…

pom.xml

<!-- 百度SDK -->
<dependency>
    <groupId>com.baidu.aip</groupId>
    <artifactId>java-sdk</artifactId>
    <version>4.16.8</version>
</dependency>

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.4</version>
</dependency>

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

配置秘钥

package com.weir.demo.ocr_idcard_demo.config;

import com.weir.demo.ocr_idcard_demo.BaiduAIUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author weir
 */
@Configuration
@ConfigurationProperties(prefix = "baidu")
public class BaiduConfig {
    public String appId;
    public String apiKey;
    public String secretKey;

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public String getApiKey() {
        return apiKey;
    }

    public void setApiKey(String apiKey) {
        this.apiKey = apiKey;
    }

    public String getSecretKey() {
        return secretKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    @Bean
    public BaiduAIUtils baiAiHelper() {
        return new BaiduAIUtils(apiKey,secretKey);
    }
}

封装工具包

package com.weir.demo.ocr_idcard_demo;


import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

public class BaiduAIUtils {
    private String apiKey;

    private String secretKey;

    private static String ACCESS_TOKEN = null;

    private static final String ACCESS_TOKEN_URL = "https://aip.baidubce.com/oauth/2.0/token?";

    private static final String LICENSE_PLATE_URL = "https://aip.baidubce.com/rest/2.0/ocr/v1/license_plate";

    private static final String ID_CARD_URL = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard";

    private static final String ID_CARD_AUTHENTICATION_URL = "https://aip.baidubce.com/rest/2.0/face/v3/person/idmatch";

    public BaiduAIUtils(String apiKey, String secretKey) {
        this.apiKey = apiKey;
        this.secretKey = secretKey;
    }

    /**
     * 获取访问Token
     *
     * @return
     */
    public String getAccessToken() {
        // 获取token地址
        String getAccessTokenUrl = ACCESS_TOKEN_URL
                // 1. grant_type为固定参数
                + "grant_type=client_credentials"
                // 2. 官网获取的 API Key
                + "&client_id=" + apiKey
                // 3. 官网获取的 Secret Key
                + "&client_secret=" + secretKey;

        String result = null;
        try {
            result = HttpUtil.get(getAccessTokenUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }
        JSONObject jsonObject = (JSONObject) JSONObject.parse(result);
        return jsonObject.getString("access_token");
    }

    /**
     * 获取 带有Token的URL
     *
     * @param requestUrl
     * @return
     */
    private String getApiAccessTokenUrl(String requestUrl) {
        if (StringUtils.isEmpty(ACCESS_TOKEN)) {
            ACCESS_TOKEN = getAccessToken();
        }
        return requestUrl + "?access_token=" + ACCESS_TOKEN;
    }

    /**
     * 获取身份证数据
     *
     * @return
     */
    public String getIdCardData(String image) {
        String reqUrl = getApiAccessTokenUrl(ID_CARD_URL);
        Map<String, Object> param = new HashMap<>();
        param.put("image", image);
        param.put("id_card_side", "front");
        String result = null;
        try {
            result = HttpUtil.post(reqUrl, param);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}

application.yml

baidu:
  app-id: "26376707"
  api-key: "0prb3RNrT91omegTrCIvlFbt"
  secret-key: "输入自己秘钥"

测试类

@Test
void test() throws IOException {
    BufferedImage img = ImageIO.read(FileUtil.file("D:\Download\Edge_Down\身份证-测试包\01-常涛.png"));
    String base64 = ImgUtil.toBase64(img, ImgUtil.IMAGE_TYPE_PNG);
    String idCardData = baiduAIUtils.getIdCardData(base64);
    System.out.println("idCardData = " + idCardData);
}

测试结果

idCardData = {"words_result":{"姓名":{"location":{"top":459,"left":704,"width":236,"height":127},"words":"常涛"},"民族":{"location":{"top":674,"left":1220,"width":88,"height":108},"words":"汉"},"住址":{"location":{"top":1088,"left":691,"width":1063,"height":237},"words":"河北省邯郸市肥乡县肥乡镇"},"公民身份号码":{"location":{"top":1597,"left":1126,"width":1386,"height":128},"words":"411526199706013217"},"出生":{"location":{"top":878,"left":707,"width":830,"height":101},"words":"19970601"},"性别":{"location":{"top":676,"left":691,"width":98,"height":108},"words":"男"}},"words_result_num":6,"image_status":"normal","idcard_number_type":1,"log_id":1534189165822718071}

总结

使用百度API分装实现基于OCR的识别,体会 一下API工具人魅力;对于百度其他的智能API有很多,这里简单依照疫情的身份证识别作为引导,建议大家尝试其他的场景;这是一个有趣的尝试。