银行卡,身份证,驾驶证识别

第一、背景

银行卡,身份证,驾驶证等证件扫描和识别有很广泛的应用场景,比如用户实名认证时。

第二、接入

这里使用百度的文字识别功能。登陆百度的AI开放平台找到文字识别文档。创建一个应用地址
创建好的应用会有三个关键参数。AppID,API Key,Secret Key个会程序里会有使用。

使用SDK
maven引入方式:

<!-- 百度图片识别sdk -->
<dependency>
    <groupId>com.baidu.aip</groupId>
    <artifactId>java-sdk</artifactId>
    <version>${baidu-version}</version>
</dependency>

参数配置类AlibabaMainConfig.java:

package yui.bss.baidu.config;

public class AlibabaMainConfig {
    public static final String APP_ID = "144444951468";
    public static final String API_KEY = "ahvukw8hqlhoAqqbXrXXXXqPoCyE";
    public static final String SECRET_KEY = "RqwNLpnH8YwctkkRI07lpv8kpXXXXXXXUFfR";
}

AipOcr是Optical Character Recognition的Java客户端,为使用Optical Character Recognition的开发人员提供了一系列的交互方法。用户可以参考如下代码新建一个AipOcr,初始化完成后建议单例使用,避免重复获取access_token。
配置AipOcr
如果用户需要配置AipOcr的一些细节参数,可以在构造AipOcr之后调用接口设置参数,目前只支持以下参数:

setConnectionTimeoutInMillis:建立连接的超时时间(单位:毫秒)
setSocketTimeoutInMillis: 通过打开的连接传输数据的超时时间(单位:毫秒)
setHttpProxy :设置http代理服务器
setSocketProxy :设置socket代理服务器 (http和socket类型代理服务器只能二选一)

AlipayClientFactory.java:

package yui.bss.baidu.config;

import javax.annotation.PostConstruct;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.baidu.aip.ocr.AipOcr;

@Service
public class AlipayClientFactory {
    private static Logger logger = Logger.getLogger(AlipayClientFactory.class);
    public static AipOcr client;

    @PostConstruct
    public void postConstruct() throws Exception {
        logger.info("百度环境初始化开始");
        // 初始化一个AipOcr
        AlipayClientFactory.client = new AipOcr(AlibabaMainConfig.APP_ID, AlibabaMainConfig.API_KEY, AlibabaMainConfig.SECRET_KEY);
        // 可选:设置网络连接参数
        client.setConnectionTimeoutInMillis(2000);
        client.setSocketTimeoutInMillis(60000);
        logger.info("百度环境初始化结束");
    }
}

创建一个接口,用于外部调用IBaiduImgMgrx.java

package yui.bss.baidu.service;

import yui.bss.baidu.bean.BankCardBean;
import yui.bss.baidu.bean.DrivingLicenseBean;
import yui.bss.baidu.bean.IdCardBean;
import yui.bss.baidu.bean.PlateLicense;

public interface IBaiduImgMgrx {

    /**
     * 通过图片地址url识别身份证信息
     * 
     * @param imgUrl
     */
    IdCardBean doBaiduIdCard(String imgUrl);

    /**
     * 银行卡识别
     * 
     * @param imgUrl
     */
    BankCardBean doBankCard(String imgUrl);

    /**
     * 车牌识别
     * 
     * @param imgUrl
     */
    PlateLicense doPlateLicense(String imgUrl);

    /**
     *驾驶证识别
     * 
     * @param imgUrl
     */
    DrivingLicenseBean doDrivingLicense(String imgUrl);

}

接口实现如下BaiduImgMgrxImpl.java:

package yui.bss.baidu.service;

import java.util.HashMap;

import org.apache.log4j.Logger;
import org.json.JSONObject;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;

import yui.bss.baidu.bean.BankCardBean;
import yui.bss.baidu.bean.DrivingLicenseBean;
import yui.bss.baidu.bean.IdCardBean;
import yui.bss.baidu.bean.PlateLicense;
import yui.bss.baidu.config.AlipayClientFactory;
import yui.comn.util.FileUtil;

