8.OpenCV-识别身份证号码(Python)

需求描述:

通过OpenCV识别身份证照片上的身份证号码(仅识别身份证号码)

实现思路:

1.将身份证号中的0,1,2,3,4,5,6,7,8,9作为模板,与身份证照片中的身份证号码区域进行模板匹配。

2.先要制作一个身份证号码模板,我这里弄了一个,基本上可以用。

 3.识别出身份证照片身份证号区域,进行图像模板匹配。

   以下面这样图为例(你也可以替换为你要识别的图片):

 4.识别出身份证号码后,在图中标记出识别结果。

运行效果:

Python源代码目前只能识别标准角度拍摄照片,拍摄角度变形的无法识别):

import cv2
import numpy as np 

rectKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(15,15)) #kernel1 = np.ones((15, 15), np.uint8)
sqKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

#轮廓排序
def sort_contours(cnts,method="left-to-right"):
    reverse=False
    i=0
    if method=="right-to-left" or method=="bottom-to-top":
        reverse=True
    if method=="top-to-bottom" or method=="bottom-to-top":
        i=1
    boundingBoxes=[cv2.boundingRect(c) for c in cnts] #外接矩形
    (cnts,boundingBoxes)=zip(*sorted(zip(cnts,boundingBoxes),key=lambda b:b[1][i],reverse=reverse))
    return cnts,boundingBoxes

# 第一步:预处理模板文件
templateImg = cv2.imread("template.jpg") #template.jpg 即为模板文件,上面那张0-9数字图片
templateImg = cv2.resize(templateImg, (900, 200), interpolation=cv2.INTER_CUBIC)
#转灰度图
templateGray=cv2.cvtColor(templateImg,cv2.COLOR_BGR2GRAY) 
cv2.imshow("1.1 templateGray",templateGray)
#二值处理
templateGray=cv2.threshold(templateGray,30,255,cv2.THRESH_BINARY_INV)[1] 
# cvblackhat = cv2.morphologyEx(templateGray, cv2.MORPH_BLACKHAT, np.ones((50, 50), np.uint8))
# templateGray=cv2.threshold(cvblackhat,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1] 
cv2.imshow("1.2 threshold",templateGray)

#提取轮廓(10个数字的外部轮廓)
templateContours,hierarchy=cv2.findContours(templateGray.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(templateImg,templateContours,-1,(0,0,255),3)
cv2.imshow("1.3 drawContours",templateImg)
templateContours=sort_contours(templateContours,method="left-to-right")[0]

#用于做模板匹配的图像集合
templates={}
for(i,c) in enumerate(templateContours):
    (x,y,w,h)=cv2.boundingRect(c) #外接矩形
    roi=templateGray[y:y+h,x:x+w]
    roi=cv2.resize(roi,(57,88))
    templates[i]=roi

#第二步:处理身份证图片

# 1.读取原图
idimg = cv2.imread("idcard.jpg") #需要进行识别的图片
idimg = cv2.resize(idimg, (509, 300), interpolation=cv2.INTER_CUBIC)
idimgok = idimg.copy()
cv2.imshow("1.origin", idimg)

#2.转灰度图
gray = cv2.cvtColor(idimg, cv2.COLOR_BGR2GRAY)
cv2.imshow("2.gray", gray)

#3.黑帽运算:移除干扰项
cvblackhat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, rectKernel)
cv2.imshow("3.black", cvblackhat)

#4.顶帽运算:突出轮廓
tophat=cv2.morphologyEx(cvblackhat,cv2.MORPH_TOPHAT,rectKernel)
cv2.imshow("4.tophat", tophat)

#5.边缘检测
sobel=cv2.Sobel(tophat,ddepth=cv2.CV_32F,dx=1,dy=0,ksize=-1)
sobel=np.absolute(sobel)
(min,max)=(np.min(sobel),np.max(sobel))
sobel=(255*((sobel-min)/(max-min)))
sobel=sobel.astype("uint8")
cv2.imshow("5.sobel", sobel)

