计算机竞赛 身份证识别系统 - 图像识别 深度学习

news2024/12/23 1:20:58

文章目录

  • 0 前言
  • 1 实现方法
    • 1.1 原理
        • 1.1.1 字符定位
        • 1.1.2 字符识别
        • 1.1.3 深度学习算法介绍
        • 1.1.4 模型选择
    • 2 算法流程
    • 3 部分关键代码
  • 4 效果展示
  • 5 最后

0 前言

🔥 优质竞赛项目系列,今天要分享的是

🚩 毕业设计 图像识别 深度学习 身份证识别系统

该项目较为新颖,适合作为竞赛课题方向,学长非常推荐!

🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:3分
  • 工作量:3分
  • 创新点:4分

🧿 更多资料, 项目分享:

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

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

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

相关文章

【算法训练-二分查找 四】【模拟二分】X的平方根

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【二分查找】,使用【数组】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为&…

stm32-SPI协议

SPI协议详解(图文并茂超详细) SPI通讯协议 于是我们想有没有更好一点的串行通讯方式;相比较于UART,SPI的工作方式略有不同。 SPI是一个同步的数据总线,也就是说它是用单独的数据线和一个单独的时钟信号来保证发送端和…

Django的模版使用(Django-03)

一 模版的使用 模板引擎是一种可以让开发者把服务端数据填充到html网页中完成渲染效果的技术。它实现了 把前端代码和服务端代码分离 的作用,让项目中的业务逻辑代码和数据表现代码分离,让前端开发者和服务端开发者可以更好的完成协同开发。 静态网页&…

Linux文本三剑客---awk

AWK是什么 Linux文本三剑客之一(grep,sed,awk),功能最强大的文本工具。 逐行读取输入的文本内容,默认以空格和tab键作为分隔符。但是多个空格或者tab键的空格,会自动压缩成一个,然后按照指定的模式和条件执…

3D 毛玻璃晶质见证卡

效果展示 页面结构 从上面的效果展示来看,页面主要成员是一张卡片,并且卡片上有三个小矩形,而小矩形上会展示对应的内容。 当鼠标悬停在卡片上时,卡片会随着鼠标的移动而改变视角。 CSS3 知识点 transform-style 属性的 prese…

用OpenCV(Python)获取图像的SIFT特征

import cv2 as cv import numpy as np import matplotlib.pyplot as plt imgcv.imread("../Lena.png") img_graycv.cvtColor(img,cv.COLOR_BGR2GRAY)#创建一个SIFI对象 siftcv.SIFT_create()#使用SIFT对象在灰度图像img_gray中检测关键点,结果存储在变量k…

MATLAB中plot3函数用法

目录 语法 说明 向量和矩阵数据 表数据 其他选项 示例 绘制三维螺旋图 绘制多个线条 使用矩阵绘制多个线条 指定等间距刻度单位和轴标签 将点绘制为不带线的标记 自定义颜色和标记 指定线型 在绘图后修改线条 绘制表中的数据 在 x 和 y 轴上绘制多个表变量 指…

【国漫逆袭】人气榜,小医仙首次上榜,霍雨浩排名飙升,不良人热度下降

Hello,小伙伴们,我是小郑继续为大家深度解析国漫资讯。 为了提升作品和角色的讨论度,增加平台的用户活跃度,小企鹅推出了动漫角色榜,该榜单以【年】【周】【日】为单位,通过角色的点赞量和互动量进行排名 上周的动漫角…

解决dockerfile创建镜像时pip install报错的bug

项目场景: 使用docker-compose创建django容器 问题描述 > [5/5] RUN /bin/bash -c source ~/.bashrc && python3 -m pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple: 0.954 Looking in indexes: https://…

关于PointHeadBox类的理解