@Service
public class BaiduImgMgrxImpl implements IBaiduImgMgrx {
    private static Logger logger = Logger.getLogger(BaiduImgMgrxImpl.class);

    @Override
    public IdCardBean doBaiduIdCard(String imgUrl) {
        // 重写接口方法:2018319日
        // 传入可选参数调用接口
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("detect_direction", "true");
        options.put("detect_risk", "false");

        // 通用文字识别, 图片参数为远程url图片
        byte[] file = FileUtil.readNetImage(imgUrl);
        JSONObject res = AlipayClientFactory.client.idcard(file, "front", options);
        IdCardBean idCardFront = JSON.parseObject(res.toString(), IdCardBean.class);
        return idCardFront;
    }

    @Override
    public BankCardBean doBankCard(String imgUrl) {
        // 传入可选参数调用接口
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("detect_direction", "true");
        options.put("detect_risk", "false");

        // 通用文字识别, 图片参数为远程url图片
        byte[] file = FileUtil.readNetImage(imgUrl);
        JSONObject res = AlipayClientFactory.client.bankcard(file, options);
        BankCardBean bankCardBean = JSON.parseObject(res.toString(), BankCardBean.class);
        return bankCardBean;
    }

    @Override
    public PlateLicense doPlateLicense(String imgUrl) {
        // 传入可选参数调用接口
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("multi_detect", "true");

        // 通用文字识别, 图片参数为远程url图片
        byte[] file = FileUtil.readNetImage(imgUrl);
        JSONObject res = AlipayClientFactory.client.plateLicense(file, options);
        PlateLicense plateLicense = JSON.parseObject(res.toString(), PlateLicense.class);
        return plateLicense;
    }

    @Override
    public DrivingLicenseBean doDrivingLicense(String imgUrl) {
        // 传入可选参数调用接口
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("detect_direction", "true");

        // 通用文字识别, 图片参数为远程url图片
        byte[] file = FileUtil.readNetImage(imgUrl);
        JSONObject res = AlipayClientFactory.client.drivingLicense(file, options);
        DrivingLicenseBean drivingLicenseBean = JSON.parseObject(res.toString(), DrivingLicenseBean.class);
        return drivingLicenseBean;
    }
}

其中涉及到的bean如下:
1.银行卡识别结果类BankCardBean.java

package yui.bss.baidu.bean;

/**
 * @author chenyuan
 * @version 创建时间:2018年3月19日 下午4:20:32
 * @ClassName 类名称
 * @Description 类描述
 */
public class BankCardBean {
    private Result result;
    private long log_id;

    public void setResult(Result result) {
        this.result = result;
    }

    public Result getResult() {
        return result;
    }

    public void setLog_id(long log_id) {
        this.log_id = log_id;
    }

    public long getLog_id() {
        return log_id;
    }

    public static class Result {

        private String bank_card_number;
        private int bank_card_type;
        private String bank_name;

        public void setBank_card_number(String bank_card_number) {
            this.bank_card_number = bank_card_number;
        }

        public String getBank_card_number() {
            return bank_card_number;
        }

        public void setBank_card_type(int bank_card_type) {
            this.bank_card_type = bank_card_type;
        }

        public int getBank_card_type() {
            return bank_card_type;
        }

        public void setBank_name(String bank_name) {
            this.bank_name = bank_name;
        }

        public String getBank_name() {
            return bank_name;
        }

    }
}

2.驾驶证识别结果DrivingLicenseBean.java

package yui.bss.baidu.bean;

import com.alibaba.fastjson.annotation.JSONField;

/**
 * @author chenyuan
 * @version 创建时间:2018年3月19日 下午4:20:32
 * @ClassName 类名称
 * @Description 类描述
 */
public class DrivingLicenseBean {
    private String log_id;
    private DrivingLicenseWordsResult words_result;

    public String getLog_id() {
        return log_id;
    }

    public void setLog_id(String log_id) {
        this.log_id = log_id;
    }

    public DrivingLicenseWordsResult getWords_result() {
        return words_result;
    }

