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=Falsei=0if method=="right-to-left" or method=="bottom-to-top":reverse=Trueif method=="top-to-bottom" or method=="bottom-to-top":i=1boundingBoxes=[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.hqwc.cn/news/7456.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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

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

2. 计算点到平面的投影

参考 https://www.cnblogs.com/nobodyzhou/p/6145030.html 所以用各种平面提取算法后&#xff0c;得到的平面方程, 注意此处的平面方程abcd已经是归一化了。 a x b y c z d 0 ax by cz d 0 axbyczd0 此时的原点到该平面点的投影点为 C P ( − a d , − b d , − c …

Linux:DNS服务(bind)

目录 环境 主服务器和从服务器的配置环境 主服务器 从服务器 主DNS配置文件 dns从服务器配置 环境 如果你只需要主dns服务器那么你只需要挑着主dns服务器配置看即可 我这里使用了4台虚拟机&#xff0c;你也可以不使用这么多根据你的电脑性能去调整 他们必须要在同一个网段…

(十九)数据编辑——属性编辑②

数据编辑——属性编辑② 使用键盘输入值并不是编辑表中值的唯一方式。在某些情况下&#xff0c;为了设置字段值&#xff0c;可能要对单条记录甚至是所有记录执行数学计算。ArcMap 中的字段计算器可以对所有或所选记录进行简单和高级计算。 此外&#xff0c;还可以基于字段计算…

每天一点Python——day47

#第四十七天字典生成式&#xff1a;字典生成的公式 a[ab,ac,ad] b[12,13,14] 把a&#xff0c;b列表合并为字典 将第一个列表中的元素作为字典当中的键&#xff0c;第二个列表中的元素作为字典当中的值 这个过程我们需要打包 我们需要使用内置函数zip()生成字典 #如图所示 #例&a…

基于深度学习的高精度塑料瓶检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度塑料瓶检测识别系统可用于日常生活中或野外来检测与定位塑料瓶目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的塑料瓶目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检…

推荐信模版(英文)计算机专业

推荐信模版&#xff08;英文&#xff09;计算机专业 ✅ 内容已校对 润色 ©️ 文章来源&#xff1a;https://blog.csdn.net/IYXUAN&#xff0c;原创内容&#xff0c;转载请注明&#xff01; 推荐信&#xff08;一&#xff09; January 4, 2023 Dear Admissions Committe…

vue使用mapbox地图

1、下载依赖 npm install --save mapbox-gl mapbox/mapbox-gl-language 2、引入mapBox&#xff0c;将引入的内容封装为js文件 在api/map文件夹下新建mapbox.js文件 代码&#xff1a; import mapboxgl from mapbox-gl import mapbox-gl/dist/mapbox-gl.css import MapboxLang…

linux上搭建nfs服务

NFS&#xff08;Network File System&#xff09;&#xff1a;它最大的功能就是可以通过网络&#xff0c;让不同的机器、不同的操作系统可以共享彼此的文件。 NFS服务器可以让PC将网络中的NFS服务器共享的目录挂载到本地端的文件系统中&#xff0c;而在本地端的系统中来看&…

【209. 长度最小的子数组】

目录 一、题目解析二、算法原理三、代码实现 一、题目解析 二、算法原理 注意点&#xff1a; 三、代码实现 我自己写的代码(我的评价是很挫) class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {int left 0, right -1, ret INT_MAX…

MyCat2介绍以及部署和读写分离/分库分表(MyCat2.0)

一&#xff0c;MyCat入门 1.什么是mycat 官网&#xff1a;http://www.mycat.org.cn/​ mycat是数据库中间件 它可以干什么&#xff1f; 读写分离数据分片&#xff1a;垂直拆分&#xff0c;水平拆分多数据源整合 2.数据库中间件 ​ 中间件&#xff1a;是一类连接软件组件和…

FPGA实验三:状态机的设计

目录 一、实验目的 二、实验要求 三、实验代码 1.design source文件部分代码 2.测试文件代码 四、实验结果及分析 1、引脚锁定 2、仿真波形及分析 &#xff08;1&#xff09;设计好序列检测器 &#xff08;2&#xff09;仿真波形&#xff08;检测11010&#xff09; 3…