当前位置: 首页 > news >正文

2023/8/16 华为云OCR识别驾驶证、行驶证

目录

一、 注册华为云账号开通识别驾驶证、行驶证服务

二、编写配置文件

        2.1、配置秘钥

        2.2、 编写配置工具类

三、接口测试

        3.1、测试接口

        3.2、结果

 四、实际工作中遇到的问题

        4.1、前端传值问题

        4.2、后端获取数据问题

        4.3、使用openfeign调用接口报错

        4.3、前端显示问题


hello大家好,好久没写博客了,你们找到工作了吗?博主在去年11月成功找到工作,到现在上班大半年了,最近需求用到华为云OCR文字识别,这里就详细记录一下!

一、 注册华为云账号开通识别驾驶证、行驶证服务

华为云官网:特惠专区_云服务器_云主机_企业上云-华为云

 如上图所示,华为云还有很多文字识别服务,这个看个人需求了解即可。

 开放api接口地址体验:https://console.huaweicloud.com/apiexplorer/#/openapi/OCR/debug?api=RecognizeDriverLicense

二、编写配置文件

        2.1、配置秘钥

ocr:projectId: xxxxxxxxxxxxxx   // 项目id:华为云个人凭证获取area: cn-north-4        // 区域:北京4区,目前好像只有北京4区支持这两个证件的识别服务ak: xxxxxxxxxxxxx        //AK:华为云个人凭证获取sk: xxxxxxxxxxxxx        //SK:华为云个人凭证获取

        2.2、 编写配置工具类

@Component
public class OcrUtil {private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);@Value("${ocr.projectId}")private String projectId;@Value("${ocr.area}")private String area;@Value("${ocr.ak}")private String AK;@Value("${ocr.sk}")private String SK;private static CloseableHttpClient httpClient;static {PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();cm.setMaxTotal(100);cm.setDefaultMaxPerRoute(20);cm.setDefaultMaxPerRoute(50);httpClient = HttpClients.custom().setConnectionManager(cm).build();}public String getTokenByAKSK (){String url = "https://iam."+area+".myhuaweicloud.com/v3/auth/tokens";Map<String,String> p1 = new HashMap<>();Map<String,Object> p2 = new HashMap<>();Map<String,Object> p3 = new HashMap<>();Map<String,Object> p4 = new HashMap<>();Map<String,Object> p5 = new HashMap<>();Map<String,Object> p6 = new HashMap<>();Map<String,Object> p7 = new HashMap<>();Map<String,Object> p8 = new HashMap<>();p1.put("key",AK);p2.put("key",SK);p3.put("access",p1);p3.put("secret",p2);p4.put("hw_ak_sk",p3);String[] str = new String[1];str[0] = "hw_ak_sk";p4.put("methods",str);p5.put("identity",p4);p6.put("name",area);p7.put("project",p6);p5.put("scope",p7);p8.put("auth",p5);String result = postJson(url, JSON.toJSONString(p8));return result;}public static String postJson(String url, String jsonString) {CloseableHttpResponse response = null;String result = "";try {HttpPost httpPost = new HttpPost(url);RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();httpPost.setConfig(requestConfig);httpPost.setConfig(requestConfig);httpPost.addHeader("Content-type", "application/json; charset=utf-8");httpPost.setHeader("Accept", "application/json");httpPost.setEntity(new StringEntity(jsonString, StandardCharsets.UTF_8));response = httpClient.execute(httpPost);Header[] h = response.getAllHeaders();for(Header header : h){if(header.getName().equals("X-Subject-Token")){result = header.getValue();}}} catch (IOException e) {log.error("调用HttpUtils.Post IOException, url=" + url + ",param=" + jsonString, e);} finally {try {if (response != null) {response.close();}} catch (IOException e) {log.error("调用HttpUtils.Post IOException, url=" + url + ",param=" + jsonString, e);}}return result;}public static Result postJson(String url, String token, String jsonString) {CloseableHttpResponse response = null;BufferedReader in;String result = "";boolean err = false;try {HttpPost httpPost = new HttpPost(url);RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();httpPost.setConfig(requestConfig);httpPost.setConfig(requestConfig);httpPost.addHeader("Content-type", "application/json; charset=utf-8");httpPost.setHeader("Accept", "application/json");httpPost.setHeader("X-Auth-Token", token);httpPost.setEntity(new StringEntity(jsonString, StandardCharsets.UTF_8));response = httpClient.execute(httpPost);in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));StringBuilder sb = new StringBuilder();String line;String NL = System.getProperty("line.separator");while ((line = in.readLine()) != null) {sb.append(line).append(NL);}in.close();result = sb.toString();err = response.getStatusLine().getStatusCode() == 400;} catch (IOException e) {log.error("调用HttpUtils.Post IOException, url=" + url + ",param=" + jsonString, e);} finally {try {if (response != null) {response.close();}} catch (IOException e) {log.error("调用HttpUtils.Post IOException, url=" + url + ",param=" + jsonString, e);}}if (err) {return Result.error().data("data", result);} else {return Result.ok().data("data", result);}}/*** 功能描述:* 华为云驾驶证识别* @Param: [token, imageUrl]* @Return: com.ruoyi.phaseone.common.utils.R* @Author: Mr.Huang* @Date: 2023/8/10 10:21**/public Result driverLicense(String token, String imageUrl) {String url = "https://ocr."+area+".myhuaweicloud.com/v2/"+projectId+"/ocr/driver-license";Map<String, Object> p = new HashMap<>();// url:图片地址  image:图片的base64数据 两个参数二选一,详情见官网APIp.put("url", imageUrl);p.put("side", "front");log.info("ocr驾驶证识别请求路径:{},请求参数:{}",url,p);return postJson(url, token, JSON.toJSONString(p));}/*** 功能描述:* 华为云行驶证识别* @Param: [token, imageUrl]* @Return: com.sy.milkteasyservice.response.Result* @Author: Mr.Huang* @Date: 2023/8/14 10:52**/public Result vehicleLicense(String token, String imageUrl) {String url = "https://ocr."+area+".myhuaweicloud.com/v2/"+projectId+"/ocr/vehicle-license";Map<String, Object> p = new HashMap<>();// url:图片地址  image:图片的base64数据 两个参数二选一,详情见官网APIp.put("url", imageUrl);// front:行驶证主页  back:行驶证副页p.put("side", "front");log.info("ocr行驶证识别请求路径:{},请求参数:{}",url,p);return postJson(url, token, JSON.toJSONString(p));}
}