    public void setWords_result(DrivingLicenseWordsResult words_result) {
        this.words_result = words_result;
    }

    // 为了友好解析,使用了FastJson对源数据key中文的解析
    public static class DrivingLicenseWordsResult {
        @JSONField(name = "证号")
        private Words certNo;
        @JSONField(name = "有效期限")
        private Words valdTm;
        @JSONField(name = "准驾车型")
        private Words canCar;
        @JSONField(name = "有效起始日期")
        private Words valdFm;
        @JSONField(name = "住址")
        private Words address;
        @JSONField(name = "姓名")
        private Words name;
        @JSONField(name = "国籍")
        private Words country;
        @JSONField(name = "出生日期")
        private Words birthday;
        @JSONField(name = "性别")
        private Words sex;
        @JSONField(name = "初次领证日期")
        private Words first;
        public Words getCertNo() {
            return certNo;
        }
        public void setCertNo(Words certNo) {
            this.certNo = certNo;
        }
        public Words getValdTm() {
            return valdTm;
        }
        public void setValdTm(Words valdTm) {
            this.valdTm = valdTm;
        }
        public Words getCanCar() {
            return canCar;
        }
        public void setCanCar(Words canCar) {
            this.canCar = canCar;
        }
        public Words getValdFm() {
            return valdFm;
        }
        public void setValdFm(Words valdFm) {
            this.valdFm = valdFm;
        }
        public Words getAddress() {
            return address;
        }
        public void setAddress(Words address) {
            this.address = address;
        }
        public Words getName() {
            return name;
        }
        public void setName(Words name) {
            this.name = name;
        }
        public Words getCountry() {
            return country;
        }
        public void setCountry(Words country) {
            this.country = country;
        }
        public Words getBirthday() {
            return birthday;
        }
        public void setBirthday(Words birthday) {
            this.birthday = birthday;
        }
        public Words getSex() {
            return sex;
        }
        public void setSex(Words sex) {
            this.sex = sex;
        }
        public Words getFirst() {
            return first;
        }
        public void setFirst(Words first) {
            this.first = first;
        }
    }

    public static class Words {
        private String words;
        public void setWords(String words) {
            this.words = words;
        }
        public String getWords() {
            return words;
        }
    }
}

3.身份证识别结果类IdCardBean.java:

package yui.bss.baidu.bean;

import com.alibaba.fastjson.annotation.JSONField;

/**
* @author chenyuan
* @version 创建时间:2018年3月19日 下午4:20:32
* @ClassName 类名称
* @Description 类描述
*/
public class IdCardBean {
    /**
     * direction 图像方向,当detect_direction=true时存在。-1:未定义,- 0:正向,- 1: 逆时针90度,- 2:逆时针180度,- 3:逆时针270度
     * image_status normal-识别正常 reversed_side-身份证正反面颠倒 non_idcard-上传的图片中不包含身份证 blurred-身份证模糊 other_type_card-其他类型证照 over_exposure-身份证关键字段反光或过曝 unknown-未知状态
     * risk_type 输入参数 detect_risk = true 时,则返回该字段识别身份证类型: normal-正常身份证;copy-复印件;temporary-临时身份证;screen-翻拍;unknow-其他未知情况
     * edit_tool 如果参数 detect_risk = true 时,则返回此字段。如果检测身份证被编辑过,该字段指定编辑软件名称,如:Adobe Photoshop CC 2014 (Macintosh),如果没有被编辑过则返回值无此参数
     * log_id 唯一的log id,用于问题定位
     * words_result定位和识别结果数组
     * words_result_num 识别结果数,表示words_result的元素个数
     * +location    位置数组(坐标0点为左上角)
     * ++left   表示定位位置的长方形左上顶点的水平坐标
     * ++top    表示定位位置的长方形左上顶点的垂直坐标
     * ++width  表示定位位置的长方形的宽度
     * ++height 表示定位位置的长方形的高度
     * +words   识别结果字符串
     */
    private Long log_id;
    private int words_result_num;
    private int direction;
    private String image_status;
    private WordsResult words_result;
    private String edit_tool;
    private String risk_type;
    public Long getLog_id() {
        return log_id;
    }
    public void setLog_id(Long log_id) {
        this.log_id = log_id;
    }