#6.闭操作,先膨胀,再腐蚀
sobel=cv2.morphologyEx(sobel,cv2.MORPH_CLOSE,rectKernel) 
cv2.imshow("6.close", sobel)

#7.二值化突出轮廓,自动阈值范围 cv2.THRESH_BINARY|cv2.THRESH_OTSU
thresh=cv2.threshold(sobel,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1] 
cv2.imshow("7.thresh", thresh)

#8.再闭操作,先膨胀,再腐蚀
thresh=cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,sqKernel) 
cv2.imshow("8.close2", thresh)

#9.提取轮廓,并在图上标记轮廓
cnts,hierarchy=cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
mark=idimg.copy()
cv2.drawContours(mark,cnts,-1,(0,0,255),2)
cv2.imshow("9.mark", mark)

#身份证区域,虽然只有一个轮廓,这里还是用集合来处理
pidArea=[]
for(i,c) in enumerate(cnts):
    (x,y,w,h)=cv2.boundingRect(c)
    ar=w/float(h)
    if ar>12 and ar<40:
        pidArea.append((x,y,w,h)) #身份证号区域长宽比比较明显,算是一个比较明显的特征
        break
#pidArea=sorted(pidArea,key=lambda x:x[0])#若有多个区域,需进行从左到右排序

#10.模板匹配
output=[] 
for(i,(gx,gy,gw,gh)) in enumerate(pidArea):
    area=gray[gy-5:gy+gh+5,gx-5:gx+gw+5] #稍微扩展点区域,保证内容都能框住
    cv2.imshow("9.matched", area) 

    #下面操作跟处理模板图像一样:
    #先黑帽处理,移除干扰项,再二值化处理(自动阈值)    
    area = cv2.morphologyEx(area, cv2.MORPH_BLACKHAT, np.ones((10, 10), np.uint8))
    area=cv2.threshold(area,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1] 
    cv2.imshow("10.threshold", area) 

    # 再检测轮廓
    numContours,hierarchy=cv2.findContours(area.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)     

    #注意:此处需判断轮廓的个数是否是18个,对应18个数字 
    numContours=sort_contours(numContours,method="left-to-right")[0]

    #11.遍历轮廓,并逐个与模板图像进行匹配,将最高得分保留
    for c in numContours:
        (x,y,w,h)=cv2.boundingRect(c)
        roi=area[y:y+h,x:x+w]
        roi=cv2.resize(roi,(57,88)) #模板也做了缩放,相同尺寸进行比较
        scores=[]
        #跟10张模板图片进行模板匹配
        for (j,templateROI)in templates.items():
            result=cv2.matchTemplate(roi,templateROI,cv2.TM_CCOEFF)
            (_,score,_,_)=cv2.minMaxLoc(result)
            scores.append(score) #scores中存放了当前轮廓对应0-10中每个数字的概率

        #将分值最大的保留下来
        num=np.argmax(scores)  #np.argmax():获取array的某一个维度中数值最大的那个元素的索引,索引即为对应数字
        output.append(str(num))
        

#12.在原图上绘制识别结果
index=0
(gx,gy,gw,gh)=pidArea[0] #身份证区域位置
for c in numContours:
    (x,y,w,h)=cv2.boundingRect(c) #数字轮廓位置
    num=output[index]
    cv2.putText(idimg,str(num),(gx+x-8 ,gy+y-15),cv2.FONT_HERSHEY_SIMPLEX,0.65,(0,0,255),2) 
    index=index+1    
cv2.imshow("12.done", idimg)

print("识别结果:"+"".join(output))
cv2.waitKey(0)

 运行结果:

模板处理

图像处理

 特别说明:

1.对输入身份证照片有要求,必须是完全的身份证照片,不能有背景,不能变形。

2.只识别了身份证号区域,如需识别其他信息,可以自行修改代码。

3.如无法识别你的图片,请手动调试代码,注释都在代码里,修改对应步骤参数,多试几次。

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

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

相关文章

RabbitMQ Exchange类型和工作模式介绍

