视觉AI训练营 DAY2 身份证识别系统搭建

本文涉及的产品
个人证照识别,个人证照识别 200次/月
OCR统一识别,每月200次
文档理解,结构化解析 100页
简介: 该项目是通过阿里云自主研发的sdk,实现图片识别功能通过上传身份证照片可以显示出身份证的信息基于springboot实现

本项目使用了Spring boot的框架
阿里云视觉智能开放平台:https://vision.aliyun.com/
这里提供了两个SDK
https://help.aliyun.com/document_detail/144481.html
https://help.aliyun.com/document_detail/153132.html
整体是一个接口调用,前端上传数据,服务器端配置参数向阿里的开放接口发送请求,然后得到返回结果,再处理数据返回到前端页面

<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
    <title>身份证识别</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-xl-12 mx-auto">
                <h1>身份证识别</h1>
                <div class="col-sm-12">
                    <p th:text="${messages}" th:if="${messages != null}" class="alert alert-info"></p>
                </div>
                <form method="post" th:action="@{/upload}" enctype="multipart/form-data">
                    <div class="row">
                        <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="locationf" class="form-control" onclick="$('#i-back').click();">
                                <label class="input-group-btn">
                                    <input type="button" id="i-checkb" 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="$('#locationf').val($('#i-back').val());" style="display: none">
                        <div class="col-sm-4">
                            <button type="submit" class="btn btn-primary form-control">开始识别</button>
                        </div>
                    </div>
                </form>
            </div>
        </div>

        <div class="row" style="margin-top: 38px;">
            <div class="col-md-12 mx-auto">
                <div class="row">
                    <div class="col-sm-4">
                        <img th:src="${faceImage}" th:if="faceImage != null" class="img-fluid">
                    </div>
                    <div class="col-sm-4">
                        <img th:src="${backImage}" th:if="backImage != null" class="img-fluid">
                    </div>
                </div>
            </div>
        </div>
        <div class="row" style="margin-top: 38px;">
            <div class="col-md-12 mx-auto" th:if="${faceResult != null}">
                <div class="row">
                    <div class="col-sm-4">
                        <p><span>姓名: </span><span th:text="${faceResult.name}"></span></p>
                        <p><span>性别: </span><span th:text="${faceResult.gender}"></span></p>
                        <p><span>民族: </span><span th:text="${faceResult.nationality}"></span></p>
                        <p><span>出生日期: </span><span th:text="${faceResult.birthDate}"></span></p>
                        <p><span>住址: </span><span th:text="${faceResult.address}"></span></p>
                        <p><span>身份证号: </span><span th:text="${faceResult.IDNumber}"></span></p>
                    </div>
                    <div class="col-sm-4">
                        <p><span>签发机关: </span><span th:text="${backResult.issue}"></span></p>
                        <p><span>有效日期: </span><span th:text="${backResult.startDate}">-<span th:text="${faceResult.endDate}"></span></span></p>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
</html>

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Controller
public class MainController {

    @Value("${file.uplaod.path}")
    private String uploadDir;
    @Autowired
    private OcrService ocrService;

    private List<String> faceImages = new ArrayList<>();
    private List<String> backImages = new ArrayList<>();
    private List<Map<String, String>> faceResults = new ArrayList<>();
    private List<Map<String, String>> backResults = new ArrayList<>();

    @RequestMapping("/index")
    public String index(Model model) {
        if (faceImages.size() != backImages.size()) {
            clearAllList();
        }
        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";
    }

    @RequestMapping("/test")
    @ResponseBody
    public String test() {
        return "test";
    }