    public int getWords_result_num() {
        return words_result_num;
    }

    public void setWords_result_num(int words_result_num) {
        this.words_result_num = words_result_num;
    }

    public int getDirection() {
        return direction;
    }

    public void setDirection(int direction) {
        this.direction = direction;
    }

    public String getImage_status() {
        return image_status;
    }

    public void setImage_status(String image_status) {
        this.image_status = image_status;
    }
    public WordsResult getWords_result() {
        return words_result;
    }
    public void setWords_result(WordsResult words_result) {
        this.words_result = words_result;
    }

    public String getEdit_tool() {
        return edit_tool;
    }
    public void setEdit_tool(String edit_tool) {
        this.edit_tool = edit_tool;
    }
    public String getRisk_type() {
        return risk_type;
    }
    public void setRisk_type(String risk_type) {
        this.risk_type = risk_type;
    }
    //为了友好解析,使用了FastJson对源数据key中文的解析
    public static class WordsResult {
        @JSONField(name="住址")
        private Address address;
        @JSONField(name="出生")
        private Birth birth;
        @JSONField(name="姓名")
        private Name name;
        @JSONField(name="公民身份号码")
        private IdCardNum idCardNum;
        @JSONField(name="性别")
        private Sex sex;
        @JSONField(name="民族")
        private Nation nation;
        @JSONField(name="签发日期")
        private IssueDate issueDate;
        @JSONField(name="签发机关")
        private Authority authority;
        @JSONField(name="失效日期")
        private ExpiryDate expiryDate;
        public Address getAddress() {
            return address;
        }
        public void setAddress(Address address) {
            this.address = address;
        }
        public Birth getBirth() {
            return birth;
        }
        public void setBirth(Birth birth) {
            this.birth = birth;
        }
        public Name getName() {
            return name;
        }
        public void setName(Name name) {
            this.name = name;
        }
        public IdCardNum getIdCardNum() {
            return idCardNum;
        }
        public void setIdCardNum(IdCardNum idCardNum) {
            this.idCardNum = idCardNum;
        }
        public Sex getSex() {
            return sex;
        }
        public void setSex(Sex sex) {
            this.sex = sex;
        }
        public Nation getNation() {
            return nation;
        }
        public void setNation(Nation nation) {
            this.nation = nation;
        }
        public IssueDate getIssueDate() {
            return issueDate;
        }
        public void setIssueDate(IssueDate issueDate) {
            this.issueDate = issueDate;
        }
        public Authority getAuthority() {
            return authority;
        }
        public void setAuthority(Authority authority) {
            this.authority = authority;
        }
        public ExpiryDate getExpiryDate() {
            return expiryDate;
        }
        public void setExpiryDate(ExpiryDate expiryDate) {
            this.expiryDate = expiryDate;
        }
    }
    public static class Address {
        private Location location;
        private String words;
        public void setLocation(Location location) {
             this.location = location;
         }
         public Location getLocation() {
             return location;
         }

        public void setWords(String words) {
             this.words = words;
         }
         public String getWords() {
             return words;
         }
    }
    public static class Birth {
        private Location location;
        private String words;
        public void setLocation(Location location) {
             this.location = location;
         }
         public Location getLocation() {
             return location;
         }

        public void setWords(String words) {
             this.words = words;
         }
         public String getWords() {
             return words;
         }
    }
    public static class Nation {
        private Location location;
        private String words;
        public void setLocation(Location location) {
             this.location = location;
         }
         public Location getLocation() {
             return location;
         }
        public void setWords(String words) {
             this.words = words;
         }
         public String getWords() {
             return words;
         }
    }
    public static class Sex {
        private Location location;
        private String words;
        public void setLocation(Location location) {
             this.location = location;
         }
         public Location getLocation() {
             return location;
         }