forward函数 def forward(self, batch_dict):"""Args:batch_dict:batch_size:point_features: (N1 N2 N3 ..., C) or (B, N, C)point_features_before_fusion: (N1 N2 N3 ..., C)point_coords: (N1 N2 N3 ..., 4) [bs_idx, x, y, z]point_labels (opti…

Folium笔记:HeatMap

在地图上生成热力图 0 举例 import folium from folium.plugins import HeatMap# 创建一个地图对象 m folium.Map(location(1.34084, 103.83637), zoom_start13)# 创建一个坐标点的数据集 data [(1.431656, 103.827896),(1.424789, 103.789902),(1.325781, 103.860446),(1.…

【算法训练-搜索算法 一】【DFS网格搜索框架】岛屿数量、岛屿的最大面积、岛屿的周长

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【搜索算法】,使用【数组】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为&…

多卡片效果悬停效果

效果展示 页面结构 从页面的结构上看&#xff0c;在默认状态下毛玻璃卡片是有层次感的效果叠加在一起&#xff0c;并且鼠标悬停在卡片区域后&#xff0c;卡片整齐排列。 CSS3 知识点 transform 属性的 rotate 值运用content 属性的 attr 值运用 实现页面整体布局 <div …

代码随想录算法训练营第五十七天 | 动态规划 part 15 | 392.判断子序列、115.不同的子序列

目录 392.判断子序列思路代码 115.不同的子序列思路代码 392.判断子序列 Leetcode 思路 dp[i][j] 表示以下标i-1为结尾的字符串s&#xff0c;和以下标j-1为结尾的字符串t&#xff0c;相同子序列的长度为dp[i][j]递推公式&#xff1a; 初始化&#xff1a;为0遍历顺序&#xff…

日常工作报告生成器微信小程序源码 支持日报,周报,月报,年终终结

相信大家上班都会有做工作报告的情况吧 那么这款小程序就是大家的福音了 只要输入你的工作内容或者岗位自动生成你的工作报告 支持报,周报,月报,年终终结 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/88391810 源码下载2&#xff1a;评论留言或私信…

JVM篇---第二篇

系列文章目录 文章目录 系列文章目录一、简述一下JVM的内存模型二、说说堆和栈的区别三、什么时候会触发FullGC一、简述一下JVM的内存模型 1.JVM内存模型简介 JVM定义了不同运行时数据区,他们是用来执行应用程序的。某些区域随着JVM启动及销毁,另外一 些区域的数据是线程性独…

自动化测试框架详解

一、什么是自动化测试框架 在了解什么是自动化测试框架之前&#xff0c;先了解一下什么叫框架&#xff1f;框架是整个或部分系统的可重用设计&#xff0c;表现为一组抽象构件及构件实例间交互的方法;另一种定义认为&#xff0c;框架是可被应用开发者定制的应用骨架。前者是从应…

知识图谱-Neo4j使用详解

neo4j应用场景 知识图谱欺诈检测实时推荐引擎反洗钱主数据管理供应链管理增强网络和IT运营管理能力数据谱系身份和访问管理材料清单 图数据库neo4j简介 关系查询&#xff1a;mysql和neo4j性能对比 neo4j的特性和优点&#xff1a; Neo4j-CQL简介 neo4j的Cypher语言是为处理图…

96.qt qml-http之XMLHttpRequest介绍详解使用

在QML中我们可以通过XMLHttpRequest 来实现http/https访问网络接口,接下来我们先来学习XMLHttpRequest类的常用部分、 由于QML的XMLHttpRequest少部分参数是没有的,所以本章来单独讲解下。下章我们来实现旋转请求按钮以及通用的JSON请求模板方法 1.XMLHttpRequest初步使用 …

计算机网络(六):应用层

参考引用 计算机网络微课堂-湖科大教书匠计算机网络&#xff08;第7版&#xff09;-谢希仁 1. 应用层概述 应用层是计算机网络体系结构的最顶层&#xff0c;是设计和建立计算机网络的最终目的&#xff0c;也是计算机网络中发展最快的部分 早期基于文本的应用 (电子邮件、远程登…