视觉学习第二天

本文涉及的产品
文档理解,结构化解析 100页
自定义KV模板,自定义KV模板 500次/账号
车辆物流识别,车辆物流识别 200次/月
简介: 身份证识别

SDK参考

一种是OSS方式,一种是通过本地上传服务

OSS方式

AI类目 SDK包名称 SDK链接 Github链接
文字识别 aliyun-java-sdk-ocr Aliyun Java SDK OCR aliyun-java-sdk-ocr

maven

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.4.8</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.52</version>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-imageenhan</artifactId>
    <version>${aliyun.imageenhan.version}</version>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-imagerecog</artifactId>
    <version>${aliyun.imagerecog.version}</version>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-facebody</artifactId>
    <version>${aliyun.facebody.version}</version>
</dependency>

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-imageseg</artifactId>
    <version>${aliyun.imageseg.version}</version>
</dependency>

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-goodstech</artifactId>
    <version>${aliyun.goodstech.version}</version>
</dependency>

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-imageaudit</artifactId>
    <version>${aliyun.imageaudit.version}</version>
</dependency>

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-objectdet</artifactId>
    <version>${aliyun.objectdet.version}</version>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-ocr</artifactId>
    <version>${aliyun.ocr.version}</version>
</dependency>

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-imageprocess</artifactId>
    <version>${aliyun.imageprocess.version}</version>
</dependency>

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-videoenhan</artifactId>
    <version>${aliyun.videoenhan.version}</version>
</dependency>

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-videoseg</artifactId>
    <version>${aliyun.videoseg.version}</version>
</dependency>

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-videorecog</artifactId>
    <version>${aliyun.videorecog.version}</version>
</dependency>

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-imgsearch</artifactId>
    <version>${aliyun.imgsearch.version}</version>
</dependency>

说明

本地上传方式

maven

<dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>ocr</artifactId>
            <version>1.0.3</version>
        </dependency>

身份识别所需要的其他依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.10</version>
    </dependency>

    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>ocr</artifactId>
        <version>1.0.3</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.1.37</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

前端界面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>VIAPI</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/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="face" id="i-back" accept=".jpg, .png, .jpeg" onchange="$('#location1').val($('#i-face').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-fliud" alt=""/>
                </div>
                <div class="col-sm-4">
                    <img style="width: 100%;" th:src="${backImage}" th:if="${backImage ne null}" class="img-fliud" 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.bitrhDate}"></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>
            <div class="col-sm-4">
                <p th:if="${backResult ne null}"><span>签发机关:</span><span th:text="${bacResult.issue}"></span></p>
                <p th:if="${backResult ne null}"><span>有效日期:</span><span th:text="${bacResult.startDate}"></span>~<span th:text="${bacResult.endDate}"></span></p>
            </div>

        </div>


    </div>
</body>
</html>

AccessKey

spring.servlet.multipart.max-file-size=100MB
文件上传地址
file.upload.path=

viapi.accessKeyId=
viapi.accessKeySecret=

构建client,以及服务功能

@Service
public class OcrService {

    private Client ocrClient;
    private RuntimeOptions runtime;

    //阿里云的ID和密码
    @Value("${viapi.accessKeyId}")
    private String accessKeyId;
    @Value("${viapi.accessKeySecret}")
    private String accessKeySecret;

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

        ocrClient = new Client(config);
        runtime = new RuntimeOptions();
    }

    /**
     *
     * @param filePath 本地文件路径
     * @param side 身份正反面信息
     * @return
     * @throws Exception
     */
    public Map<String,String> RecognizeIdCard(String filePath,String side) throws Exception{
        RecognizeIdentityCardAdvanceRequest request = new RecognizeIdentityCardAdvanceRequest();
        request.imageURLObject = Files.newInputStream(Paths.get(filePath));
        request.side = side;
        RecognizeIdentityCardResponse response = ocrClient.recognizeIdentityCardAdvance(request,runtime);

        if ("face".equals(side)){
            //正面
            return JSON.parseObject(JSON.toJSONString(response.data.frontResult),new TypeReference<Map<String,String>>() {});
        }else {
            //反面
            return JSON.parseObject(JSON.toJSONString(response.data.backResult),new TypeReference<Map<String,String>>() {});
        }
    }
}

RecognizeIdentityCardAdvanceRequest类源码