RabbitMQ Exchange类型和工作模式介绍 一RabbitMQ Exchange类型1.1.Fanout1.2.Direct1.3.Topic1.4.Headers 二 RabbitMQ 工作模式介绍2.1.work工作模式(资源的竞争)2.2.publish/subscribe发布订阅(共享资源)2.3.routing路由模式应用--direct交换器 2.4.topic 主题模式(路由模式…

CSDN个性化推荐系统-负反馈测试

文章目录 前言一、uc不感兴趣标签过滤测试1.uc不感兴趣标签获取(uc_unlike_tag_list)1.1个人中心界面1.2从标签中可以发现什么&#xff1f;1.3与研发确认点1.4设计开发1.5接口获取结果 2.推荐流文章标签获取(tag_list)2.1部分代码2.2基本标签校验2.3基本标签校验结果 3.推荐流u…

华为云专家出品《深入理解边缘计算》电子书上线

华为开发者大会PaaS生态电子书推荐&#xff0c;助你成为了不起的开发者&#xff01; 什么是边缘计算&#xff1f;边缘计算的应用场景有哪些&#xff1f; 华为云出品《深入理解边缘计算》电子书上线 带你系统理解云、边、端协同的相关原理 了解开源项目的源码分析流程 学成能…

Linux--在当前路径下创建目录/文件夹指令:mkdir

语法&#xff1a; mkdir [选项] 文件名 功能&#xff1a; 在当前目录下创建一个名为 “文件名”的目录 常用选项&#xff1a; -p, --parents 可以是一个路径名称。此时若路径中的某些目录尚不存在,加上此选项后,系统将自动建立好那些不存在的目录&#xff0c;即一次可以建立…

基于Ant DesignPro Vue + SpringBoot 前后端分离 - 后端微服化 + 接口网关 + Nacos + Sentinel

基于Ant DesignPro Vue SpringBoot 前后端分离 - 后端微服化 接口网关 Nacos Sentinel 通过Ant DesignPro Vue SpringBoot 搭建的后台管理系统后&#xff0c;实现了前后端分离&#xff0c;并实现了登录认证&#xff0c;认证成功后返回该用户相应权限范围内可见的菜单。 后…

Linux基础:Vim编辑器实用指南

前言 Linux基础是学习云原生的重中之重&#xff0c;如果你还不知道学习路线可以参考&#xff1a; 耗时3个月&#xff0c;线下访谈30 csdn大佬&#xff0c;规划出了我的云原生学习路线 文章目录 前言vim的介绍vim的四种模式1. 插入模式1.1 进入插入模式&#xff1a;1.2 退出插入…

[Pytorch]Broadcasting广播机制

文章目录 Broadcasting广播机制BroadcastableBroadcasting Broadcasting广播机制 Broadcasting机制用于在不同维度的张量进行运算时进行维度的自动增加与扩展&#xff0c;Broadcasting机制使用的前提是两个参与运算的张量是可broadcastable的。 Broadcastable 怎样的两个向量…

【数据分析之道-Matplotlib(七)】Matplotlib直方图

文章目录 专栏导读1、hist()基本语法2、使用 hist() 函数绘制多个数据组的直方图3、修改直方图的颜色及边框颜色4、六一儿童节为主题&#xff0c;使用直方图进行可视化 专栏导读 ✍ 作者简介&#xff1a;i阿极&#xff0c;CSDN Python领域新星创作者&#xff0c;专注于分享pyth…

web入门——springboot、HTTP协议

这里写目录标题 springboot入门 http协议概念以及特点请求协议格式请求头的一些含义解释 响应协议格式具体的状态码以及响应头的一些含义解释 协议解析 springboot 入门 http协议 概念以及特点 请求协议 格式 包括请求行、请求头、请求体三部分&#xff08;请求体是pos请求方…

想要让视频素材格式快速调整转换的方法分享

有时候有些视频播放软件不支持播放某些格式的视频文件&#xff1f;那要怎么解决呢&#xff1f;换一个播放软件&#xff1f;不妨试试批量转换视频格式&#xff0c;简单的几步操作就能快速解决烦恼&#xff0c;跟着小编一起来看看具体的操作环节吧。 首先先进入“固乔科技”的官网…

MapReduce分布式计算(二)

MapReduce工作流程 原始数据File 1T数据被切分成块存放在HDFS上&#xff0c;每一个块有128M大小 数据块Block hdfs上数据存储的一个单元,同一个文件中块的大小都是相同的 因为数据存储到HDFS上不可变&#xff0c;所以有可能块的数量和集群的计算能力不匹配 我们需要一个动态…

MySQL中的DDL操作,MySQL中DML操作,MySQL查询数据,SQL函数,MySQL中的索引,MySQL事务,MySQL的用户管理,MySQL分页查询

目录 MySQL中的DDL操作 一、创建表与删除表 1&#xff0c;创建表 2&#xff0c;查看已创建的表。 3&#xff0c;删除表 二、修改表 1&#xff0c;修改表名 2&#xff0c;修改列名 3&#xff0c;修改列类型 4&#xff0c;添加新列 5&#xff0c;删除指定列 三、MySQ…

ML算法——Support Vector Machine随笔【机器学习】

文章目录 4、Support Vector Machine (SVM)4.1、理论部分4.1.1、更优的决策边界4.1.2、解决低维不可分问题 4.2、sklearn 实现4.2.1、SVM 分类&#xff08;SVC&#xff09;4.2.2、SVM回归&#xff08;SVR&#xff09;4.2.3、网格调参 4.3、案例 4、Support Vector Machine (SVM…

UE5 Stride Warping Orientation Warping功能学习

在UE5的 Lyra Demo中&#xff0c;运用到了各类动画Warping&#xff08;动画扭曲&#xff09;技术&#xff0c;通过各类Warping节点在动画蓝图中的合理组织&#xff0c;可以有效的解决运动滑步问题&#xff0c;并为动画增添更多细节。 本文主要基于Animation Warping插件讲一下…

python 加速(1)

文章目录 简单步骤像Python一样做torch 的一切安装Cmake安装 Torch &#xff08;GPU&#xff09;CMakeLists.txt试用小样设置 CLion 环境 Cuda配置VS C 环境建上手的文件step1: interpolation.cppstep2: interpolation_kernel.custep3: include/ utils.hstep4: setup.pystep5: …

【系统架构】第五章-软件工程基础知识(软件测试、净室软件工程、基于构件的软件工程、 软件项目管理)

软考-系统架构设计师知识点提炼-系统架构设计师教程&#xff08;第2版&#xff09; 软件测试 一、测试方法 以测试过程中程序执行状态为依据可分为静态测试&#xff08;ST&#xff09;和动态测试&#xff08;DT&#xff09; 以具体实现算法细节和系统内部结构的相关情况为根据…

【强化学习】常用算法之一 “A3C”

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typeblog个…

VUE3-组件问题

VUE3-组件问题 文章目录 VUE3-组件问题一、S-Table1.问题描述2.问题展示3.问题解决 二、form表单无法显示1.问题描述2.问题展示3.问题解决 三、input 框为不可编辑状态四、Echarts组件未渲染五、图片正常引用&#xff0c;但是部署服务器部署不上去&#xff0c;看不到图片1.图片…

element封装 table表格 ,插槽的使用,修改el-table-column的值

举例 vue2这种不封装的 直接写的很罗嗦麻烦 下面圈起来的可以封装一个对象 进行循环 弊端: 循环后 无法进行获取更改某一列的值 比如data日期我需要转换年月日 不循环我直接在这个el-table-column的这一列进行写&#xff08;如下&#xff09; <el-table-column label&quo…

Vue3解决:[Vue warn]: Failed to resolve component: el-table(或el-button) 的三种解决方案

1、问题描述&#xff1a; 其一、报错为&#xff1a; [Vue warn]: Failed to resolve component: el-table If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement. at <App> 或者&#xff1a; …