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

news2024/11/19 16:48:14

需求描述:

通过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.如无法识别你的图片,请手动调试代码,注释都在代码里,修改对应步骤参数,多试几次。

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

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

相关文章

坚鹏:中国邮储银行金融科技前沿技术发展与应用场景第1期培训

中国邮政储蓄银行金融科技前沿技术发展与应用场景第1期培训圆满结束 中国邮政储蓄银行拥有优良的资产质量和显著的成长潜力&#xff0c;是中国领先的大型零售银行。2016年9月在香港联交所挂牌上市&#xff0c;2019年12月在上交所挂牌上市。中国邮政储蓄银行拥有近4万个营业网点…

基于java+swing+mysql图书管理系统V6.0

基于javaswingmysql图书管理系统V6.0 一、系统介绍二、功能展示1.项目骨架2.数据库表3.项目内容4.登陆界面5.管理员-读者注册6、管理员-书籍入库7、管理员-书籍更新8、管理员-书库管理9、管理员-读者更新10、用户-还书11、用户-借书 四、其它1.其他系统实现五.获取源码 一、系统…

【3Ds Max】常用的基本初始化设置

目录 一、单位设置 二、首选项设置 2.1 撤销次数设置 2.2 设置保存时压缩 2.3 设置自动保存时间间隔 2.4 选中模型时高亮显示 一、单位设置 我们以设置毫米单位为例 在 “自定义-》单位设置” 中进行设置 点击“系统单位设置”按钮 如下设置就表示&#xff1a;1个单位长度…

Jmeter_响应数据为空以及中文乱码

目录 一、响应数据为空 解决方法 二、响应中文乱码 产生原因 解决方法 一、响应数据为空 最近做测试接口&#xff0c;使用同样的请求方式、地址、参数和header&#xff0c;在postman中能正常响应&#xff0c;接收数据的也正常&#xff0c;但是在Jmeter中&#xff0c;虽然…

FPGA-DFPGL22学习4-仿真平台学习

文章目录 前言一、仿真的步骤二、使用步骤1.PDS编译仿真库2.编写仿真tb文件3.选择行为仿真4.查看观察窗口5.修改代码后重新编译 总结 前言 和原子哥一起学习FPGA 开发环境&#xff1a;正点原子 ATK-DFPGL22G 开发板 参考书籍&#xff1a; 《ATK-DFPGL22G之FPGA开发指南_V1.1…

OSPF故障定位没思路?照这篇抄就行

我的网工朋友大家好。 好久没聊OSPF技术了&#xff0c;相关基础且经典的内容&#xff0c;公众号陆陆续续分享过一些&#xff0c;趣味科普&#xff0c;面试考题&#xff0c;实验操作&#xff0c;都有涉及。 按照惯例&#xff0c;先给你整一波优质的往期内容&#xff1a; 《 5个…

考研算法30天:堆排序 【堆排序】

原先自己写过这道题的题解&#xff0c;但是当时水平有限所以这次重写一次。 (1条消息) 堆的创建&#xff08;题目&#xff1a;堆排序&#xff09;_空が笑っています的博客-CSDN博客 算法介绍 我在上陈越姥姥的课程之后我学会了如何用数组表示一个堆(堆其实就是根节点大于或者…

本地已安装Git。 但是VSCode提示:未找到 Git。点击Git侧边栏选项,按钮都是灰的

问题&#xff1a; 解决方案&#xff1a; 1、点击设置 2、在输入框中输入git.path&#xff0c;然后点击“在settings.json中编辑”&#xff0c; 打开settings.json文件&#xff0c;进行git.path配置&#xff1b; 3、配置git.path&#xff0c;下面两种格式都可以&#xff0c;设…

Google Hacking爬虫修改版

这里是个演示 项目是根据这个项目进行修改的 修改了哪些东西&#xff1a; 新增个模式&#xff0c;一个Request&#xff0c;一个Selenium原版只能读第一页&#xff0c;修改成可以自动判断添加了更多的搜索摸板输出csv&#xff0c;url标题域名 针对第三点&#xff1a; 添加了一…

自学黑客(网络安全),一般人我劝你还是算了吧(自学网络安全学习路线--第十三章 网络应用安全上)【建议收藏】

