整合百度AI实现手机拍照识别车牌号

一、功能需求
如图所示,上报时不仅可以手动输入车牌号,还允许拍照自动识别车牌,填充到输入框。
这里写图片描述

二、思路
拟采用百度AI实现该功能(http://ai.baidu.com/docs#/OCR-API/5116ac95
这里写图片描述

根据百度的文档描述,初步明确需要的几个参数为:
1、应用的API Key
2、应用的Secret Key
3、access_token
4、图片数据

官方文档给的提示比较混乱,这一点那一点,刚接触的人会觉得比较晕,我按照自己的思路重新整理了一下。

三、步骤
1、先去百度AI后台创建一个应用,获取到相应的两个KEY
https://console.bce.baidu.com/ai/
这里写图片描述

2、获取access_token
文档:http://ai.baidu.com/docs#/Auth/top
这里写图片描述

注意:access_token的有效期为30天,需要每30天进行定期更换;

前端代码

<script>
        var token = sessionStorage.getItem("accessToken");
        if (token == null || token == '') {
            $.ajax({
                url: "${ctx!}/mobile/index/baidu",
                type: "GET",
                dataType: "JSON",
                data: {},
                success: function (message) {
                    sessionStorage.setItem("accessToken", message.data.token);
                },
                error: function (e) {

                }
            });
        }
    </script>

后端代码

 /**
     * 获取百度AI应用数据.
     *
     * @param map map
     * @return message
     */
    @CrossOrigin
    @RequestMapping(value = "/baidu", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public Message getAi(Model map) {
        Message message = new Message();
        String url = Constants.BAIDU_AI_TOKEN + clientId + "&client_secret=" + clientSecret + "";
        String data = HttpUtil.httpRequest(url);
        String accessToken = JSONObject.parseObject(data).getString("access_token");
        map.addAttribute("token", accessToken);
        message.setData(map);
        message.setSuccess(Boolean.TRUE);
        return message;
    }

3、图片数据
文档:http://ai.baidu.com/docs#/OCR-API/0d9adafa (车牌识别所需参数格式要求参考的是该文档)
这里写图片描述
【image】参数
这里的image我采用的是base64编码。

格式文档:http://ai.baidu.com/docs#/OCR-API/0d9adafa
这里写图片描述

(1)、注意:图片的base64编码是不包含图片头的,如(data:image/jpg;base64,)

在这一步需要前端获取图片,并将图片转成base64编码,js代码如下:

前端代码

$("#file1").change(function () {
        var file1 = document.getElementById("file1").files;
        file1 = validateUp(file1);
        var url = window.URL.createObjectURL(file1[0]);
        //转base64
        var canvas = document.createElement('CANVAS'),
            ctx = canvas.getContext('2d'),
            img2 = new Image;
        img2.crossOrigin = 'Anonymous';
        img2.onload = function () {
            var height = img2.height;
            //console.log("========原始高========" + height);
            var width = img2.width;
            //console.log("========原始宽========" + width);
            if (height > width) {
                height = img2.width;
                width = img2.height;
                //console.log("====" + width + "====转换height========" + height + "===" + height + "==转换width======" + width);
            }
            var scale = width / height;
            //console.log("--比例--" + scale);
            // 图片宽度压缩
            var width1 = img2.width;
            if (width < 500) {
                width1 = width;
            } else if (width < 1000) {
                width1 = width / 2;
            } else if (width < 2000) {
                width1 = width / 4;
            } else if (width < 3000) {
                width1 = width / 6;
            } else if (width < 4000) {
                width1 = width / 8;
            } else if (width < 5000) {
                width1 = width / 10;
            }
            //console.log("========调整后宽========" + width1);
            //console.log("========调整后高========" + parseInt(width1 / scale));

            // 创建属性节点
            var anw = document.createAttribute("width");
            anw.nodeValue = width1;
            var anh = document.createAttribute("height");
            anh.nodeValue = parseInt(width1 / scale);
            canvas.setAttributeNode(anw);
            canvas.setAttributeNode(anh);
            ctx.drawImage(img2, 0, 0, width1, parseInt(width1 / scale));
            var base64 = canvas.toDataURL('image/jpeg', 0.1);
            if (base64 != null && base64 != "" && base64 != "undefined") {
                var imgData = base64.replace("data:image/jpeg;base64,", "");
                //imgData = encodeURI(imgData);
                getLicense(imgData);
                //console.info("========images========" + JSON.stringify(imgData));
            }
            canvas = null;
        };
        img2.src = url;
    })

这里取到的【imgData】就不包含头部信息了。

(2)、图像数据,base64编码后进行urlencode,要求base64编码和urlencode后大小不超过4M,最短边至少15px,最长边最大4096px,支持jpg/png/bmp格式,当image字段存在时url字段失效

我采用后台去请求接口获取车牌号,所以要将access_token和image传到后台,对image进行urlencode参照的是下图方法:
这里写图片描述

至此,所需要的4个参数都已准备完毕。

4、后台发起POST请求获取参数

后端代码

/**
     * 获取车牌号.
     *
     * @param base64 base64
     * @param token  token
     * @param map    map
     * @return message
     */
    @CrossOrigin
    @RequestMapping(value = "/getLicense", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public Message getLicense(@RequestParam(value = "base64") String base64, @RequestParam(value = "token")
            String token, Model map) {
        Message message = new Message();
        try {
            String base = HttpUtil.urlEncode("image", "UTF-8") + "=" +
                    HttpUtil.urlEncode(base64, "UTF-8");
            String url = Constants.BAIDU_AI_LICENSE;
            String result = HttpUtil.post(url, token, base);
            String license = JSONObject.parseObject(result).getJSONObject("words_result").getString("number");
            if (!Strings.isNullOrEmpty(license)) {
                map.addAttribute("license", license);
                message.setData(map);
                message.setSuccess(Boolean.TRUE);
            } else {
                message.setSuccess(Boolean.FALSE);
            }
        } catch (Exception e) {
            message.setSuccess(Boolean.FALSE);
        }
        return message;
    }

DEBUG调试看下数据是否拿到:
这里写图片描述

四、效果展示
这里写图片描述

这里写图片描述

这里写图片描述

五、注意事项:
1、access_token有有效期,需要定期更换。
2、图片大小限制(分辨率、字节数)。
后台发起请求获取车牌号,一张图片从前台传到后台,再调用百度API,相当于传递两次,图片太大的话会造成访问过慢,用户体验不好。但是图片过小、分辨率压缩的过低,又会降低识别成功率。所以这里对处理图片的参数设置需要自己去把握,更好的平衡利弊。

六、资源
HttpUtil下载地址:https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3

猜你喜欢

转载自blog.csdn.net/tonyfreak/article/details/80748768