调用此接口的流程就是:获取token后设置请求头,发起请求获得结果

三、接口测试

        3.1、测试接口

@RestController
public class HuaWeiObsController {@Autowiredprivate ObsService ObsService;@Autowiredprivate OcrUtil ocrUtil;@ApiOperation(value = "上传图片文件",notes = "xxxxx")@PostMapping("/uploadImgFile")public Result upload(MultipartFile file){String url = ObsService.upload(file);// 行驶证识别/*        Result result = ocrUtil.vehicleLicense(ocrUtil.getTokenByAKSK(), url);System.out.println("调用华为云行驶证识别结果:"+result.toString());Map<String, Object> data = result.getData();Object data1 = data.get("data");JSONObject jsonObject = JSON.parseObject(data1.toString());String result1 = jsonObject.get("result").toString();System.out.println(result1);vehicleLicense vehicleLicense = JSON.parseObject(result1, vehicleLicense.class);System.out.println("orc识别结果是:"+vehicleLicense.toString());return Result.ok().data("result",vehicleLicense).data("url",url);*/// 驾驶证识别Result result = ocrUtil.driverLicense(ocrUtil.getTokenByAKSK(), url);System.out.println("调度接口获取的结果集:"+result);Map<String, Object> data = result.getData();Object data1 = data.get("data");JSONObject jsonObject = JSON.parseObject(data1.toString());String result1 = jsonObject.get("result").toString();System.out.println(result1);drivingLicence drivingLicence = JSON.parseObject(result1, drivingLicence.class);System.out.println("orc识别结果是:"+drivingLicence.toString());return Result.ok().data("result",drivingLicence).data("url",url);}
}

这里的文件上传用的是华为云的OBS服务,上传图片后拿到该图片对应的地址,注意:此图片地址必须要可以访问,如设置访问权限则会调用接口失败!