        public void setWords(String words) {
             this.words = words;
         }
         public String getWords() {
             return words;
         }
    }
    public static class IdCardNum {
        private Location location;
        private String words;
        public void setLocation(Location location) {
             this.location = location;
         }
         public Location getLocation() {
             return location;
         }

        public void setWords(String words) {
             this.words = words;
         }
         public String getWords() {
             return words;
         }
    }
    public static class Name {
        private Location location;
        private String words;
        public void setLocation(Location location) {
             this.location = location;
         }
         public Location getLocation() {
             return location;
         }

        public void setWords(String words) {
             this.words = words;
         }
         public String getWords() {
             return words;
         }
    }
    public static class IssueDate {
        private Location location;
        private String words;
        public void setLocation(Location location) {
             this.location = location;
         }
         public Location getLocation() {
             return location;
         }

        public void setWords(String words) {
             this.words = words;
         }
         public String getWords() {
             return words;
         }
    }
    public static class Authority {
        private Location location;
        private String words;
        public void setLocation(Location location) {
             this.location = location;
         }
         public Location getLocation() {
             return location;
         }

        public void setWords(String words) {
             this.words = words;
         }
         public String getWords() {
             return words;
         }
    }
    public static class ExpiryDate {
        private Location location;
        private String words;
        public void setLocation(Location location) {
             this.location = location;
         }
         public Location getLocation() {
             return location;
         }

        public void setWords(String words) {
             this.words = words;
         }
         public String getWords() {
             return words;
         }
    }
    public static class Location {
        private int width;
        private int top;
        private int height;
        private int left;
        public void setWidth(int width) {
             this.width = width;
         }
         public int getWidth() {
             return width;
         }

        public void setTop(int top) {
             this.top = top;
         }
         public int getTop() {
             return top;
         }

        public void setHeight(int height) {
             this.height = height;
         }
         public int getHeight() {
             return height;
         }

        public void setLeft(int left) {
             this.left = left;
         }
         public int getLeft() {
             return left;
         }
    }
}

4.驾驶证识别结果类PlateLicense.java:

package yui.bss.baidu.bean;

import java.util.List;

/**
 * @author chenyuan
 * @version 创建时间:2018年3月19日 下午5:20:20
 * @ClassName 类名称
 * @Description 类描述
 */
public class PlateLicense {
    private long log_id;
    private List<Words_result> words_result;

    public void setLog_id(long log_id) {
        this.log_id = log_id;
    }

    public long getLog_id() {
        return log_id;
    }
    public List<Words_result> getWords_result() {
        return words_result;
    }

    public void setWords_result(List<Words_result> words_result) {
        this.words_result = words_result;
    }
    public static class Words_result {

        private String color;
        private String number;

        public void setColor(String color) {
            this.color = color;
        }

        public String getColor() {
            return color;
        }

        public void setNumber(String number) {
            this.number = number;
        }

        public String getNumber() {
            return number;
        }

    }
}

到此,银行卡,身份证,驾驶证识别信息已经做完.

第三、 测试

测试使用springMVC框架写个接口如下:

/**
     * 身份证图片扫描
     *
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/baiduIdcard", method = RequestMethod.POST)
    @ResponseBody
    public Object baiduIdcard(@RequestParam(value = "imgUrl", required = true) String imgUrl){
        try {
            IdCardBean idCardFront = baiduImgMgrx.doBaiduIdCard(imgUrl);
            return buildObj(idCardFront);
        } catch (Exception e) {
            logger.info("error.", e);
            return buildFailure("百度身份证验证失败");
        }
    }

    /**
     * 银行卡扫描
     *
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/bankCard", method = RequestMethod.POST)
    @ResponseBody
    public Object bankCard(@RequestParam(value = "imgUrl", required = true) String imgUrl){
        try {
            BankCardBean bankCardBean = baiduImgMgrx.doBankCard(imgUrl);
            return buildObj(bankCardBean);
        } catch (Exception e) {
            logger.info("error.", e);
            return buildFailure("银行卡扫描失败");
        }
    }

    /**
     * 驾驶证识别
     *
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/drivingLicense", method = RequestMethod.POST)
    @ResponseBody
    public Object drivingLicense(@RequestParam(value = "imgUrl", required = true) String imgUrl){
        try {
            DrivingLicenseBean drivingLicenseBean = baiduImgMgrx.doDrivingLicense(imgUrl);
            return buildObj(drivingLicenseBean);
        } catch (Exception e) {
            logger.info("error.", e);
            return buildFailure("车牌识别失败");
        }
    }

    /**
     * 车牌识别
     *
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/plateLicense", method = RequestMethod.POST)
    @ResponseBody
    public Object plateLicense(@RequestParam(value = "imgUrl", required = true) String imgUrl){
        try {
            PlateLicense plateLicense = baiduImgMgrx.doPlateLicense(imgUrl);
            return buildObj(plateLicense);
        } catch (Exception e) {
            logger.info("error.", e);
            return buildFailure("车牌识别失败");
        }
    }

结果如下:
1.银行卡图片识别结果,图片地址.
结果如下:

{
    "data": {
        "result": {
            "bank_card_number": "5187 1088 8888 8888", 
            "bank_card_type": 2, 
            "bank_name": "招商银行"
        }, 
        "log_id": 6611694109754502000
    }, 
    "status": "200"
}

2.驾驶证识别结果如下(图片地址):

{
    "data": {
        "log_id": "7864365883458190264", 
        "words_result": {
            "certNo": {
                "words": "440782198905114717"
            }, 
            "valdTm": {
                "words": "6年"
            }, 
            "canCar": {
                "words": "C1"
            }, 
            "valdFm": {
                "words": "20120229"
            }, 
            "address": {
                "words": "广东省江门市新会区沙堆镇沙西富成北社13巷21号"
            }, 
            "name": {
                "words": "郑嘉荣"
            }, 
            "country": {
                "words": "中国"
            }, 
            "birthday": {
                "words": "19890511"
            }, 
            "sex": {
                "words": "男"
            }, 
            "first": {
                "words": "20120229"
            }
        }
    }, 
    "status": "200"
}

3.车牌识别结果如下.图片地址

{
    "data": {
        "log_id": 7459084314014470000, 
        "words_result": [
            {
                "color": "blue", 
                "number": "赣B2B250"
            }
        ]
    }, 
    "status": "200"
}

4.身份证识别结果如下:

{
    "data": {
        "log_id": 1647048351325783600, 
        "words_result_num": 6, 
        "direction": 3, 
        "image_status": "normal", 
        "words_result": {
            "address": {
                "location": {
                    "width": 501, 
                    "top": 962, 
                    "height": 1446, 
                    "left": 832 }, 
                "words": "浙江省宁波XXXXX"
            }, 
            "birth": {
                "location": {
                    "width": 127, 
                    "top": 975, 
                    "height": 997, 
                    "left": 1497 }, 
                "words": "19871210"
            }, 
            "name": {
                "location": {
                    "width": 150, 
                    "top": 987, 
                    "height": 375, 
                    "left": 2049 }, 
                "words": "陈X"
            }, 
            "idCardNum": {
                "location": {
                    "width": 140, 
                    "top": 1543, 
                    "height": 1899, 
                    "left": 477 }, 
                "words": "43249871210601XXX"
            }, 
            "sex": {
                "location": {
                    "width": 0, 
                    "top": 0, 
                    "height": 0, 
                    "left": 0 }, 
                "words": "男"
            }, 
            "nation": {
                "location": {
                    "width": 111, 
                    "top": 1700, 
                    "height": 91, 
                    "left": 1767 }, 
                "words": "汉"
            }, 
            "issueDate": null, 
            "authority": null, 
            "expiryDate": null
        }, 
        "edit_tool": null, 
        "risk_type": null
    }, 
    "status": "200"
}

第四 总结

想具体了解整个过程,请稳步百度AI开放平台”文字识别“文档.这里还有不使用SDK接入的(API)(http://ai.baidu.com/docs#/Auth/top)

猜你喜欢

转载自blog.csdn.net/achenyuan/article/details/79616063