public class RecognizeIdentityCardAdvanceRequest extends TeaModel {
    @NameInMap("ImageURLObject")
    @Validation(
        required = true
    )
    public InputStream imageURLObject; //url
    @NameInMap("Side")
    @Validation(
        required = true
    )
    public String side; //正反面

    public RecognizeIdentityCardAdvanceRequest() {
    }

    public static RecognizeIdentityCardAdvanceRequest build(Map<String, ?> map) throws Exception {
        RecognizeIdentityCardAdvanceRequest self = new RecognizeIdentityCardAdvanceRequest();
        return (RecognizeIdentityCardAdvanceRequest)TeaModel.build(map, self);
    }
}

MainController请求

@Controller
@RequestMapping("/")
public class MainController {

    private String uploadDirectory;
    private OcrService ocrService;
    private List<String> faceImages;
    private List<String> backImages;
    private List<Map<String,String>> faceResults;
    private List<Map<String,String>> backResults;
    
    public MainController(@Value("${file.upload.path}") String uploadDirectory,OcrService ocrService){
        this.uploadDirectory = uploadDirectory;
        this.ocrService = ocrService;
        faceImages = new ArrayList<>();
        backImages = new ArrayList<>();
        faceResults = new ArrayList<>();
        backResults = new ArrayList<>();
    }

    public String saveFile(MultipartFile file) throws IOException {
        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;
    }

    @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("bacResult",backResults.get(backResults.size()-1));
        }
        return "index";
    }

    /**
     *
     * @param face 正面文件
     * @param back 反面文件
     * @param attributes 重定向
     * @return
     */
    @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;

        Path dir = Paths.get(uploadDirectory);


        try {
            //上传目录是否存在
            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:/";

    }
}
相关文章
|
3月前
|
人工智能 自然语言处理 搜索推荐
两分钟“熟读”《国史大纲》,大模型的下一个爆点是“书童”?
年初的大模型之战激发了我们对“读书助理”的构想。多数模型受限于文本长度与理解能力,但在GLM-4-Long出现后迎来转机。该模型支持1M上下文,能一次处理完整本《红楼梦》。我们对其进行了深度测试:以《国史大纲》为例,它不仅能迅速提取核心信息,还能准确回答细节问题,仿佛与作者对话。此外,通过多文档训练,GLM-4-Long甚至能成为特定领域的“知识博主”。这标志着大模型竞争已从单纯追求文本长度转向综合能力的较量,预示着AGI应用的新纪元。
|
6月前
|
人工智能 机器人 API
ChatGPT4.0直接出图功能上线!神奇一键画,新手小白也能绘画(chatgpt4.0直接出圖)
ChatGPT4.0直接出图功能上线!神奇一键画,新手小白也能绘画(chatgpt4.0直接出圖)
349 2
|
6月前
|
人工智能 算法 数据挖掘
ChatGPT 调教日记(二):程序员转量化的背景知识
ChatGPT 调教日记(二):程序员转量化的背景知识
62 0
|
人工智能 搜索推荐 iOS开发
ChatGPT还在2G冲浪?新模型「youChat」:我已能够解说2022世界杯(2)
ChatGPT还在2G冲浪?新模型「youChat」:我已能够解说2022世界杯
145 0
ChatGPT还在2G冲浪?新模型「youChat」:我已能够解说2022世界杯(2)
|
人工智能 JSON 安全
能听懂语音的ChatGPT来了:10小时录音扔进去,想问什么问什么
能听懂语音的ChatGPT来了:10小时录音扔进去,想问什么问什么
152 0
|
人工智能 异构计算
让ChatGPT来写今年的高考作文,能得几分?
使用最新的ChatGPT4模型,做2023年全国甲卷的高考作文
139 0
|
机器学习/深度学习 人工智能 算法
【周末闲谈】AI作图,你真的了解它吗?
【周末闲谈】AI作图,你真的了解它吗?
142 0
|
人工智能 搜索推荐 区块链
ChatGPT还在2G冲浪?新模型「youChat」:我已能够解说2022世界杯(1)
ChatGPT还在2G冲浪?新模型「youChat」:我已能够解说2022世界杯
134 0
|
人工智能 JSON 前端开发
大火AutoGPT星标超PyTorch,网友:看清它的局限性
大火AutoGPT星标超PyTorch,网友:看清它的局限性
|
机器学习/深度学习 算法 机器人
只需1次演示,1小时在线训练,机器人真就做到看一遍就会了
只需1次演示,1小时在线训练,机器人真就做到看一遍就会了
127 0
下一篇
无影云桌面