        3.2、结果

 

 

 四、实际工作中遇到的问题

        4.1、前端传值问题

问题描述:由于前端使用的是根据el-upload封装后的组件,我发现驾驶证和行驶证上传到的是同一个接口,那这样就分不清上传的驾驶证还是行驶证。

解决办法:在调用后端接口传入图片类型字段,判断是驾驶证还是行驶证

:action="this.$http.adornUrl(`/proxyKpiApi/${config.uploadUrl}?${config.id ? `id=${config.id}&` : ''}token=${$cookie.get('token')}&${config.type ? `type=${config.type}` : ''}`)"

 

        4.2、后端获取数据问题

问题描述:项目中使用的华为云obs文件上传服务,但是上传后获得的图片地址因为安全性考虑,不能直接访问,导致调用接口失败。

 

    // openfeign驾驶证服务@PostMapping(value = "/performance/driverLicense", params = "{url={url}}")R driverLicense(@RequestParam("url") String url);// openfeign行驶证服务@PostMapping(value = "/performance/vehicleLicense", params = "{url={url}}")R vehicleLicense(@RequestParam("url") String url);

解决办法:将上传的文件转换成base64格式,调用接口时改成使用image参数,图片的base64数据。

                if(StringUtils.isNotBlank(type)){byte[] fileBytes = file.getBytes();// 将上传的文件转换成base64格式String base64String = Base64.getEncoder().encodeToString(fileBytes);if(type.equals("driverLicense")){// 远程调用识别驾驶证服务com.ruoyi.phaseone.common.utils.R r = carrierPerformanceService.driverLicense(base64String);log.info("ocr驾驶证识别请求结果:{}",r);if(String.valueOf(r.get("code")).equals("0")){Object data = r.get("data");JSONObject jsonObject = JSON.parseObject(data.toString());String result1 = jsonObject.get("result").toString();DrivingLicenceEntity drivingLicenceEntity = JSON.parseObject(result1, DrivingLicenceEntity.class);map.put("ocrResult",drivingLicenceEntity);}}else if(type.equals("vehicleLicense")){// 远程调用识别行驶证服务com.ruoyi.phaseone.common.utils.R r = carrierPerformanceService.vehicleLicense(base64String);log.info("ocr行驶证识别请求结果:{}",r);if(String.valueOf(r.get("code")).equals("0")){Object data = r.get("data");JSONObject jsonObject = JSON.parseObject(data.toString());String result1 = jsonObject.get("result").toString();VehicleLicenseEntity vehicleLicenseEntity = JSON.parseObject(result1, VehicleLicenseEntity.class);map.put("ocrResult",vehicleLicenseEntity);}}}

        4.3、使用openfeign调用接口报错

问题描述:按照上面步骤修改后,由于项目是微服务架构,文件上传服务和前端调用的接口不在同一个服务上,所以要使用openfeign远程调用。但是调用的过程中报错了。报错信息:[<h1>Bad Message 414</h1><pre>reason: URI Too Long</pre>]

解决办法:此问题是因为图片数据转换成base64后,通过远程调用传的值URI太长了,因此我们将接口改造一下,将参数改成对象。

@Data
public class ImageEntity implements Serializable {private String imageUrl;private String imageBase64;
}
    // openfeign驾驶证服务@PostMapping( "/performance/driverLicense")R driverLicense(@RequestBody ImageEntity image);// openfeign行驶证服务@PostMapping("/performance/vehicleLicense")R vehicleLicense(@RequestBody ImageEntity image);
                if(StringUtils.isNotBlank(type)){byte[] fileBytes = file.getBytes();// 将上传的文件转换成base64格式String base64String = Base64.getEncoder().encodeToString(fileBytes);ImageEntity image =new ImageEntity();image.setImageBase64(base64String);if(type.equals("driverLicense")){// 远程调用识别驾驶证服务com.ruoyi.phaseone.common.utils.R r = carrierPerformanceService.driverLicense(image);log.info("ocr驾驶证识别请求结果:{}",r);if(String.valueOf(r.get("code")).equals("0")){Object data = r.get("data");JSONObject jsonObject = JSON.parseObject(data.toString());String result1 = jsonObject.get("result").toString();DrivingLicenceEntity drivingLicenceEntity = JSON.parseObject(result1, DrivingLicenceEntity.class);map.put("ocrResult",drivingLicenceEntity);}}else if(type.equals("vehicleLicense")){// 远程调用识别行驶证服务com.ruoyi.phaseone.common.utils.R r = carrierPerformanceService.vehicleLicense(image);log.info("ocr行驶证识别请求结果:{}",r);if(String.valueOf(r.get("code")).equals("0")){Object data = r.get("data");JSONObject jsonObject = JSON.parseObject(data.toString());String result1 = jsonObject.get("result").toString();VehicleLicenseEntity vehicleLicenseEntity = JSON.parseObject(result1, VehicleLicenseEntity.class);map.put("ocrResult",vehicleLicenseEntity);}}}

        4.3、前端显示问题

问题描述:调用接口成功后,由于前端使用的是el-upload封装后的组件,用的watch函数监听值的变化,每次打开该控件都会显示其结果。

    watch: {'dataForm.carLicence.attachments' (newVal, oldVal) {}

解决方案:判断newVal中的ocrResult是否为空,不为空在赋值,因为可以上传多个文件,所以每次更新选取集合中最后一个元素的数据

    watch: {'dataForm.carLicence.attachments' (newVal, oldVal) {if (newVal[newVal.length - 1] && newVal[newVal.length - 1].ocrResult !== undefined && newVal[newVal.length - 1].ocrResult !== null) {// 车牌号this.dataForm.carNumber = newVal[newVal.length - 1].ocrResult.number;// 发动机号this.dataForm.engineNumber = newVal[newVal.length - 1].ocrResult.engine_no;// 所有人this.dataForm.carLicence.person = newVal[newVal.length - 1].ocrResult.name;// 品牌型号this.dataForm.carLicence.brandModel = newVal[newVal.length - 1].ocrResult.model;// 注册日期this.dataForm.carLicence.registerTime = newVal[newVal.length - 1].ocrResult.register_date;// 发证日期this.dataForm.carLicence.certificationTime = newVal[newVal.length - 1].ocrResult.issue_date;}}},

http://www.lryc.cn/news/134801.html

相关文章:

  • 【Java开发】 Mybatis-Plus 07:创建时间、更新时间自动添加
  • 解决vue2项目在IE11浏览器中无画面的兼容问题
  • 信号
  • 产品经理的真实薪资有多少?今天带你看看
  • 《一个操作系统的实现》windows用vm安装CentOS——从bochs环境搭建到第一个demo跑通
  • 线程Thread
  • 如何使用CSS实现一个渐变背景效果?
  • 初始C语言(7)——详细讲解有关初阶指针的内容
  • ArcGIS Pro技术应用(暨基础入门、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合、案例应用)
  • RISC-V公测平台发布 · 数据库在RISC-V服务器上的适配评估
  • UE5.2 LyraDemo源码阅读笔记(五)输入系统
  • 线段树详解——影子宽度
  • 使用R语言绘制折线图
  • 无涯教程-Perl - wantarray函数
  • 【gitkraken】gitkraken自动更新问题
  • 《Java Web程序设计》试卷03
  • 怎么查看小程序中的会员信息
  • 网络安全—黑客—自学笔记
  • 深度解读波卡 2.0:多核、更有韧性、以应用为中心
  • 微服务中间件--Eureka注册中心
  • 积跬步至千里 || 矩阵可视化
  • zookeeper详细介绍
  • 面板市场趋势分析:价格上涨势头或将减缓 | 百能云芯
  • JVM性能调优
  • 【全链路追踪】XXL-JOB添加TraceID
  • [Unity]Lua本地时间、倒计时和正计时。
  • 探究HTTP API接口测试:工具、方法与自动化
  • CSS中如何实现文字溢出省略号(text-overflow: ellipsis)效果?
  • CSDN编程题-每日一练(2023-08-21)
  • 面试题-React(四):React中的事件绑定如何实现?有几种方式?