竞赛保研 基于计算机视觉的身份证识别系统
0 前言
🔥 优质竞赛项目系列,今天要分享的是
基于机器视觉的身份证识别系统
该项目较为新颖,适合作为竞赛课题方向,学长非常推荐!
🧿 更多资料, 项目分享:
https://gitee.com/dancheng-senior/postgraduate
1 实现方法
1.1 原理
1.1.1 字符定位
在Android移动端摄像头拍摄的图片是彩色图像,上传到服务器后为了读取到身份证上的主要信息,就要去除其他无关的元素,因此对身份证图像取得它的灰度图并得到二值化图。
对身份证图像的的二值化有利于对图像内的信息的进一步处理,可以将待识别的信息更加突出。在OpenCV中,提供了读入图像接口函数imread,
首先通过imread将身份证图像读入内存中:
id_card_img = cv2.imread(path_img)
之后再调用转化为灰度图的接口函数cvtColor并给它传入参数COLOR_BGR2GRAY,它就可以实现彩色图到灰度图的转换,代码如下
gray_id_card_img = cv2.cvtColor(color_img, cv2.COLOR_BGR2GRAY)
preprocess_bg_mask = PreprocessBackgroundMask(boundary)
转化为二值化的灰度图后图像如图所示:
转换成灰度图之后要进行字符定位,通过每一行进行垂直投影,就可以找到所有字段的位置,具体如下:
然后根据像素点起始位置,确定字符区域,然后将字符区域一一对应放入存放字符的列表中:
vertical_peek_ranges = extract_peek_ranges_from_array(vertical_sum,minimun_val=40,minimun_range=1)vertical_peek_ranges2d.append(vertical_peek_ranges)
最后的效果图如图所示:
1.1.2 字符识别
身份证识别中,最重要的是能够识别身份证图像中的中文文字(包括数字和英文字母),这里学长采用深度学习的方式来做:
1)身份证图像涉及个人隐私,很难获取其数据训练集。针对此问题,我采用获取身份证上印刷体汉字和数字的数据训练集的方法,利用Python图像库(PIL)将13类汉字印刷体字体转换成6492个类别,建立了较大的字符训练集;
2)如何获取身份证图片上的字符是在设计中一个重要问题。我采用水平和垂直投影技术,首先对身份证图像进行预处理,然后对图片在水平和垂直方向上像素求和,区分字符与空白区域,完成了身份证图像中字符定位与分割工作,有很好的切分效果;
3)在模型训练中模型的选择与设计是一个重要的环节,本文选择Lenet模型,发现模型层次太浅,然后增加卷积层和池化层,设计出了改进的深层Lenet模型,然后采用Caffe深度学习工具对模型进行训练,并在训练好的模型上进行测试,实验表明,模型的测试精度达到96.2%。
1.1.3 深度学习算法介绍
深度学习技术被提出后,发展迅速,在人工智能领域取得了很好的成绩,越来越多优秀的神经网络也应运而生。深度学习通过建立多个隐层的深层次网络结构,比如卷积神经网络,可以用来研究并处理目前计算机视觉领域的一些热门的问题,如图像识别和图像检索。
深度学习建立从输入数据层到高层输出层语义的映射关系,免去了人工提取特征的步骤,建立了类似人脑神经网的分层模型结构。深度学习的示意图如图所示
1.1.4 模型选择
在进行网络训练前另一项关键的任务是模型的选择与配置,因为要保证模型的精度,要选一个适合本文身份证信息识别的网络模型。
首先因为汉字识别相当于一个类别很多的图片分类系统,所以先考虑深层的网络模型,优先采用Alexnet网络模型,对于汉字识别这种千分类的问题很合适,但是在具体实施时发现本文获取到的数据训练集每张图片都是6464大小的一通道的灰度图,而Alexnet的输入规格是224224三通道的RGB图像,在输入上不匹配,并且Alexnet在处理像素较高的图片时效果好,用在本文的训练中显然不合适。
其次是Lenet模型,没有改进的Lenet是一个浅层网络模型,如今利用这个模型对手写数字识别精度达到99%以上,效果很好,在实验时我利用在Caffe下的draw_net.py脚本并且用到pydot库来绘制Lenet的网络模型图,实验中绘制的原始Lenet网络模型图如图所示,图中有两个卷积层和两个池化层,网络层次比较浅。
2 算法流程
3 部分关键代码
cv2_color_img = cv2.imread(test_image)##放大图片resize_keep_ratio = PreprocessResizeKeepRatio(1024, 1024)cv2_color_img = resize_keep_ratio.do(cv2_color_img) ##转换成灰度图cv2_img = cv2.cvtColor(cv2_color_img, cv2.COLOR_RGB2GRAY)height, width = cv2_img.shape##二值化 调整自适应阈值 使得图像的像素值更单一、图像更简单adaptive_threshold = cv2.adaptiveThreshold(cv2_img, ##原始图像255, ##像素值上限cv2.ADAPTIVE_THRESH_GAUSSIAN_C, ##指定自适应方法Adaptive Method,这里表示领域内像素点加权和cv2.THRESH_BINARY, ##赋值方法(二值化)11, ## 规定领域大小(一个正方形的领域)2) ## 常数C,阈值等于均值或者加权值减去这个常数adaptive_threshold = 255 - adaptive_threshold## 水平方向求和,找到行间隙和字符所在行(numpy)horizontal_sum = np.sum(adaptive_threshold, axis=1)## 根据求和结果获取字符行范围peek_ranges = extract_peek_ranges_from_array(horizontal_sum)vertical_peek_ranges2d = []for peek_range in peek_ranges:start_y = peek_range[0] ##起始位置end_y = peek_range[1] ##结束位置line_img = adaptive_threshold[start_y:end_y, :]## 垂直方向求和,分割每一行的每个字符vertical_sum = np.sum(line_img, axis=0)## 根据求和结果获取字符行范围vertical_peek_ranges = extract_peek_ranges_from_array(vertical_sum,minimun_val=40, ## 设最小和为40minimun_range=1) ## 字符最小范围为1## 开始切割字符vertical_peek_ranges = median_split_ranges(vertical_peek_ranges)## 存放入数组中vertical_peek_ranges2d.append(vertical_peek_ranges)## 去除噪音,主要排除杂质,小的曝光点不是字符的部分filtered_vertical_peek_ranges2d = []for i, peek_range in enumerate(peek_ranges):new_peek_range = []median_w = compute_median_w_from_ranges(vertical_peek_ranges2d[i])for vertical_range in vertical_peek_ranges2d[i]:## 选取水平区域内的字符,当字符与字符间的间距大于0.7倍的median_w,说明是字符if vertical_range[1] - vertical_range[0] > median_w*0.7:new_peek_range.append(vertical_range)filtered_vertical_peek_ranges2d.append(new_peek_range)vertical_peek_ranges2d = filtered_vertical_peek_ranges2dchar_imgs = []crop_zeros = PreprocessCropZeros()resize_keep_ratio = PreprocessResizeKeepRatioFillBG(norm_width, norm_height, fill_bg=False, margin=4)for i, peek_range in enumerate(peek_ranges):for vertical_range in vertical_peek_ranges2d[i]:## 划定字符的上下左右边界区域x = vertical_range[0]y = peek_range[0]w = vertical_range[1] - xh = peek_range[1] - y## 生成二值化图char_img = adaptive_threshold[y:y+h+1, x:x+w+1]## 输出二值化图char_img = crop_zeros.do(char_img)char_img = resize_keep_ratio.do(char_img)## 加入字符图片列表中char_imgs.append(char_img)## 将列表转换为数组np_char_imgs = np.asarray(char_imgs)## 放入模型中识别并返回结果output_tag_to_max_proba = caffe_cls.predict_cv2_imgs(np_char_imgs)ocr_res = ""## 读取结果并展示for item in output_tag_to_max_proba:ocr_res += item[0][0]print(ocr_res.encode("utf-8"))## 生成一些Debug过程产生的图片if debug_dir is not None:path_adaptive_threshold = os.path.join(debug_dir,"adaptive_threshold.jpg")cv2.imwrite(path_adaptive_threshold, adaptive_threshold)seg_adaptive_threshold = cv2_color_img# color = (255, 0, 0)# for rect in rects:# x, y, w, h = rect# pt1 = (x, y)# pt2 = (x + w, y + h)# cv2.rectangle(seg_adaptive_threshold, pt1, pt2, color)color = (0, 255, 0)for i, peek_range in enumerate(peek_ranges):for vertical_range in vertical_peek_ranges2d[i]:x = vertical_range[0]y = peek_range[0]w = vertical_range[1] - xh = peek_range[1] - ypt1 = (x, y)pt2 = (x + w, y + h)cv2.rectangle(seg_adaptive_threshold, pt1, pt2, color)path_seg_adaptive_threshold = os.path.join(debug_dir,"seg_adaptive_threshold.jpg")cv2.imwrite(path_seg_adaptive_threshold, seg_adaptive_threshold)debug_dir_chars = os.path.join(debug_dir, "chars")os.makedirs(debug_dir_chars)for i, char_img in enumerate(char_imgs):path_char = os.path.join(debug_dir_chars, "%d.jpg" % i)cv2.imwrite(path_char, char_img)
4 效果展示
5 最后
🧿 更多资料, 项目分享:
https://gitee.com/dancheng-senior/postgraduate
相关文章:

竞赛保研 基于计算机视觉的身份证识别系统
0 前言 🔥 优质竞赛项目系列,今天要分享的是 基于机器视觉的身份证识别系统 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-sen…...

在visual studio中调试时无法查看std::wstring
1.问题 在调试的时候发现std::wstring类型的变量查看不了,会显示(error)|0,百思不得其解。 2.解决方法 参考的:vs2015调试时无法显示QString变量的值,只显示地址_vs调试qstring的时候如何查看字符串-CSDN博客 在工具/选项/调试…...
2023年全国职业院校技能大赛高职组应用软件系统开发正式赛题—模块三:系统部署测试
模块三:系统部署测试(3 小时) 一、模块考核点 模块时长:3 小时模块分值:20 分本模块重点考查参赛选手的系统部署、功能测试、Bug 排查修复及文档编写能力,具体包括:系统部署。将给定项目发布到…...

微信小程序上传并显示图片
实现效果: 上传前显示: 点击后可上传,上传后显示: 源代码: .wxml <view class"{{company_logo_src?blank-area:}}" style"position:absolute;top:30rpx;right:30rpx;height:100rpx;width:100rp…...

java基础知识点系列——数据输入(五)
java基础知识点系列——数据输入(五) 数据输入概述 Scanner使用步骤 (1)导包 import java.util.Scanner(2)创建对象 Scanner sc new Scanner(System.in)(3)接收数据 int i sc…...

