OpenCV小练习:身份证号码识别

目标:针对一张身份证照片,把身份证号码识别出来(转成数字或字符串)。

实现思路:需要将目标拆分成两个子任务:(1) 把身份证号码区域从整张图片中检测/裁剪出来;(2) 将图片中的数字转化成文字。第一个子任务用OpenCV(如何自行编译OpenCV源码?),第二个子任务主要仰仗Tesseract(注:Tesseract是著名的OCR文字识别开源项目)。

使用OpenCV做图像处理的大致过程为:首先要将彩色图像转成灰度图,再进一步做二值化转换。为了把身份证号码区域整个圈出来,需要继续对图像进行“膨胀”处理,使得每个数字的小区域都与相邻数字的小区域连接起来,连成一个大区域。这样处理之后,在用cv::findContours查找轮廓时,就可以根据身份证号码区域的面积和宽高比把它挑选出来了。

具体代码实现

首先用OpenCV加载图片文件:

Mat srcImage = imread(".\\assets\\pigidcard.png");

接着对图像进行灰度化和二值化处理:

Mat grayImg;
cv::cvtColor(srcImage, grayImg, COLOR_BGR2GRAY);
Mat binary;
cv::threshold(grayImg, binary, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);

到这一步,图像看起来是这样的:

接着要做“膨胀”处理。这一步非常关键!需要调整下面这个Size类型的内核大小,目标是让身份证号码的这些数字前后相连,形成一个整体的矩形区域。

Mat kernel = cv::getStructuringElement(MORPH_RECT, Size(26, 26));
Mat dilation;
cv::dilate(binary, dilation, kernel);

到这一步,图像看起来是这样的:

实际的轮廓/区域分布是这样的:

然后就是遍历图像中的所有轮廓。我们设定两个条件,当轮廓的面积以及轮廓外边框的宽高比都大于某个值(根据实际情况而定),我们就认为当前这个轮廓就是身份证号码区域,可以把它裁剪出来。

std::vector<std::vector<Point>> contours;
std::vector<Vec4i> hierarchy;
cv::findContours(dilation, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);for (size_t i = 0; i < contours.size(); i++) {double area = cv::contourArea(contours[i]);Rect roi = cv::boundingRect(contours[i]);double aspectRatio = (double)roi.width / roi.height;// 根据实际情况调整这两个阈值if (area > 40000 && aspectRatio > 10) {Mat cropped = binary(roi);imshow("ID Card - number only", cropped);// 继续使用 Tesseract OCR// …break;}
}

上面代码运行的结果:cropped对象是裁剪出来的仅含一串身份证号码的小图片。注意这是一个二值图,而且不是膨胀处理后的图像哦!接着轮到Tesseract登场了,把这个图片中的数字转成字符串。(注:请参考这篇文章自行把Tesseract源代码编译成静态库。)

#include "baseapi.h"
#include "allheaders.h"#pragma comment(lib, "leptonica-1.84.1.lib")
#pragma comment(lib, "tesseract54.lib")// 使用 Tesseract OCR
tesseract::TessBaseAPI tess;
if (tess.Init("tessdata", "eng") == 0) {tess.SetPageSegMode(tesseract::PSM_SINGLE_BLOCK);// Tesseract无法识别二值图!转换回RGB图像Mat ocrImg;cv::cvtColor(cropped, ocrImg, COLOR_GRAY2BGR);int bytesPerPixel = GetBytesPerPixel(ocrImg);tess.SetImage((uchar*)ocrImg.data, ocrImg.cols, ocrImg.rows, bytesPerPixel, ocrImg.cols * bytesPerPixel);char* outText = tess.GetUTF8Text();std::cout << "ID numbers: " << outText << std::endl;delete[] outText;tess.End();
}

打完收工!o(* ̄▽ ̄*)ブ

P.S. 完整的代码可以从这里下载:https://github.com/luqiming666/OpenCVMisc。查看OpenCVMiscDlg.cpp 文件中的_DetectIDCard_WithGoodDilation() 函数实现即可。我也上传了Tesseract库文件,但只有Release版。如果要验证OCR效果,需要把OpenCVMisc项目的配置切换到Release + x64,并且在OpenCVMiscDlg.cpp文件头部放开这个宏定义:#define _ENABLE_TESSERACT_

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

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

相关文章

Java重修笔记 第四十五天 LinkedHashSet 类

LinkedHashSet 类 1. LinkedHashSet 是 HashSet 的子类&#xff0c;继承 HashSet 的方法 2. LinkedHashSet 的底层是 LinkedHashMap &#xff0c;底层维护了一个数组加双向链表的组合 3. LinkedHashSet 根据元素的 hashCode 值来决定元素在 table 数组上的存储位置&#xf…

Pandas库性能优化指南:从基础到进阶(终)

Pandas是Python中广泛使用的数据处理库&#xff0c;凭借其强大的功能和易用性&#xff0c;深受数据科学家和开发者的青睐。然而&#xff0c;Pandas在处理大规模数据时可能会遇到性能瓶颈&#xff0c;导致执行效率低下。本文将深入探讨如何通过一系列优化技巧&#xff0c;提升Pa…

快速学习go-zero

go的web框架有很多,目前go的社区大家对于框架的态度也不尽相同,有些轻量级的框架,但是也就代表整合第三方中间件就需要自己根据客户端进行封装,比如gingorm,也有些功能完全但是被认为丢失了go本身轻量设计的初衷, 比如goframe,而同样的微服务有很多框架,国内比较出门的就是go-z…

rockyliunx 救援模式下禁用docker

目录地址 /usr/lib/systemd/system/docker.service 进入系统界面&#xff1a; 选择系统 按E 按e出现 如下界面&#xff0c;找到 quite 后面添加 init/bin/bash 按 ctrl x 保存 后&#xff0c;到如下界面 加载文件系统为读写 输入命令 mount -o remount, rw / 修改docer.s…

