互联网加竞赛 基于计算机视觉的身份证识别系统

news2024/11/24 22:48:58

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

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

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

相关文章

Sora:继ChatGPT之后,OpenAI的又一力作

关于Sora的报道,相信很多圈内朋友都已经看到了来自各大媒体铺天盖地的宣传了,这次,对于Sora的宣传,绝不比当初ChatGPT的宣传弱。自OpenAI发布了GPT4之后,就已经有很多视频生成模型了,不过这些模型要么生成的…

【JavaEE】_CSS选择器

目录 1. 基本语法格式 2. 引入方式 2.1 内部样式 2.2 内联样式 2.3 外部样式 3. 基础选择器 3.1 标签选择器 3.2 类选择器 3.3 ID选择器 4. 复合选择器 4.1 后代选择器 4.2 子选择器 4.3 并集选择器 4.4 伪类选择器 1. 基本语法格式 选择器若干属性声明 2. 引入…

C语言从零实现贪吃蛇小游戏

制作不易,点赞关注一下呗!!! 文章目录 前言一. 技术要点二、WIN32API介绍三、贪吃蛇游戏设计与分析 1.游戏开始前的初始化 2.游戏运行的逻辑 总结 前言 当我们掌握链表这样的数据结构之后,我们就可以用它来…

Rust 学习笔记 - Hello world

前言 本文将讲解如何完成一个 Rust 项目的开发流程,从编写 “Hello, World!” 开始,到使用 Cargo 管理和运行项目。 编写 Hello world 开始一个新项目很简单,首先,创建一个包含 main.rs 文件的 hello_world 文件夹,…

GPT翻译网站的加载与使用

Sider: ChatGPT侧边栏 GPTs, GPT-4 Turbo, 联网, 绘图 sider.ai https://chromewebstore.google.com/detail/sider-chatgpt%E4%BE%A7%E8%BE%B9%E6%A0%8F-gpts-g/difoiogjjojoaoomphldepapgpbgkhkb?hlzh-CN 加入与移除 第二个翻译网站 https://chromewebstore.google.com/…

电商小程序08调用缓存

目录 1 将信息存入缓存中2 获取登录信息3 退出登录4 发布预览总结 小程序的登录功能里,如果只是将登录信息保存到全局变量中,存在的问题是如果小程序重新打开,用户的登录状态就丢失了。为了解决这个问题,我们需要用到微搭的缓存的…

13-k8s的控制器资源-rc控制器replicationcontrollers

一、rc控制器资源的概述 replicationcontrollers控制器资源,简称:rc控制器; 简单理解,rc控制器就是控制相同的pod副本数量; 使用rc控制器资源创建pod,就可以设定创建pod的数量; 二、rc控制器资源…

C++中对象的构造与析构顺序

一、对象的构造顺序 对象的构造&#xff0c;先被创建的对象&#xff0c;先被构造&#xff0c;先调用其构造函数 class A { private:int _a 0; public://构造函数A(int a 0){_a a;cout << "A(int a 0)" << " " << _a << endl…

NVIDIA 刚刚揭秘了他们的最新大作——Eos,一台跻身全球十强的超级计算机

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

HCIA-HarmonyOS设备开发认证V2.0-内核扩展组件

目录 一、CPU 占用率1.1、CPU 占用率基本概念1.2、CPU 占用率运行机制1.3、CPU 占用率开发流程 二、动态加载2.1、 动态加载基本概念2.2、动态加载运行机制 坚持就有收获 一、CPU 占用率 1.1、CPU 占用率基本概念 CPU&#xff08;中央处理器&#xff0c;Central Processing U…

Java 学习和实践笔记(11)

三大神器&#xff1a; 官方网址: http://www.jetbrains.com/idea/ 官方网址: https://code.visualstudio.com/ 官方网址: http://www.eclipse.org 装好了idea社区版&#xff0c;并试运行以下代码&#xff0c;OK&#xff01; //TIP To <b>Run</b> code, press &l…

洛谷AT_abc034_a[ABC034A] テスト

#先看题目 题目描述 输入格式 无 输出格式 无 题意翻译 输入两个数字 x 和 y&#xff0c;如果 y>x 输出Better&#xff0c;否则输出Worse。 输入输出样例 无 题目链接https://www.luogu.com.cn/problem/AT_abc034_a #思路 没有 #最后附上完整代码 #include&l…

(02)Hive SQL编译成MapReduce任务的过程

目录 一、架构及组件介绍 1.1 Hive底层架构 1.2 Hive组件 1.3 Hive与Hadoop交互过程 二、Hive SQL 编译成MR任务的流程 2.1 HQL转换为MR源码整体流程介绍 2.2 程序入口—CliDriver 2.3 HQL编译成MR任务的详细过程—Driver 2.3.1 将HQL语句转换成AST抽象语法树 词法、语…

二叉树的锯齿形层序遍历

1.题目 这道题是2024-2-16的签到题&#xff0c;题目难度为中等。 考察知识点为BFS算法和双端队列。 题目链接&#xff1a;二叉树的锯齿形层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 锯齿形层序遍历 。&#xff08;即先从左往右&#xff0c;再从右往左进行…

VScode写LaTeX配置,实测有效

环境配置请看LaTeX环境配置-TexLive&#xff0c;实测有效http://t.csdnimg.cn/0txlL VScode写LaTeX配置 0.smatra pdf下载 如果使用外部pdf查看器&#xff0c;比如我用的sumatra pdf,官网是Sumatra PDF reader download page 下载对应版本&#xff0c;比如64位&#xff0c;下…

【STM32 CubeMX】I2C中断方式与DMA方式

文章目录 前言一、I2C中断方式1.1 CubeMX配置I2C中断1.2 I2C中断函数使用Master模式Mem模式 1.3 DMA方式发送和接收CubeMX配置IIC DMA方式Master模式Mem模式 总结 前言 在STM32 CubeMX环境中&#xff0c;I2C&#xff08;Inter-Integrated Circuit&#xff09;通信协议的实现可…

机器人专题:我国机器人产业园区发展现状、问题、经验及建议

今天分享的是机器人系列深度研究报告&#xff1a;《机器人专题&#xff1a;我国机器人产业园区发展现状、问题、经验及建议》。 &#xff08;报告出品方&#xff1a;赛迪研究院&#xff09; 报告共计&#xff1a;26页 机器人作为推动工业化发展和数字中国建设的重要工具&…

【数据结构】无向图创建邻接矩阵、深度优先遍历和广度优先遍历(C语言版)

无向图创建邻接矩阵、深度优先遍历和广度优先遍历 一、概念解析&#xff1a; &#xff08;1&#xff09;无向图&#xff1a;&#xff08;2&#xff09;邻接矩阵&#xff1a; 二、创建邻接矩阵&#xff1a;三、深度遍历、广度遍历 &#xff08;1&#xff09;深度遍历概念&#x…

模型 IPO(输入、处理、输出)学习模型

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_总纲目录。重在提升认知。信息转化与传递。 1 模型 IPO(输入、处理、输出)学习模型的应用 1.1 项目管理知识体系 PMBOK 中的IPO应用 在项目管理领域&#xff0c;PMBOK&#xff08;Project Management Body of Know…

ChatGPT绘图指南:DALL.E3玩法大全(一)

一、 DALLE.3 模型介绍 1、什么是 DALLE.3 模型&#xff1f; DALLE-3模型&#xff0c;是一种由OpenAI研发的技术&#xff0c;它是一种先进的生成模型&#xff0c;可以将文字描述转化为清晰的图片。这种模型的名称"DALLE"实际上是"Deep Auto-regressive Latent …