文章目录 一、自学网络安全学习的误区和陷阱二、学习网络安全的一些前期准备三、自学网络安全学习路线一、网络攻击的步骤1、搜集初始信息2、搜确定攻击目标的IP地址范围3、扫描存活主机开放的端口4、分析目标系统 二、口令安全1、口令破解2、口令破解方法3、设置安全的口令4、…

【pycharm】 Anaconda3 和 pycharm 安装配置1

anaconda3 下载地址 Anaconda3-2023.03-1-Windows-x86_64.exeC:\ProgramData\anaconda3 安装路径解释器默认是从online下载 或者3.10 实际上我在tbuild下有python3.9

python spider 爬虫 之 解析 xpath 、jsonpath、BeautifulSoup (二)

Jsonpath 安装&#xff1a; pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jsonpath 使用&#xff1a;jsonpath 只能解析本地文件&#xff0c;跟xpath不一样 objjson.load(open(‘json文件’&#xff0c;‘r’, encoding‘utf-8’)) json.load(是文件&#xff0c;…

关于云服务器CentOS7.6版本安装宝塔面板后,点击终端无响应解决方案

问题再现: 下面是我沟通宝塔客服后&#xff0c;给的解决方案。 我在百般无奈的情况下、卸载了宝塔后&#xff0c;最终躺平&#xff0c;选择了问宝塔官方客服 1、从华为提供的远程登录方式选一种 二、输入服务器密码通过ssh远程登录 服务器 二、执行宝塔官方提供的 命令执…

centos7 配置jenkins run docker

本机环境已有jdk11 一、安装配置maven环境 1、下载maven wget https://dlcdn.apache.org/maven/maven-3/3.9.3/binaries/apache-maven-3.9.3-bin.tar.gz 2、解压 tar -zxvf apache-maven-3.9.3-bin.tar.gz 3、移动位置 mv apache-maven-3.9.3 /usr/local/ 4、加入环境变…

Nvidia官方视频编解码性能

NVIDIA VIDEO CODEC SDK | NVIDIA Developer 1080P解码性能&#xff1a; 720P解码性能&#xff1a; 详细的参见官方的链接地址&#xff0c;对于GPU的解码fps能力&#xff0c;可以作为评估参照&#xff01;

Intellij IDEA 插件开发 | 京东云技术团队

写在前面 很多idea插件文档更多的是介绍如何创建一个简单的idea插件&#xff0c;本篇文章从开发环境、demo、生态组件、添加依赖包、源码解读、网络请求、渲染数据、页面交互等方面介绍&#xff0c;是一篇能够满足基本的插件开发工程要求的文章。 如有疏漏欢迎指正&#xff0…

汇编端口

输出年月日 时分秒 assume cs:code , ds:data data segmentdb 0 data ends code segment start:mov ax,datamov ds,axmov cx,3mov di,100mov bl,0mov ah,0mov byte ptr ds:[0],0 st1:mov al,blout 70h,alin al,71hcall showptrsub di,2add bl,2add byte ptr ds:[0],1loop st1mo…

STM32 标准库 任意长度收发

void UART5_IRQHandler(void) //串口1中断服务程序 {u8 Res;if(USART_GetITStatus(UART5, USART_IT_RXNE) ! RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾){Res USART_ReceiveData(UART5);//(USART1->DR); //读取接收到的数据USART_RX_BUF[USART_RX…

记一次PHP的laravel框架数据库查询报错500

错误的原因 是有个给第三方回调的接口&#xff0c;由于第三方接口是不需要传token的因此在本地测试的时候&#xff0c;我们是将Header加入token的字段&#xff0c;测试一切正常&#xff0c;但是到显示调试过程中一直出现500。 经过不断地定位&#xff0c;发现是在通过订单号到…

almalinux下卸载并升级安装10.9的mariadb(实操)

MariaDB 简介 MariaDB Server 是一个通用的开源关系数据库管理系统。 它是世界上最受欢迎的数据库服务器之一&#xff0c;拥有包括 Wikipedia、WordPress.com 和 Google 在内的知名用户。 MariaDB Server 在 GPLv2 开源许可下发布&#xff0c;并保证保持开源。 它可用于高可用…