docker的安装+docker镜像的基本操作

一&#xff0e;docker的介绍 1、Docker 是什么&#xff1f; Docker 是⼀个开源的应⽤容器引擎&#xff0c;可以实现虚拟化&#xff0c;完全采⽤“沙 盒”机制&#xff0c;容器之间不会存在任何接⼝。 Docker 通过 Linux Container&#xff08;容器&#xff09;技术将任意…

SpringBoot项目集成数据脱敏(密码加密)功能

代码连接【https://gitee.com/pengmqqq/sensitive-data-encryption】 介绍 后端敏感数据加密的一些解决方案&#xff0c;包括&#xff1a; 配置文件敏感数据加解密前端传输敏感数据加解密数据库获取的敏感数据加解密 软件架构 配置文件数据脱敏&#xff1a; Jasypt AES …

【线程池】

什么是线程池&#xff1f; 线程池是一个可以复用线程的技术。简单来说&#xff0c;线程池是一种基于池化技术的思想来管理线程的技术&#xff0c;旨在减少线程的创建和销毁次数&#xff0c;提高系统的响应速度和吞吐量。它预先创建了一定数量的线程&#xff0c;并将这些线程放…

力扣52-最大子序和(java详细题解)

题目链接&#xff1a;https://leetcode.cn/problems/maximum-subarray/description/ 前情提要&#xff1a; 因为本人最近都来刷贪心类的题目所以该题就默认用贪心方法来做。 贪心方法&#xff1a;局部最优推出全局最优。 如果一个题你觉得可以用局部最优推出全局最优&#…

Java中的定时器(Timer)

目录 一、什么是定时器? 二、标准库中的定时器 三、实现自定义定时器 一、什么是定时器? 定时器就像一个"闹钟"&#xff0c;当它到达设定的时间后&#xff0c;就会执行预定的代码。 例如&#xff0c;我们在TCP的超时重传机制中讲过&#xff0c;如果服务器在规定…

DNS劫持问题

目录 DNS劫持概述 定义 图示 ​编辑图示说明 DNS劫持的原理 1. DNS请求与响应过程 图示 ​编辑2. 劫持发生点 本地劫持 路由器劫持 中间人攻击 图示 ​编辑图示说明 DNS劫持的影响 1. 对个人用户的影响 图示 ​编辑图示说明 2. 对企业的影响 图示 ​编辑图示…

【Python】set os.environ[“CUDA_VISIBLE_DEVICES“] = ‘1‘ Invalid

If set os.environ[“CUDA_VISIBLE_DEVICES”] ‘1’ Invalid you can place the code block os.environ["CUDA_VISIBLE_DEVICES"] 1 before all cuda code calls. For example: import os os.environ["CUDA_VISIBLE_DEVICES"] 2 import numpy as np…

0828作业+梳理

一、作业 代码&#xff1a; #include <iostream>using namespace std;using datatype int; //类型重命名 #define MAX 2 //宏定义 //结构体定义 struct Sqlist { private:datatype *data; //顺序表数组int size 0; //数组大小int len 0; …

Ubuntu 16.04下Firefox版本更新

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; 在Ubuntu 16.04上更新Firefox的过程可能涉及多个步骤&#xff0c;具体取决于你的需求&#xff0c;比如是要安装一个稳定版本&#xff0c;还是需要使用最新的开发者版本或beta版本。下面我将详细介绍如何在Ub…

Python酷库之旅-第三方库Pandas(105)

目录 一、用法精讲 456、pandas.DataFrame.rdiv方法 456-1、语法 456-2、参数 456-3、功能 456-4、返回值 456-5、说明 456-6、用法 456-6-1、数据准备 456-6-2、代码示例 456-6-3、结果输出 457、pandas.DataFrame.rtruediv方法 457-1、语法 457-2、参数 457-3…

搭建面向切面编程项目

此项目在整合Mybatis基础上修改&#xff0c;可参考主页的整合Mybatis文章 注解版本 第一步 引入maven坐标 <!-- 切面编程所需jar包--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId>…

学生管理系统升级(登录注册 + 关联学生管理系统)

新增需求 这是在昨天的基础初代版本上面新增一个登录注册忘记密码的功能 需求分析 注册 登录 忘记密码 user类代码呈现 package StudentSystem;public class User {private String username;private String password;private String personID;private String phoneNumber;pu…

PHP同城派送多区域运营配送小程序源码

&#x1f69a;&#x1f4a8;「同城派送多区域运营小程序」——让每一份需求快速触达&#xff01;&#x1f308;&#x1f680; &#x1f525; 开篇燃爆&#xff1a;同城生活新风尚&#xff0c;一键速达不是梦&#xff01; Hey小伙伴们&#xff0c;你还在为找不到合适的同城服务…

推荐并整理一波vscode插件(哪些内置了,哪些好用)

文章目录 背景现在还在用的&#xff08;21款&#xff09;Chinese(Simplified)简体中文Chinese LoremLorem ipsumCode Runner&#xff08;很推荐&#xff09;Codeium: AI Coding Autocomplete&#xff08;推荐&#xff09;Draw.io IntegrationESLintHighlight Matching TagJavaS…

数学建模学习(125):使用Python实现Borda计数法进行多标准决策分析

文章目录 1. 背景2. 理论与原理3. 案例背景与数据构建4. Python代码实现5. 代码解析与结果解读参考文献1. 背景 Borda计数法由法国数学家Jean-Charles de Borda于1781年提出,是一种用于多选项投票系统的排名方法。它被广泛应用于多标准决策分析(MCDA)中,以解决在复杂的决策…