    @PostMapping("/upload")
    public String upload(@RequestParam("face") MultipartFile face, @RequestParam("back") MultipartFile back,
                         RedirectAttributes redirectAttributes) {
        if (face.isEmpty() || back.isEmpty()) {
            redirectAttributes.addFlashAttribute("messages", "请选择一个文件进行上传。");
            return "redirect:/index";
        }
        String errorMessages = null;
        Path dir = Paths.get(uploadDir);
        if (!Files.exists(dir)) {
            try {
                Files.createDirectories(dir);
            } catch (IOException e) {
                e.printStackTrace();
                errorMessages += e.getMessage() + "\n";
            }
        }
        try {
            if (!face.isEmpty()) {
                String filename = saveFile(face);
                Map<String, String> faceResult = ocrService.RecognizeIdCard(uploadDir + filename, "face");
                faceImages.add("/images/" + filename);
                faceResults.add(faceResult);
            }
            if (!back.isEmpty()) {
                String filename = saveFile(back);
                Map<String, String> faceResult = ocrService.RecognizeIdCard(uploadDir + filename, "back");
                backImages.add("/images/" + filename);
                backResults.add(faceResult);
            }
        } catch (Exception e) {
            e.printStackTrace();
            errorMessages += e.getMessage() + "\n";
        }
        if (StringUtils.isNoneBlank(errorMessages)) {
            redirectAttributes.addFlashAttribute("messages", errorMessages);
        }
        return "redirect:/index";
    }

    private void clearAllList() {
        faceImages.clear();
        backImages.clear();
        faceResults.clear();
        backResults.clear();
    }

    public String saveFile(MultipartFile file) {
        String filename = UUID.randomUUID().toString() + "."
                + StringUtils.substringAfterLast(file.getOriginalFilename(), ".");
        Path path = Paths.get(uploadDir + filename);
        try {
            Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            return null;
        }
        return filename;
    }
}
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.aliyun.ocr.Client;
import com.aliyun.ocr.models.Config;
import com.aliyun.ocr.models.RecognizeIdentityCardAdvanceRequest;
import com.aliyun.ocr.models.RecognizeIdentityCardResponse;
import com.aliyun.teautil.models.RuntimeOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;

@Service
public class OcrService {

    private Client orcClient;
    private RuntimeOptions runtimeOptions;

    @Value("${aliapi.accessKeyId}")
    private String accessKeyId;
    @Value("${aliapi.accessKeySecret}")
    private String accessKeySecret;

    @PostConstruct
    private void init() throws Exception {
        Config config = new Config();
        config.endpointType = "access_key";
        config.regionId = "cn-shanghai";
        config.accessKeyId = accessKeyId;
        config.accessKeySecret = accessKeySecret;
        config.endpoint = "ocr.cn-shanghai.aliyuncs.com";

        orcClient = new Client(config);
        runtimeOptions = new RuntimeOptions();
    }


