竞赛保研 基于计算机视觉的身份证识别系统

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, ## 设最小和为40
                minimun_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_ranges2d

        char_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] - x
                h = 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] - x
                    h = peek_range[1] - y
                    pt1 = (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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件测试|pycharm关联GitHub的详细步骤

简介 GitHub 是全球最大的开源代码托管平台之一,而 PyCharm 是一款强大的 Python 集成开发环境。将两者结合使用,可以提高团队协作和代码管理的效率。本文将详细介绍如何在 PyCharm 中管理 GitHub 账号,包括如何设置 GitHub 账号、创建新仓库…

伴鱼实时数仓建设案例

伴鱼实时数仓建设案例 文章目录 伴鱼实时数仓建设案例伴鱼实时作业应用场景伴鱼实时数仓的建设体系DWD 层复杂场景数据处理方案1. 数据的去重2. join场景两条实时数据流相关联对于关联历史数据 3. 从数据形态观查join DWS 数据层数据处理方案未来与展望 随着伴鱼业务的快速发展…

JUC之CompletableFuture

Future接口理论 Future接口定义了异步任务执行的一些方法&#xff0c;包括异步任务执行结果&#xff0c;异步任务执行是否中断&#xff0c;异步任务是否完毕等。 Future接口常用实现类FutureTask异步任务 FutureTask<String> futureTask new FutureTask<String>…

企业网盘:实现数据跨境传输,助力企业出海的必备工具

今年是“一带一路”十周年。在这十年间&#xff0c;中国和“一带一路”共建国家携手并行&#xff0c;贸易持续增长发展。在如今经济全球化的大方向下&#xff0c;跨国经济合作将会是各国共识。 目前&#xff0c;中外合作企业、跨境企业已成为国际贸易发展趋势。不过&#x…

扩展欧几里得算法

文章目录 扩展欧几里得算法的内容及证明扩展欧几里得算法的代码实现扩展欧几里得算法的用途 本文的问题场景中&#xff0c;涉及到的变量均为整数。 扩展欧几里得算法的内容及证明 贝祖等式&#xff1a; a x b y g c d ( a , b ) c axby gcd(a, b) c axbygcd(a,b)c 其中 …

PLC数组队列搜索FC(SCL代码+梯形图程序)

根据输入数据搜索输入数据队列中和输入数据相同的数,函数返回其所在队列的位置。这里我们需要用到博途PLC的数组指针功能,有关数组指针的详细使用方法,可以参考下面文章: 博途PLC数组指针: https://rxxw-control.blog.csdn.net/article/details/134761364 区间搜索FC …

软件测试|Git:fatal: refusing to merge unrelated histories错误分析与解决

问题介绍 在使用Git时&#xff0c;有时我们可能会遇到以下错误消息&#xff1a; fatal: refusing to merge unrelated histories这个错误通常发生在尝试合并两个不相关的Git仓库历史时。在本文中&#xff0c;我们将详细解释为什么会出现这个错误以及如何解决它。 问题分析 …

代码随想录算法训练营第四天 | 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

代码随想录算法训练营第四天 | 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II 文章目录 代码随想录算法训练营第四天 | 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II1 Le…

CSS样式学习

html超文本传输标签&#xff0c;属性等权重 outline 标签轮廓 <input type"text"> <textarea cols"30" rows"10"></textarea> outline: none; 表示无轮廓 &#xff08;开发时用的比较多&#xff09; CSS 轮廓&#xff…

大创项目推荐 深度学习疫情社交安全距离检测算法 - python opencv cnn

文章目录 0 前言1 课题背景2 实现效果3 相关技术3.1 YOLOV43.2 基于 DeepSort 算法的行人跟踪 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习疫情社交安全距离检测算法 ** 该项目较为新颖&#xff0c;适合作为竞赛…

【踩坑】flask_uploads报错cannot import name ‘secure_filename‘

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 背景说明 截至目前&#xff0c;用新版的flask实现文件上传(用到flask_uploads库)&#xff0c;会出现这个问题。 问题原因 版本问题&#xff0c;新的werkzeug已经把secure_filename的位置改了。 解决方法 手动修改…

第23集《佛法修学概要》

庚二、不偷盗分五&#xff1a;辛一、解释名义&#xff1b;辛二、具缘成犯&#xff1b;辛三、犯戒轻重&#xff1b;辛四、开缘情况&#xff1b;辛五、持犯得失 请大家打开讲义第六十五页。我们看庚二、不偷盗。 这一科&#xff0c;我们讲到人天乘的法门。五戒十善为什么叫人天…

【数模百科】距离美赛还有20天,不要忘了阅读往年获奖论文(附04-23年美赛获奖论文)

之前发了很多数模相关的知识&#xff0c;受到了一些人的关注&#xff0c;也有很多人私下问我&#xff0c;距离美赛还有20几天了&#xff0c;还来不来得及。 对此我想说&#xff0c; 来不来得及重要吗&#xff1f; 你名都报了&#xff0c;钱也交了&#xff0c;还是笔不小的钱…

OpenGL 网格拾取坐标(Qt)

文章目录 一、简介二、代码实现三、实现效果参考资料一、简介 有时候我们希望通过鼠标来拾取某个网格中的坐标,这就涉及到一个很有趣的场景:光线投射,也就是求取一条射线与网格的交点,这里如果我们采用普通遍历网格中的每个面片的方式,当网格的面片数据量很大时计算效率就…

H7303 无电感,线性恒流,低压差,大电流,车灯/台灯 9V 12V 24V 30V

线性恒流芯片是一种用于控制电流的电子元件&#xff0c;通常用于驱动LED等器件。它的工作原理是通过维持输出电流的恒定来保持被驱动器件的亮度或功率稳定。 具体来说&#xff0c;线性恒流芯片会监测输出电流并调整电压以保持恒定的电流流过被驱动器件。以下是其基本工作步骤&…

国内镜像:极速下载编译WebRTC源码(For Android/Linux/IOS)(二十四)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

基础数据结构第九期 堆(数组+STL)

前言 堆是一种重要的数据结构&#xff0c;因此应该熟练掌握。 一、堆的基本概念 堆的基本&#xff1a; 堆的结构实际上是一棵完全二叉树&#xff0c;堆可以分为大根堆和小根堆 大根堆&#xff1a; 小根堆&#xff1a; 堆的储存&#xff1a; 若节点小标为i&#xff0c;则左子…

常用计算电磁学算法特性与电磁软件分析

常用计算电磁学算法特性与电磁软件分析 参考网站&#xff1a; 计算电磁学三大数值算法FDTD、FEM、MOM ADS、HFSS、CST 优缺点和应用范围详细教程 ## 基于时域有限差分法的FDTD的计算电磁学算法&#xff08;含Matlab代码&#xff09;-框架介绍 参考书籍&#xff1a;The finite…

three.js 学习笔记(学习中1.10更新) |

文章目录 three.js 学习笔记基础概念透视相机 第一个three.js应用threejs画布尺寸和布局canvas画布宽高度动态变化 坐标辅助器 THREE.AxesHelper实现动画效果requestAnimationFrame时间相关属性和方法 THREE.Clock类 相机控件 轨道控制器OrbitControls 灯光点光源点光源辅助观察…

基于python舆情分析可视化系统+情感分析+爬虫+机器学习(源码)✅

大数据毕业设计&#xff1a;Python招聘数据采集分析可视化系统✅ 毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&…