身份识别web应用
阿里云ai训练营,继续来记一波笔记,今天主要学的是调用阿里的ocr接口来实现一个简单的身份证文字信息识别。附上阿里的demo地址https://github.com/aliyun/alibabacloud-viapi-demo。阿里视觉开放平台地址:https://vision.aliyun.com/。
下边为识别结果图,(文字显示不全是因为选的身份证图片问题,)

下边是需要的pom依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>ocr</artifactId> <version>1.0.3</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.4.6</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.68</version> </dependency>
|
demo的前端界面用thymeleaf渲染的,用了bootstrap的部分样式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <title>VIAPI</title> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"> <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-12 mx-auto"> <h2>VIAPI RecognizeIdentityCard Example</h2> <div class="col-sm-12"> <p th:text="${message}" th:if="${message ne null}" class="alert alert-primary"></p> </div> <form method="post" th:action="@{/upload}" enctype="multipart/form-data"> <div class="col-sm-4"> <div class="input-group"> <input id='location' class="form-control" onclick="$('#i-face').click();"> <label class="input-group-btn"> <input type="button" id="i-check" value="上传人像面" class="btn btn-primary" onclick="$('#i-face').click();"> </label> </div> </div> <input type="file" name="face" id='i-face' accept=".jpg, .png, .jpeg" onchange="$('#location').val($('#i-face').val());" style="display: none"> <div class="col-sm-4"> <div class="input-group"> <input id='location1' class="form-control" onclick="$('#i-back').click();"> <label class="input-group-btn"> <input type="button" id="i-check-1" value="上传国徽面" class="btn btn-primary" onclick="$('#i-back').click();"> </label> </div> </div> <input type="file" name="back" id='i-back' accept=".jpg, .png, .jpeg" onchange="$('#location1').val($('#i-back').val());" style="display: none"> <div class="col-sm-4"> <button type="submit" class="btn btn-primary">开始识别</button> </div> </form>
</div> </div>
<div class="row" style="margin-top: 30px;"> <div class="col-md-12 mx-auto"> <div class="col-sm-4"> <img style="width: 100%;" th:src="${faceImage}" th:if="${faceImage ne null}" class="img-fluid" alt=""/> </div> <div class="col-sm-4"> <img style="width: 100%;" th:src="${backImage}" th:if="${backImage ne null}" class="img-fluid" alt=""/> </div> </div> </div> <div class="row" style="margin-top: 30px;"> <div class="col-md-12 mx-auto"> <div class="col-sm-4"> <p th:if="${faceResult ne null}"><span>姓名:</span><span th:text="${faceResult.name}"></span></p> <p th:if="${faceResult ne null}"><span>性别:</span><span th:text="${faceResult.gender}"></span></p> <p th:if="${faceResult ne null}"><span>民族:</span><span th:text="${faceResult.nationality}"></span></p> <p th:if="${faceResult ne null}"><span>出生日期:</span><span th:text="${faceResult.birthDate}"></span></p> <p th:if="${faceResult ne null}"><span>住址:</span><span th:text="${faceResult.address}"></span></p> <p th:if="${faceResult ne null}"><span>身份证号码:</span><span th:text="${faceResult.IDNumber}"></span></p> </div> <div class="col-sm-4"> <p th:if="${backResult ne null}"><span>签发机关:</span><span th:text="${backResult.issue}"></span></p> <p th:if="${backResult ne null}"><span>有效日期:</span><span th:text="${backResult.startDate}"></span>~<span th:text="${backResult.endDate}"></span></p> </div> </div> </div> </div> </body> </html>
|
后端主要用到的技术栈是springboot和阿里ocr,没用的数据库,上传的图片是存到缓存里边的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @RequestMapping() public String index(Model model) { if (faceImages.size() != backImages.size()) { faceImages.clear(); backImages.clear(); faceResults.clear(); backResults.clear(); } if (!CollectionUtils.isEmpty(faceImages) && faceImages.size() == backImages.size()) { model.addAttribute("faceImage", faceImages.get(faceImages.size() - 1)); model.addAttribute("faceResult", faceResults.get(faceResults.size() - 1)); model.addAttribute("backImage", backImages.get(backImages.size() - 1)); model.addAttribute("backResult", backResults.get(backResults.size() - 1)); } return "index"; }
|
以下是上传文件的控制方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| @PostMapping("/upload") public String uploadFile(@RequestParam("face") MultipartFile face, @RequestParam("back") MultipartFile back, RedirectAttributes attributes) { if (face.isEmpty() || back.isEmpty()) { attributes.addFlashAttribute("message", "Please select a file to upload."); return "redirect:/"; }
String errorMessage = null; try { Path dir = Paths.get(uploadDirectory); if (!Files.exists(dir)) { Files.createDirectories(dir); }
if (!face.isEmpty()) { String filename = saveFile(face); Map<String, String> res = ocrService.RecognizeIdCard(uploadDirectory + filename, "face"); faceImages.add("/images/" + filename); faceResults.add(res); } if (!back.isEmpty()) { String filename = saveFile(back); Map<String, String> res = ocrService.RecognizeIdCard(uploadDirectory + filename, "back"); backImages.add("/images/" + filename); backResults.add(res); } } catch (TeaException e) { e.printStackTrace(); errorMessage = JSON.toJSONString(e.getData()); } catch (Exception e) { e.printStackTrace(); errorMessage = e.getMessage(); }
if (StringUtils.isNotBlank(errorMessage)) { attributes.addFlashAttribute("message", errorMessage); } return "redirect:/"; } private String saveFile(MultipartFile file) throws Exception { String suffix = StringUtils.substringAfterLast(file.getOriginalFilename(), "."); String filename = UUID.randomUUID().toString() + "." + suffix; Path path = Paths.get(uploadDirectory + filename); Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING); return filename; }
|