MySQL面试题 | 07.精选MySQL面试题
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…...

C语言中关于指针的理解及用法
关于指针意思的参考:https://baike.baidu.com/item/%e6%8c%87%e9%92%88/2878304 指针 指针变量 地址 野指针 野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的) 以下是导致野指针的原因 1.指针…...

软件测试|深入理解Python中的re.search()和re.findall()区别
前言 在Python中,正则表达式是一种强大的工具,用于在文本中查找、匹配和处理模式。re 模块提供了许多函数来处理正则表达式,其中 re.search()和 re.findall() 是常用的两个函数,用于在字符串中查找匹配的模式。本文将深入介绍这两…...

❤ Vue3 完整项目太白搭建 Vue3+Pinia+Vant3/ElementPlus+typerscript(一)yarn 版本控制 ltb (太白)
❤ 项目搭建 一、项目信息 Vue3 完整项目搭建 Vue3PiniaVant3/ElementPlustyperscript(一)yarn 版本控制 项目地址: 二、项目搭建 (1)创建项目 yarn create vite <ProjectName> --template vueyarn install …...

linux搭建SRS服务器
linux搭建SRS服务器 文章目录 linux搭建SRS服务器SRS说明实验说明搭建步骤推流步骤查看web端服务器拉流步骤final SRS说明 SRS(simple Rtmp Server),是一个简单高效的实时视频服务器,支持RTMP/WebRTC/HLS/HTTP-FLV/SRT, 是国人自己开发的一款…...

