【计算机视觉】OpenCV实现身份证号识别:从图像到文本

2024-01-22 10:10

本文主要是介绍【计算机视觉】OpenCV实现身份证号识别:从图像到文本,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

目录

 

项目介绍:

代码详解:

完整代码展示:


项目介绍:

本文是一个基于Python和OpenCV的身份证号识别项目。它的主要目标是自动识别和提取身份证上的身份证号码。

下面是项目所用到的图片,大家可以自行下载:

  • 待识别身份证照片:
card_id.jpg
  • 用于数字模板匹配的图片: 
TP.png

该项目的工作流程大致如下:

  1. 图像预处理:首先,需要对输入的身份证图像进行预处理,包括灰度化、二值化、去噪等操作,以便后续能更准确地进行文字识别。
  2. 文字定位和分割:接着,使用OpenCV中的图像处理技术,如边缘检测、形态学操作等,对预处理后的图像进行文字定位和分割,获取每个数字或字母的位置。
  3. 模板匹配:然后,利用模板匹配技术,对每个分割出来的数字或字母进行匹配。
  4. 信息整合:最后,将所有识别出的数字或字母按照它们在身份证上的位置进行排列,得到完整的身份证号码。

这个项目有很多实际的应用场景,比如在自动化办公、身份验证等场合,可以大大提高工作效率和准确性,话不多说,直接进入正题。

代码详解:

1.安装Python和导入所需的库

import cv2
import numpy as np

2.定义绘图函数,以便后续便于展示图片

#绘图展示
def cv_show(name,image):cv2.imshow(name,image)cv2.waitKey(0)

3.定义排序函数,用于排序轮廓(contours)

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

 4.定义一个resize函数,用于调整图像大小。与cv2.resize不同的是,允许你基于指定的高度和/或宽度来调整图像的大小

def resize(image,width=None,height=None,inter=cv2.INTER_AREA):dim=None(h,w)=image.shape[:2]if width is None and height is None:return imageif width is None:r=height/float(h)dim=(int(w*r),height)else:r=width/float(w)dim=(width,int(h*r))resize=cv2.resize(image,dim,interpolation=inter)return resize

5.模板图像中的数字定位处理

'''模板图像中的数字定位处理'''
img=cv2.imread("TP.png")
cv_show('img',img)
gray=cv2.imread("TP.png",0)
ref=cv2.threshold(gray,150,255,cv2.THRESH_BINARY_INV)[1]
cv_show('ref',ref)# 计算轮廓: cv2.findContours()数接受的参数为二值图,即黑白的(不是灰度图)
# CV2.RETR_EXTERNAL 只检测外轮廓,CV2.CHAIN APPROX SIMPLE只保留终点坐标
refCnts,hierarchy=cv2.findContours(ref.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,refCnts,-1,(0,255,0),2)
cv_show('img',img)refCnts=sort_contours(refCnts,method='left-to-right')[0]
# 保在模板中每个数字对应的像素值
digits={}
for (i,c) in enumerate(refCnts):(x,y,w,h)=cv2.boundingRect(c)roi=ref[y-2:y+h+2,x-2:x+w+2]roi=cv2.resize(roi,(57,88))roi=cv2.bitwise_not(roi)# cv_show('roi',roi)digits[i]=roi
cv2.destroyAllWindows()

图片处理结果展示:

 6.身份证图像处理

'''身份证号识别'''img=cv2.imread('./card_id.jpg')
cv_show('img',img)gray=cv2.imread('./card_id.jpg',0)
cv_show('gray',gray)ref=cv2.threshold(gray,120,255,cv2.THRESH_BINARY_INV)[1]
cv_show('ref',ref)# 计算轮廓: cv2.findContours()数接受的参数为二值图,即黑白的(不是灰度图)
# CV2.RETR_EXTERNAL 只检测外轮廓,CV2.CHAIN APPROX SIMPLE只保留终点坐标
refCnts,hierarchy=cv2.findContours(ref.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,refCnts,-1,(0,255,0),2)
cv_show('img',img)cv2.destroyAllWindows()# 遍历轮廓,找到数字部分像素区城
locs = []
for (i, c) in enumerate(refCnts):(x,y,w,h) = cv2.boundingRect(c) # 计外接知形# 选择合适的区域,根据实际任务来if (y > 330 and y< 360) and x>220: #符的留下来locs.append((x,y,w,h))
locs = sorted(locs, key=lambda x:x[0])

处理结果展示:

7.模板匹配并添加文本

output = [] # 用于存储最终结果
for (i, (gX,gY,gW, gH)) in enumerate(locs):groupOutput = []group = gray[gY - 2:gY + gH + 2,gX - 2:gX + gW + 2]# 适当加一点边界cv_show('group',group)#预处理group = cv2.threshold(group,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]# cv_show('group',group)# 计算每一组的轮廓digitCnts,hierarchy = cv2.findContours(group.copy(),cv2.RETR_EXTERNAL ,cv2.CHAIN_APPROX_SIMPLE)digitCnts = sort_contours(digitCnts,method='left-to-right')[0]# 计算每一组中的每一个数值for c in digitCnts:#找到当前数值的轮廓,resize成合适的的大小(x,y,w,h) = cv2.boundingRect(c)roi = group[y:y + h,x:x + w]roi = cv2.resize(roi,(57,88))# cv_show('roi',roi)'''-------使用模板匹配,计算匹配得分-----------'''scores = []# 在模板中计算每一个得分for (digit, digitROI) in digits.items():# 模板匹配result = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF)(_, score, _, _) = cv2.minMaxLoc(result)scores.append(score)# 得到最合适的数字groupOutput.append(str(np.argmax(scores)))# 画出来cv2.rectangle(img, (gX - 5, gY - 5), (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)# cv2.putText()是OpenCV库中的一个函数,用于在图像上添加文本。cv2.putText(img, "".join(groupOutput), (gX, gY - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)output.extend(groupOutput)  # 得到结果

