身份证识别JAVA+OPENCV+OCR

news2024/10/25 0:44:02

一、相关的地址

https://github.com/tesseract-ocr/tessdata

Releases - OpenCV

opencv要装好,我装的是4.5.3的,最新版的没试过。

tessdata就下载了需要用的。好像还有best和fast的版本,我试了一下报错,不知道是不是版本不支持的问题。

二、主要的思路

识别的代码到没什么特别的,就是在每一行的识别上,为了提高准确度,稍微花了点心思,但也不时很完善。

发现识别的时候会出现很多干扰,所以从“姓”这一行开始算第一行,然后一行一行分析。

如果图片不清晰,不是太准,有待改进。

三、代码

pom.xml的依赖:

        <!-- OpenCV -->
        <dependency>
            <groupId>org.openpnp</groupId>
            <artifactId>opencv</artifactId>
            <version>4.5.3-4</version>
        </dependency>

        <!--  Tesseract -->
        <dependency>
            <groupId>net.sourceforge.tess4j</groupId>
            <artifactId>tess4j</artifactId>
            <version>5.11.0</version> <!-- 使用最新版本 -->
        </dependency>

JAVA代码:

package com.yutiandada.idcardread.demos.test;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import net.sourceforge.tess4j.*;


public class IDCardRecognition2 {
    static {
        System.setProperty("java.library.path", "D:\\opencv\\opencv\\build\\java\\x64");
        try {
            Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
            fieldSysPath.setAccessible(true);
            fieldSysPath.set(null, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    public static Mat preprocessImage(String imagePath) {
        // 读取图像
        Mat image = Imgcodecs.imread(imagePath);

        // 可选:进行一些图像增强操作,例如锐化
        Mat enhancedImage = new Mat();
        Imgproc.GaussianBlur(image, enhancedImage, new Size(0, 0), 3);
        Core.addWeighted(image, 1.5, enhancedImage, -0.5, 0, enhancedImage);

        return enhancedImage;
    }

    public static List<String> recognizeText(Mat mat) throws TesseractException {
        try {
            // 将Mat转换为File
            File tempFile = File.createTempFile("temp", ".png");
            Imgcodecs.imwrite(tempFile.getAbsolutePath(), mat);

            // 初始化Tesseract
            Tesseract tesseract = new Tesseract();
            tesseract.setLanguage("chi_sim"); // 设置语言为简体中文
            tesseract.setDatapath("d:/tessdata"); // 设置Tesseract数据路径
//            tesseract.setPageSegMode(PageSegMode.PSM_AUTO); // 设置页面分割模式

            // 进行OCR识别
            String result = tesseract.doOCR(tempFile);
            tempFile.delete(); // 删除临时文件

            // 将结果按行分割
            List<String> lines = new ArrayList<>();
            String[] splitResult = result.split("\\r?\\n");
            for (String line : splitResult) {
                if (!line.trim().isEmpty()) {
                    lines.add(line.trim());
                }
            }

            return lines;
        } catch (IOException e) {
            // 处理异常,例如记录日志或显示错误信息
            e.printStackTrace();
            throw new TesseractException("Error during OCR processing", e);
        }
    }

    public static void main(String[] args) {
        try {
            String imagePath = "D:/images/test01.png";
            Mat processedImage = preprocessImage(imagePath);
            List<String> recognizedLines = recognizeText(processedImage);

            System.out.println("Recognized Text:");

            // 找到包含“姓”字的行索引
            int startIndex = -1;
            for (int i = 0; i < recognizedLines.size(); i++) {
                if (recognizedLines.get(i).contains("姓") || recognizedLines.get(i).contains("名") ) {
                    startIndex = i;
                    break;
                }
            }

            if (startIndex != -1) {
                // 从包含“姓”字的行开始重新编号
                List<String> filteredLines = recognizedLines.subList(startIndex, recognizedLines.size());

                // 第一行:“姓名”之后的字符串
                String name = filteredLines.get(0).replaceAll(".*姓名", "").trim();
                System.out.println("Name: " + name);

                // 第二行:性别
                String gender = "";
                String ethnicity = "";
                String secondLine = filteredLines.get(1);
                if (secondLine.contains("男")) {
                    gender = "男";
                } else if (secondLine.contains("女")) {
                    gender = "女";
                }
                int minIndex = secondLine.indexOf("民") + 2;
                if (minIndex > 0 && minIndex < secondLine.length()) {
                    ethnicity = secondLine.substring(minIndex).trim();
                }
                System.out.println("Gender: " + gender);
                System.out.println("Ethnicity: " + ethnicity);

                // 第三行:出生日期,只显示数字
                String thirdLine = filteredLines.get(2).replaceAll("[^0-9]", "").trim();
                if (thirdLine.length() == 8) {
                    String birthYear = thirdLine.substring(0, 4);
                    String birthMonth = thirdLine.substring(4, 6);
                    String birthDay = thirdLine.substring(6, 8);
                    System.out.println("Birth Year: " + birthYear);
                    System.out.println("Birth Month: " + birthMonth);
                    System.out.println("Birth Day: " + birthDay);
                } else {
                    System.out.println("Invalid date format in the third line.");
                }

                // 第四行:地址
                String addressPart1 = filteredLines.get(3).replaceAll("\\s+", "").substring(2).trim();
                String addressPart2 = filteredLines.get(4).replaceAll("\\s+", "").trim();
                String address = addressPart1 + addressPart2;
                System.out.println("Address: " + address);

                // 第六行:身份证号,只显示数字和字母
                String idNumber = filteredLines.get(5).replaceAll("[^a-zA-Z0-9]", "").trim();
                System.out.println("ID Number: " + idNumber);
            } else {
                System.out.println("No line containing '姓' found.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

IDEA里面要配置一下

把安装好的OPENCV装一下

四、效果

网上随便找的图

识别的效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2222829.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为配置 之 远程管理配置

目录 简介&#xff1a; 知识点&#xff1a; Telnet远程管理 &#xff08;1&#xff09;配置接口IP并确保R1和R2处于同一个网段 &#xff08;2&#xff09;使用password认证模式远程登录 &#xff08;3&#xff09;使用AAA认证模式远程登录 SSH远程管理 &#xff08;1&a…

基于springboot的网上服装商城推荐系统的设计与实现

基于springboot的网上服装商城推荐系统的设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;idea 源码获取&#xf…

【deathStarBench】2.安装k8s集群

安装docker 通过以下命令安装docker&#xff1a; sudo yum install docker-ce-26.1.4 docker-ce-cli-26.1.4 containerd.io随后通过查看docker --version&#xff0c;可以确定是否安装的版本一样 启动docker systemctl start docker && systemctl enable docker.se…

《纳瓦尔宝典:财富和幸福指南》读书随笔

最近在罗胖的得到听书中听到一本书&#xff0c;感觉很有启发&#xff0c;书的名字叫《纳瓦尔宝典》&#xff0c;从书名上看给人的感觉应该财富知识类、鸡汤爆棚哪类。纳瓦尔&#xff0c;这个名字之前确实没有听说过&#xff0c;用一句话介绍一下&#xff0c;一个印度裔的硅谷中…

【LeetCode】修炼之路-0006-Zigzag Conversion (Z 字形变换)【python】

题目 The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility) P A H N A P L S I I G Y I R And then read line by line: “PAHNAPLSIIGYIR” …

荣耀电脑管家-系统重装之查询设备序列号

winr输入cmd&#xff0c;再命令行中输入 wmic bios get serialnumber 如下所示

代码随想录算法训练营第六天|454四数相加II、 383赎金信、15三数之和、18四数之和

day06 1. 454四数相加II 首先定义 一个unordered_map&#xff0c;key放a和b两数之和&#xff0c;value 放a和b两数之和出现的次数。遍历大A和大B数组&#xff0c;统计两个数组元素之和&#xff0c;和出现的次数&#xff0c;放到map中。定义int变量count&#xff0c;用来统计 …

YAML格式校验API:免费工具的使用指南

YAML&#xff08;YAML Ain’t Markup Language&#xff09;是一种人类可读的数据序列化格式&#xff0c;广泛用于配置文件、数据交换等场景。由于其简洁的语法和良好的可读性&#xff0c;YAML 在开发和运维领域中越来越受到欢迎。然而&#xff0c;在使用 YAML 时&#xff0c;格…

Xcode文件默认存储位置-使用c++file保存文件默认路径以及设置为路径为当前项目路径

Xcode文件默认存储位置-使用cfile保存文件默认路径以及设置为路径为当前项目路径 1.概述 使用Xcode工具开发时候&#xff0c;遇到C调用file创建文件后&#xff0c;在当前项目中找不到文件路径。这是由于xcode会将文件保存到默认设置的路径。下面是查看文件默认存储路径和修改…

数组中的算法

目录 1.什么是数组 2.数组上的算法 2.1二分查找算法 什么是二分查找算法&#xff1f; 算法步骤 算法时间复杂度 一个问题 例题 题目分析 解题代码 2.2双指针法 什么是双指针法&#xff1f; 例题 题目分析 解题代码 1.什么是数组 数组是在一块连续的内存空间…

C++,STL 047(24.10.24)

内容 对set容器的元素进行查找与统计。 运行代码 #include <iostream> #include <set>using namespace std;void printSet(set<int> &s) {for (set<int>::iterator it s.begin(); it ! s.end(); it){cout << *it << " ";…

linux-牛刀小试

题目一&#xff1a; 1.第一问 首先创建用户tab在超级用户root的终端输入useradd tab 切换到tab用户&#xff1a; 推出重新登录到tab用户或者su – tab切换到tab用户 2.第二问 在桌面创建SHEGNCHAN目录 在SHENGCHAN文件夹下创建相应的文件&#xff1a; 3.第三问 首先&#…

哈希表【闭散列/开散列】

&#x1f33b;个人主页&#xff1a;路飞雪吖~ &#x1f320;专栏&#xff1a;C/C 目录 一、unordered系列关联式容器 &#x1f31f;unordered_map ⭐unordered_map接口说明 二、底层结构 &#x1f31f;哈希概念 &#x1f31f;哈希冲突 &#x1f31f;哈希函数 &#x1f3…

基于Leaflet和SpringBoot的全球国家综合检索WebGIS可视化

目录 前言 一、Java后台程序设计 1、业务层设计 2、控制层设计 二、WebGIS可视化实现 1、侧边栏展示 2、空间边界信息展示 三、标注成果展示 1、面积最大的国家 2、国土面积最小的国家 3、海拔最低的国家 4、最大的群岛国家 四、总结 前言 在前面的博文中&#xff…

【随手笔记】远程升级之如何平衡下载包大小与速率?

1. 远程升级基本信息 使用NB_BC26模组&#xff0c;通过AT指令使用TCP的协议与公司后台交互升级的固件为BIN文件&#xff0c;使用原始固件包升级&#xff0c;未使用差分方式原始固件包有110K,大小左右&#xff0c;固件的存储为外置的FLASH W25Q16,w25q16最小存储单位为页&#…

AListFlutter(手机alist)——一键安装,可在手机/电视上运行并挂载各个网盘

前面提到软路由系统OpenWRT的时候&#xff0c;当时说过可以在OpenWRT里安装alist&#xff0c;然后挂载网盘&#xff0c;这样就可以通过webdav的方式在家庭局域网下的任何设备都可以访问操作这些网盘&#xff0c;摆脱硬盘空间不够的问题。 但alist的官方版本是没有手机版本的&a…

【Java】探秘正则表达式:深度解析与精妙运用

目录 引言 一、基本概念 1.1 元字符 1.2 预定义字符类 1.3 边界匹配符 1.4 数量标识符 1.5 捕获与非捕获分组 二、Java中的正则表达式支持 三、正则表达式的使用示例 3.1 匹配字符串 3.2 替换字符串 3.3 分割字符串 3.4 使用Pattern和Matcher 3.5 捕获组和后向…

我了个超绝MATLAB——基础

由于要参加美赛&#xff0c;不想拖对队友们的后腿&#xff0c;于是一怒之下……怒了一下 创建MATLAB脚本 创建脚本 在主页——新建——脚本 中新建脚本&#xff08;Ctrln&#xff09; 保存 编辑器——保存&#xff08;Ctrls&#xff09; 运行 编辑器——运行&#xff08;F5&…

iOS--利用UITableViewDataSourcePrefetching实现平滑如丝的无限滚动

前言&#xff1a; 相信大家在网络不好的时候使用列表分页的App会获得非常不好的体验&#xff0c;由于网络的问题&#xff0c;会有明显的卡顿&#xff0c;就像抖音等App&#xff0c;那么我们是否能使用一些手段来优化这个体验呢&#xff1f;这里可以用到UITableView中另一个协议…

【案例演示】图像描述大模型示例及概念解释

【案例演示】图像描述大模型示例及概念解释 一、案例演示模型描述期望模型使用方式以及适用范围模型功能演示 二、大模型开源平台概览模型库的定义大模型开源平台 一、案例演示 模型链接&#xff1a;https://modelscope.cn/models/iic/mplug_image-captioning_coco_base_zh 模…