    public Map<String, String> RecognizeIdCard(String fielpath, String side) throws Exception {
        RecognizeIdentityCardAdvanceRequest request = new RecognizeIdentityCardAdvanceRequest();
        request.imageURLObject = Files.newInputStream(Paths.get(fielpath));
        request.side = side;
        RecognizeIdentityCardResponse response = orcClient.recognizeIdentityCardAdvance(request, runtimeOptions);
        return "face".equals(side) ?
                JSON.parseObject(JSON.toJSONString(response.data.frontResult), new TypeReference<Map<String, String>>(){})
                : JSON.parseObject(JSON.toJSONString(response.data.backResult), new TypeReference<Map<String, String>>(){});
    }
}
相关文章
|
23天前
|
机器学习/深度学习 数据采集 人工智能
AI赋能教育:深度学习在个性化学习系统中的应用
【10月更文挑战第26天】随着人工智能的发展,深度学习技术正逐步应用于教育领域,特别是个性化学习系统中。通过分析学生的学习数据,深度学习模型能够精准预测学生的学习表现,并为其推荐合适的学习资源和规划学习路径,从而提供更加高效、有趣和个性化的学习体验。
80 9
|
1月前
|
人工智能 自然语言处理 机器人
对话阿里云 CIO 蒋林泉:AI 时代,企业如何做好智能化系统建设?
10 月 18 日, InfoQ《C 位面对面》栏目邀请到阿里云 CIO 及 aliyun.com 负责人蒋林泉(花名:雁杨),就 AI 时代企业 CIO 的角色转变、企业智能化转型路径、AI 落地实践与人才培养等主题展开了讨论。
797 67
对话阿里云 CIO 蒋林泉:AI 时代,企业如何做好智能化系统建设?
|
1天前
|
机器学习/深度学习 人工智能 算法
【AI系统】AI芯片驱动智能革命
本课程深入解析AI模型设计演进,探讨AI算法如何影响AI芯片设计,涵盖CPU、GPU、FPGA、ASIC等主流AI芯片,旨在全面理解AI系统体系,适应后摩尔定律时代的技术挑战。
18 5
|
1月前
|
存储 人工智能 自然语言处理
高级 RAG 技术:提升生成式 AI 系统输出质量与性能鲁棒性【预检索、检索、检索后、生成优化等】
高级 RAG 技术:提升生成式 AI 系统输出质量与性能鲁棒性【预检索、检索、检索后、生成优化等】
高级 RAG 技术:提升生成式 AI 系统输出质量与性能鲁棒性【预检索、检索、检索后、生成优化等】
|
22天前
|
机器学习/深度学习 人工智能 搜索推荐
AI在医疗领域的革命:智能诊断系统的未来
在科技日新月异的今天,人工智能(AI)技术正逐渐渗透到我们生活的每一个角落,其中医疗领域尤为显著。本文将探讨AI在医疗诊断中的应用及其带来的变革,重点介绍智能诊断系统的发展现状与未来趋势。通过深入浅出的方式,我们将揭示AI如何改变传统医疗模式,提高诊断效率和准确性,最终造福广大患者。
|
1天前
|
机器学习/深度学习 存储 人工智能
【AI系统】计算之比特位宽
本文详细介绍了计算机中整数和浮点数的比特位宽概念及其在AI模型中的应用。通过对比特位宽的定义、整数与浮点数的表示方法、AI中常用的数据类型(如FP32、TF32、FP16、BF16、FP8和Int8)及其在模型训练和推理中的作用进行了阐述。特别关注了FP8数据类型在提高计算性能和减少内存占用方面的新进展,以及降低比特位宽对AI芯片性能的影响,强调了低比特位宽在AI领域的重要性。
14 0
|
28天前
|
人工智能 API 决策智能
swarm Agent框架入门指南:构建与编排多智能体系统的利器 | AI应用开发
Swarm是OpenAI在2024年10月12日宣布开源的一个实验性质的多智能体编排框架。其核心目标是让智能体之间的协调和执行变得更轻量级、更容易控制和测试。Swarm框架的主要特性包括轻量化、易于使用和高度可定制性,非常适合处理大量独立的功能和指令。【10月更文挑战第15天】
208 6
|
20天前
|
机器学习/深度学习 人工智能 算法
AI赋能大学计划·大模型技术与应用实战学生训练营——吉林大学站圆满结营
10月30日,由中国软件行业校园招聘与实习公共服务平台携手魔搭社区共同举办的AI赋能大学计划·大模型技术与产业趋势高校行AIGC项目实战营·吉林大学站圆满结营。
|
21天前
|
人工智能 自然语言处理 安全
AI技术在智能客服系统中的应用与挑战
【10月更文挑战第28天】本文将深入探讨人工智能(AI)技术在智能客服系统中的应用及其面临的挑战。我们将通过实例分析,了解AI如何改善客户服务体验,提高效率和降低成本。同时,我们也将关注AI在实际应用中可能遇到的问题,如语义理解、情感识别和数据安全等,并提出相应的解决方案。
|
23天前
|
安全 搜索推荐 机器学习/深度学习
AI赋能教育:深度学习在个性化学习系统中的应用
【10月更文挑战第26天】在人工智能的推动下,个性化学习系统逐渐成为教育领域的重要趋势。深度学习作为AI的核心技术,在构建个性化学习系统中发挥关键作用。本文探讨了深度学习在个性化推荐系统、智能辅导系统和学习行为分析中的应用,并提供了代码示例,展示了如何使用Keras构建模型预测学生对课程的兴趣。尽管面临数据隐私和模型可解释性等挑战,深度学习仍有望为教育带来更个性化和高效的学习体验。
60 0
下一篇
无影云桌面