模板匹配后的识别结果:

8.打印结果

# 打印结果
print("ID Card  #: {}".format("".join(output)))
cv2.imshow("Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

完整代码展示:

# -*- coding: utf-8 -*-
# @Time : 2023/10/18 9:32
# @Author :Muzi
# @File : id_card.py
# @Software: PyCharmimport cv2
#绘图展示
def cv_show(name,image):cv2.imshow(name,image)cv2.waitKey(0)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,boundingBoxesdef resize(image,width=None,height=None,inter=cv2.INTER_AREA):dim=None(h,w)=image.shape[:2]if width is None and height is None:return imageif width is None:r=height/float(h)dim=(int(w*r),height)else:r=width/float(w)dim=(width,int(h*r))resize=cv2.resize(image,dim,interpolation=inter)return resize
'''模板图像中的数字定位处理'''
img=cv2.imread("TP.png")
cv_show('img',img)
gray=cv2.imread("TP.png",0)
ref=cv2.threshold(gray,150,255,cv2.THRESH_BINARY_INV)[1]
cv_show('ref',ref)# 计算轮廓: cv2.findContours()数接受的参数为二值图,即黑白的(不是灰度图)
# CV2.RETR_EXTERNAL 只检测外轮廓,CV2.CHAIN APPROX SIMPLE只保留终点坐标
refCnts,hierarchy=cv2.findContours(ref.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,refCnts,-1,(0,255,0),2)
cv_show('img',img)refCnts=sort_contours(refCnts,method='left-to-right')[0]
# 保在模板中每个数字对应的像素值
digits={}
for (i,c) in enumerate(refCnts):(x,y,w,h)=cv2.boundingRect(c)roi=ref[y-2:y+h+2,x-2:x+w+2]roi=cv2.resize(roi,(57,88))roi=cv2.bitwise_not(roi)# cv_show('roi',roi)digits[i]=roi
cv2.destroyAllWindows()'''身份证号识别'''img=cv2.imread('./card_id.jpg')
cv_show('img',img)gray=cv2.imread('./card_id.jpg',0)
cv_show('gray',gray)ref=cv2.threshold(gray,120,255,cv2.THRESH_BINARY_INV)[1]
cv_show('ref',ref)# 计算轮廓: cv2.findContours()数接受的参数为二值图,即黑白的(不是灰度图)
# CV2.RETR_EXTERNAL 只检测外轮廓,CV2.CHAIN APPROX SIMPLE只保留终点坐标
refCnts,hierarchy=cv2.findContours(ref.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,refCnts,-1,(0,255,0),2)
cv_show('img',img)cv2.destroyAllWindows()# 遍历轮廓,找到数字部分像素区城
locs = []
for (i, c) in enumerate(refCnts):(x,y,w,h) = cv2.boundingRect(c) # 计外接知形ar = w / float(h)# 选择合适的区域,根据实际任务来if (y > 330 and y< 360) and x>220: #符的留下来locs.append((x,y,w,h))cnt = refCnts[20](x, y), r = cv2.minEnclosingCircle(cnt)  # 计算轮廓的外接圆
locs = sorted(locs, key=lambda x:x[0])
import numpy as np
output = []
for (i, (gX,gY,gW, gH)) in enumerate(locs):groupOutput = []group = gray[gY - 2:gY + gH + 2,gX - 2:gX + gW + 2]# 适当加一点边界cv_show('group',group)#预处理group = cv2.threshold(group,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]# cv_show('group',group)# 计算每一组的轮廓digitCnts,hierarchy = cv2.findContours(group.copy(),cv2.RETR_EXTERNAL ,cv2.CHAIN_APPROX_SIMPLE)digitCnts = sort_contours(digitCnts,method='left-to-right')[0]# 计算每一组中的每一个数值for c in digitCnts:#找到当前数值的轮廓,resize成合适的的大小(x,y,w,h) = cv2.boundingRect(c)roi = group[y:y + h,x:x + w]roi = cv2.resize(roi,(57,88))# cv_show('roi',roi)'''-------使用模板匹配,计算匹配得分-----------'''scores = []# 在模板中计算每一个得分for (digit, digitROI) in digits.items():# 模板匹配result = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF)(_, score, _, _) = cv2.minMaxLoc(result)scores.append(score)# 得到最合适的数字groupOutput.append(str(np.argmax(scores)))# 画出来cv2.rectangle(img, (gX - 5, gY - 5), (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)# cv2.putText()是OpenCV库中的一个函数,用于在图像上添加文本。cv2.putText(img, "".join(groupOutput), (gX, gY - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)output.extend(groupOutput)  # 得到结果# 打印结果
print("Card ID #: {}".format("".join(output)))
cv2.imshow("Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

这篇关于【计算机视觉】OpenCV实现身份证号识别:从图像到文本的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/632658

相关文章

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P