当前位置: 首页 > article >正文

身份证识别JAVA+OPENCV+OCR

一、相关的地址

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.kler.cn/news/363939.html

相关文章:

  • 【Modern C++】特性学习与补漏
  • 分布式并发场景的核心问题与解决方案
  • 初识知识图谱
  • C端产品经理与B端产品经理的区别
  • Lesson10---list
  • pytorch dataloader学习
  • ref属性的作用对象类型
  • 文件操作(1) —— 文件基础知识
  • 【C++】——list 容器的解析与极致实现
  • 修改IDEA中@author变量user内容
  • 开源软件搜索工具:Reddo
  • React是如何处理事件的?
  • linux 将已经启动的java应用的控制台日志输出出来, 不停应用的情况下
  • Java 使用 itextpdf 自定义 生成 pdf
  • CSS 网格布局
  • 前端发送请求格式
  • 2024昆明ICPC A. Two-star Contest(直观命名+详细注释)
  • SpringCloudAlibaba-Nacos
  • upload靶场sql靶场一点点见解
  • 【论文阅读】SRGAN
  • UE5 射线折射
  • Ubuntu22.04虚拟机安装
  • 牛客周赛63
  • 【OpenAI】第六节(语音生成与语音识别技术)从 ChatGPT 到 Whisper 的全方位指南
  • MFF原理描述
  • 2024-1024节