系列六、Spring Security中的认证 授权 角色继承
一、Spring Security中的认证 & 授权 & 角色继承 1.1、概述 关于Spring Security中的授权,请参考【系列一、认证 & 授权】,这里不再赘述。 1.2、资源类 /*** Author : 一叶浮萍归大海* Date: 2024/1/11 20:58* Description: 测试资源*/ Re…...
云原生周刊:OpenTofu 宣布正式发布 | 2023.1.15
开源项目推荐 kubeaudit kubeaudit 是一个开源项目,旨在帮助用户对其 Kubernetes 集群进行常见安全控制的审计。该项目提供了工具和检查规则,可以帮助用户发现潜在的安全漏洞和配置问题。 Chronos Chronos 是一款综合性开发人员工具,可监…...

【如何在 GitHub上面找项目】【转载】
很多的小伙伴,经常会有这样的困惑,我看了很多技术的学习文档、书籍、甚至视频,我想动手实践,于是我打开了GitHub,想找个开源项目,进行学习,获取项目实战经验。这个时候很多小伙伴就会面临这样的…...

java每日一题——ATM系统编写(答案及编程思路)
前言: 基础语句学完,也可以编写一些像样的程序了,现在要做的是多加练习,巩固下知识点,打好基础,daydayup! 题目:模仿银行ATM系统,可以创建用户,存钱,转账&…...

《TrollStore巨魔商店》TrollStore2安装使用教程支持IOS14.0-16.6.1
TrollStore(巨魔商店) 简单的说就相当于一个永久的免费证书,它可以给你的iPhone和iPad安装任何你想要安装的App软件,而且不需要越狱,不用担心证书签名过期的问题,不需要个人签名和企业签名。 支持的版本: TrollStore安装和使用教…...

鸿鹄电子招投标系统源码实现与立项流程:基于Spring Boot、Mybatis、Redis和Layui的企业电子招采平台
随着企业的快速发展,招采管理逐渐成为企业运营中的重要环节。为了满足公司对内部招采管理提升的要求,建立一个公平、公开、公正的采购环境至关重要。在这个背景下,我们开发了一款电子招标采购软件,以最大限度地控制采购成本&#…...
力扣-三数之和
三数之和 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意:答案中不可以包含重复的三元组。…...

全罐喂养一个月多少钱?适合全罐喂养的猫罐头推荐
不少铲屎官一直没有办法get到猫罐头对猫咪的好处,或者get到了又觉得给猫咪买猫罐头好贵,看到其他铲屎官都开始全罐喂养了,但是自己却迟迟下不了手,犹犹豫豫的不知道全罐喂养一个月多少钱? 今天,铲龄15年的…...
js some方法的使用
JavaScript中的数组some()方法用于检查数组中是否至少有一个元素满足指定条件。该方法会遍历数组,并对每个元素应用指定的测试函数。如果有任何一个元素使得测试函数返回true,则some()方法返回true,否则返回false。 some()方法的语法如下&am…...

QT DAY5作业
1.QT基于TCP服务器端 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> //服务器类 #include <QMessageBox> //消息对话框类 #include <QTcpSocket> //客户端类 #include <QList> //链表容器类namespace …...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...

mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器
一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下,音视频内容犹如璀璨繁星,点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频,到在线课堂中知识渊博的专家授课,再到影视平台上扣人心弦的高清大片,音…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...

Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...

leetcode_69.x的平方根
题目如下 : 看到题 ,我们最原始的想法就是暴力解决: for(long long i 0;i<INT_MAX;i){if(i*ix){return i;}else if((i*i>x)&&((i-1)*(i-1)<x)){return i-1;}}我们直接开始遍历,我们是整数的平方根,所以我们分两…...