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

简介: 该项目是通过阿里云自主研发的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>>(){});
    }
}
相关文章
|
27天前
|
机器学习/深度学习 人工智能 监控
AI算法分析,智慧城管AI智能识别系统源码
AI视频分析技术应用于智慧城管系统,通过监控摄像头实时识别违法行为,如违规摆摊、垃圾、违章停车等,实现非现场执法和预警。算法平台检测街面秩序(出店、游商、机动车、占道)和市容环境(垃圾、晾晒、垃圾桶、路面不洁、漂浮物、乱堆物料),助力及时处理问题,提升城市管理效率。
AI算法分析,智慧城管AI智能识别系统源码
|
1天前
|
人工智能 前端开发 Java
Java语言开发的AI智慧导诊系统源码springboot+redis 3D互联网智导诊系统源码
智慧导诊解决盲目就诊问题,减轻分诊工作压力。降低挂错号比例,优化就诊流程,有效提高线上线下医疗机构接诊效率。可通过人体画像选择症状部位,了解对应病症信息和推荐就医科室。
27 10
|
5天前
|
人工智能 编解码 安全
揭秘AI幻觉:GPT-4V存在视觉编码漏洞,清华联合NUS提出LLaVA-UHD
【4月更文挑战第14天】清华大学与新加坡国立大学团队针对大型多模态模型(LMMs)在处理高分辨率图像时的局限,提出新模型LLaVA-UHD。该模型通过图像模块化、压缩和空间模式组织策略,有效提升了处理任意比例和高分辨率图像的能力。实验显示,LLaVA-UHD在9个基准测试中超越现有模型,且在TextVQA任务上准确率提升6.4%,同时训练时间更短。然而,模型训练成本高、泛化能力待优化是未来需解决的问题。
16 8
揭秘AI幻觉:GPT-4V存在视觉编码漏洞,清华联合NUS提出LLaVA-UHD
|
12天前
|
机器学习/深度学习 人工智能 运维
构建未来:AI驱动的自适应网络安全防御系统
【4月更文挑战第7天】 在数字时代的浪潮中,网络安全已成为维系信息完整性、保障用户隐私和确保商业连续性的关键。传统的安全防御策略,受限于其静态性质和对新型威胁的响应迟缓,已难以满足日益增长的安全需求。本文将探讨如何利用人工智能(AI)技术打造一个自适应的网络安全防御系统,该系统能够实时分析网络流量,自动识别并响应未知威胁,从而提供更为强大和灵活的保护机制。通过深入剖析AI算法的核心原理及其在网络安全中的应用,我们将展望一个由AI赋能的、更加智能和安全的网络环境。
25 0
|
29天前
|
人工智能 算法 搜索推荐
构建未来:AI在持续学习系统中的创新应用
【2月更文挑战第30天】 本文聚焦于人工智能(AI)技术在持续学习系统(CLS)中的前沿应用,探讨了AI如何促进个体和组织的知识演进与技能提升。通过分析自适应学习算法、数据驱动的个性化推荐以及智能辅助决策支持等关键技术,揭示了AI在推动终身学习和知识管理领域的创新潜力。文章还考察了这些技术在实际部署中面临的挑战,包括数据隐私保护、算法透明度和系统集成问题,并提出了相应的解决策略。
21 3
|
30天前
|
机器学习/深度学习 存储 人工智能
构建未来:AI在持续学习系统中的创新应用
【2月更文挑战第29天】 在人工智能的不断进步中,一个引人注目的领域是持续学习系统(Continuous Learning Systems, CLS)。这类系统旨在模拟人类学习过程,允许AI模型在不断接收新信息的同时,保持并增强其先前的知识。本文将探讨AI在持续学习领域的最新技术进展,分析其对现有教育模式、工业应用及个人发展的深远影响,同时提出当前面临的主要挑战和潜在的解决方案。
19 1
|
1月前
|
机器学习/深度学习 人工智能 算法
构建未来:AI驱动的自适应网络安全防御系统
【2月更文挑战第27天】 在数字化进程加速的背景下,网络安全威胁日益增长,传统的安全防御机制逐渐显得力不从心。本文提出一种基于人工智能技术的自适应网络安全防御系统架构,旨在通过实时分析网络行为和自动调整防御策略来应对复杂多变的网络攻击。该系统利用机器学习算法对异常行为进行检测与分类,并结合深度学习技术实现攻击模式的预测和响应策略的动态优化。文章详细阐述了系统的设计理念、关键技术以及预期效能,展望了AI技术在网络安全领域应用的未来趋势。
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
构建未来:AI驱动的自适应网络安全防御系统
【2月更文挑战第26天】 在数字化时代,网络安全已成为维护信息完整性、确保业务连续性的关键。随着攻击手段的不断进化,传统的安全防御措施已不足以应对日益复杂的威胁。本文将探讨人工智能(AI)如何革新网络安全领域,构建一个自适应的防御系统。通过分析当前网络威胁的演变趋势,结合AI技术的实时数据分析、模式识别和自我学习能力,提出一种智能化的安全框架。该框架能够动态调整安全策略,预防未知攻击,并减少误报,从而为网络环境提供更加坚固的保护。
|
1月前
|
机器学习/深度学习 存储 人工智能
构建未来:AI在持续学习系统中的应用
【2月更文挑战第24天】 随着人工智能技术的飞速发展,持续学习系统(Continuous Learning Systems, CLS)已成为AI研究的前沿领域。这类系统旨在模拟人类学习过程,实现机器学习模型在学习新任务时不遗忘旧知识的能力。本文将深入探讨AI在构建持续学习系统中的关键技术和挑战,包括知识蒸馏、正则化策略、记忆增强网络等方法。通过这些技术,AI能够逐步建立起类似人类的学习曲线,为未来的自适应和普适性学习铺平道路。
|
1月前
|
存储 人工智能 自然语言处理
“智能+”时代,深维智信如何借助阿里云打造AI内容生成系统
随着数字经济的发展,线上数字化远程销售模式越来越成为一种主流,销售流程也演变为线上视频会议、线下拜访等多种方式的结合。根据Gartner报告,到2025 年60%的B2B 销售组织将从基于经验和直觉的销售转变为数据驱动的销售,将销售流程、销售数据、销售分析合并形成一致的运营实践。
394 0
“智能+”时代,深维智信如何借助阿里云打造AI内容生成系统