竞赛 基于视觉的身份证识别系统

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/674421.html

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

相关文章

GNeRF论文理解

文章目录 主要解决什么问题?结构设计以及为什么有效果?个人想法。 主要解决什么问题? 本文主要想要解决的问题是 如何使用uncalibrated的照片来进行Nerf重建。虽然说现在已经有了一些方式可以对相机位姿进行估计和优化,但是他们限…

速通systemverilog

这里写目录标题 一、systemverilog的大部分新语法logicalways_combunique_casepriority casealways_fftypedefstructenumunioninterface 二、实现流水灯三、全加器以及仿真 一、systemverilog的大部分新语法 logic always_comb unique_case priority case case中常量和变量互…

SAP-FICO总账科目案例

1、资产科目 2、负债科目

学习笔记之——2D Gaussian Splatting(2DGS)

3DGS在辐射场重建中取得了巨大的成就,实现高质量的新视图合成和快速渲染。最近新出了3DGS的升级版本,2DGS。写下本博文记录本人学习及测试2DGS的过程,本博文仅为本人学习记录用~ Project WebsiteGithub CodeOriginal paper 目录 原理解读 …

Vue3项目炫酷实战,检测密码强度值

在前端项目开发中,确保用户密码的强度是保护账户安全的重要措施。本文将演示如何使用Vue 3实现一个简单的密码强度检测功能。通过实时反馈,帮助用户创建更安全的密码,从而提升整体系统的安全性。无论您是前端开发新手还是经验丰富的开发者&am…

实验9 静态路由配置

实验9 静态路由配置 一、 原理描述二、 实验目的三、 实验内容四、 实验配置五、 实验步骤 一、 原理描述 网络中的每个路由器都会维护一张路由表或转发表。路由表的表项记录着目的网络信息以及下一跳I 地址。路由表可以手动配置,也可以通过路由算法动态生成。静态…

.NET最新漏洞 | 某SLMS系统存在SQL注入

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

结合视差补偿与3D数据处理的盲光场图像质量评价

摘要:与传统的2D图像相比,光场图像记录了场景中光线的强度和方向信息,在多媒体技术应用领域中占据着重要的地位。但在光场图像的产生、传输等处理过程中会不可避免地引入失真,影响用户视觉体验,因而需构建有效、准确的…

副业变现:AI技术在多领域创收的七大策略

AI副业变现:开启你的智能创富之路 近年来,人工智能(AI)技术迅猛发展,从大数据分析到自然语言处理,AI正在深刻地改变我们的生活和工作方式。越来越多的人开始利用AI技术发展副业,实现智能创富。…

数字认证携手华为鸿蒙生态,升级智慧办公新体验

5月29日,“千帆竞发启航 共筑鸿蒙生态”鸿蒙原生应用合作仪式在北京成功举办,近40个应用现场官宣启动鸿蒙原生应用开发。数字认证应邀参加,基于HarmonyOS NEXT鸿蒙星河版,数字认证对“掌上信手书”App进行了鸿蒙原生应用开发,为用户提供更安全、更便捷的使用体验。双方此次战略…

软件3班20240603

经典 报错 404 大概率 就是 这图 的 路径 写错i了 package com.yanyu;import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import jav…

基于PCIE X16总线架构的4路QSFP28 100G光纤通道适配器(可实现100%国产化)

板卡概述 PCIE736是一款基于PCIE总线架构的4路QSFP28 100G光纤通道适配器,该板卡具有1个PCIe Gen3x16主机接口、一共4个QSFP28 100G光纤接口,可以实现4路QSFP28 100G光纤的数据实时采集、实时缓存与PCIE高速传输。该板卡采用Xilinx的高性能Virtex Ultra…

Redis-02

redis安装包位置 /opt/redis-7.2.5 redis默认安装路径: 配置文件路径:/usr/local/bin/redisconfig gcc安装位置 /opt/rhredis启动: 在/usr/local/bin目录下输入redis-server redisconfig/redis.confredis-cli -p 6379redis性能测试命令 red…

ES6-02-变量的解构赋值

一、解构赋值的定义 ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值。 二、解构的使用 1、数组解构 2、对象解构 3、方法的解构(用的多) const zhao {name: 赵本上,age: 不知道,xiaopin: function () {console.log(我能演小品);…

【Python3.11版本利用whl文件安装对应的dlib-19.24.1-cp311-cp311-win_amd64.whl库】

下载Python对应的安装包 找到自己Python版本对应的dlib whl库将网盘下载好的文件放在安装Python的Scripts路径下面接着在该路径输入cmdpip进行安装使用的是国内的源 找到自己Python版本对应的dlib whl库 python 3.11 对应 dlib-19.24.1-cp311-cp311-win_amd64.whl -i 也可以去…

Github上一款开源、简洁、强大的任务管理工具:Condution

Condution 是一款开源任务管理工具,它以简洁易用、功能强大著称。它旨在为用户提供一个简单高效的平台,帮助他们管理日常任务、提高工作效率。 1. Condution 的诞生背景 现如今,市面上存在着许多任务管理软件,但它们往往价格昂贵…

LeetCode 算法:和为 K 的子数组c++

原题链接🔗:和为 K 的子数组 难度:中等⭐️⭐️ 题目 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1: 输入:num…

C语言:学生成绩管理系统(含源代码)

一.功能 二.源代码 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NUM 100 typedef struct {char no[30];char name[10];char sex[10];char phone[20];float cyuyan;float computer;float datastruct; } *student, student1;typ…

基于springboot实现人事管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现人事管理系统演示 摘要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;问卷信息因为其管理内容繁杂&#xff0c;管理数…

AWS EC2服务器开启root密码,SSH登录

1) EC2 Instance Connect连接&#xff0c;更改root密码 sudo passwd root 2&#xff09;接着切换到切换到 root 身份&#xff0c;编辑 SSH 配置文件 $ sudo -i$ vi /etc/ssh/sshd_configPasswordAuthentication no&#xff0c;把 no 改成 yes #PermitRootLogin prohibit-passw…