当前位置: 首页 > news >正文

OpenCV 实战:基于模板匹配的身份证号自动识别系统

目录

项目概述

一、核心工具函数实现

二、模板图像预处理

1. 模板图像二值化处理

2. 提取并排序数字轮廓

三、身份证号识别流程

1. 身份证图像预处理

2. 定位身份证号区域

3. 提取并识别每个数字

五、总结


在计算机视觉领域,证件信息的自动识别是一个非常实用的技术方向。本文将详细介绍如何使用 OpenCV 库实现身份证号的自动识别系统,通过模板匹配的方法精准提取身份证上的数字信息。

项目概述

本项目旨在通过计算机视觉技术,自动识别身份证图片中的身份证号码。系统主要分为三个核心模块:自定义工具函数、模板图像预处理、身份证号定位与识别。整个流程基于 OpenCV 库实现,不需要复杂的深度学习框架,适合入门级学习者理解和实践。

技术栈:

  • Python 3.x
  • OpenCV (cv2) 库
  • NumPy 库

一、核心工具函数实现

首先,我们需要实现两个核心工具函数:图像展示函数和轮廓排序函数,这两个函数将在整个项目中反复使用。

import cv2
import numpy as npdef cv_show(name, image):"""展示图像的通用函数:param name: 窗口名称:param image: 要展示的图像"""cv2.imshow(name, image)cv2.waitKey(0)  # 等待按键输入cv2.destroyWindow(name)  # 关闭当前窗口def sort_contours(cnts, method='left-to-right'):"""对轮廓进行排序:param cnts: 轮廓列表:param method: 排序方式,可选值:'left-to-right'、'right-to-left'、'top-to-bottom'、'bottom-to-top':return: 排序后的轮廓列表和对应的边界框列表"""reverse = False  # 排序方向标识i = 0  # 排序依据的维度# 根据排序方式调整参数if method == 'right-to-left' or method == 'bottom-to-top':reverse = Trueif method == 'top-to-bottom' or method == 'bottom-to-top':i = 1  # 按y坐标排序# 计算每个轮廓的边界框并排序bounding_boxes = [cv2.boundingRect(c) for c in cnts](cnts, bounding_boxes) = zip(*sorted(zip(cnts, bounding_boxes),key=lambda b: b[1][i], reverse=reverse))return cnts, bounding_boxes

函数说明

  • cv_show():封装了 OpenCV 的图像显示功能,自动等待用户按键并关闭窗口
  • sort_contours():根据指定方式对轮廓进行排序,这在处理数字序列时非常重要,确保数字顺序正确

二、模板图像预处理

模板匹配的核心是先建立数字模板库,我们需要从包含 0-9 数字的模板图像中提取每个数字的特征。

模版如下:

1. 模板图像二值化处理

# 读取模板图像
img = cv2.imread("shuzi.png")
cv_show('模板原图', img)# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv_show('模板灰度图', gray)# 二值化处理(反色处理,使数字为白色,背景为黑色)
ref = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV)[1]
cv_show('模板二值化图', ref)

运行结果如下:

处理说明

  • 首先读取包含 0-9 数字的模板图像
  • 转换为灰度图以简化处理
  • 应用反相二值化,将数字变为白色 (255),背景变为黑色 (0),便于后续轮廓检测

2. 提取并排序数字轮廓

# 寻找轮廓
_, 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)# 按从左到右顺序排序轮廓
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(f'数字{i}', roi)# 存储到字典中digits[i] = roicv2.destroyAllWindows()

处理说明

  • 使用cv2.findContours()函数检测数字轮廓,只检测外轮廓
  • 对轮廓进行从左到右排序,确保数字顺序正确
  • 裁剪每个数字区域并调整为统一尺寸 (57x88),便于后续匹配
  • 将处理好的数字模板存储在字典中,建立索引与数字的对应关系

三、身份证号识别流程

1. 身份证图像预处理

# 读取身份证图像
img = cv2.imread('./shenfen.jpg')
imgg = img.copy()  # 保存副本用于后续绘制结果
cv_show('身份证原图', img)# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv_show('身份证灰度图', gray)# 二值化处理
ref = cv2.threshold(gray, 120, 255, cv2.THRESH_BINARY_INV)[1]
cv_show('身份证二值化图', ref)

2. 定位身份证号区域

# 寻找身份证图像中的所有轮廓
_, refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 绘制所有轮廓,观察轮廓检测效果
a = cv2.drawContours(img.copy(), refCnts, -1, (0, 255, 0), 2)
cv_show('带轮廓的身份证', a)# 筛选身份证号区域的轮廓
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))# 按x坐标排序,确保数字顺序正确
locs = sorted(locs, key=lambda x: x[0])

定位说明

  • 首先检测身份证图像中的所有外轮廓
  • 根据身份证号的大致位置(通常在身份证下方)设置坐标筛选条件
  • 对筛选出的轮廓按 x 坐标排序,确保数字从左到右排列

3. 提取并识别每个数字

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(f'数字区域{i}', group)# 二值化处理(使用OTSU自动阈值)group = cv2.threshold(group, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]cv_show(f'二值化数字{i}', group)# 调整为与模板相同的尺寸roi = cv2.resize(group, (57, 88))cv_show(f'标准化数字{i}', 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(imgg, (gX-5, gY-5), (gX+gW+5, gY+gH+5), (0, 0, 255), 1)cv2.putText(imgg, "".join(groupOutput), (gX, gY-15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)output.extend(groupOutput)# 显示最终结果
print("识别到的身份证号: {}".format("".join(output)))
cv_show("识别结果", imgg)
cv2.destroyAllWindows()

识别说明

  • 逐个提取身份证号区域的每个数字
  • 对每个数字进行二值化和尺寸标准化,使其与模板保持一致
  • 使用cv2.matchTemplate()进行模板匹配,计算与每个数字模板的匹配得分
  • 选择得分最高的数字作为识别结果,并在原图上标记
  • 最终将所有识别结果拼接成完整的身份证号

五、总结

本项目通过 OpenCV 实现了基于模板匹配的身份证号识别系统,主要流程包括:

  1. 自定义工具函数辅助图像处理
  2. 从模板图像中提取数字特征并建立模板库
  3. 对身份证图像进行预处理和轮廓分析
  4. 定位并提取身份证号区域的每个数字
  5. 通过模板匹配识别数字并输出结果

该方法不需要复杂的深度学习模型,实现简单且易于理解,适合作为计算机视觉入门实践项目。对于精度要求更高的场景,可以考虑结合深度学习方法(如 CNN)进行优化。


文章转载自:

http://RxQWmapv.mgLqf.cn
http://2ZP6fn7W.mgLqf.cn
http://4xiGf33f.mgLqf.cn
http://1OePKTzz.mgLqf.cn
http://HAe1Sp51.mgLqf.cn
http://3r6rR9hr.mgLqf.cn
http://TEjMVaNb.mgLqf.cn
http://maR9HVvJ.mgLqf.cn
http://QAfrSOOI.mgLqf.cn
http://GbbrFq6t.mgLqf.cn
http://GJVmbrRW.mgLqf.cn
http://lMEz7sIZ.mgLqf.cn
http://9Qc6rLr3.mgLqf.cn
http://PUfPuRNK.mgLqf.cn
http://asbwJkjC.mgLqf.cn
http://KcSGpSos.mgLqf.cn
http://aXMMo8eL.mgLqf.cn
http://3itKALcG.mgLqf.cn
http://O7SpDGkg.mgLqf.cn
http://Ro5q6UNH.mgLqf.cn
http://SrIoRDt6.mgLqf.cn
http://IHlbk0ZX.mgLqf.cn
http://AyLdsfR5.mgLqf.cn
http://tH0MVnhX.mgLqf.cn
http://JGYFdxoG.mgLqf.cn
http://eP77bnnb.mgLqf.cn
http://dTavHsnb.mgLqf.cn
http://Blkn6xVc.mgLqf.cn
http://Uh7OpJ2v.mgLqf.cn
http://wJdk9j5p.mgLqf.cn
http://www.dtcms.com/a/375568.html

相关文章:

  • java中将租户ID包装为JSQLParser的StringValue表达式对象,JSQLParser指的是?
  • CMake工程指南
  • 单北斗GNSS该如何在变形监测中发挥最大效能?
  • 大数据毕业设计-基于大数据的高考志愿填报推荐系统(高分计算机毕业设计选题·定制开发·真正大数据)
  • 分布式锁redis
  • Java学习之——“IO流“的进阶流之转换流的学习
  • git 如何直接拉去远程仓库的内容且忽略本地与远端不一致的commit
  • 每日一算:分发糖果
  • 神经算子学习
  • AI大模型入门1.1-python基础字符串代码
  • Tlias管理系统(多表查询-内连接外连接)
  • win11家庭版配置远程桌面
  • 8. LangChain4j + 提示词工程详细说明
  • ChatGPT大模型训练指南:如何借助动态代理IP提高训练效率
  • 利用git进行版本控制
  • 深入理解synchronized:从使用到原理的进阶指南
  • 第八章 矩阵按键实验
  • 【CSS 3D 实战】从零实现旋转立方体:理解 3D 空间的核心原理
  • C++互斥锁使用详解与案例分析
  • Python+DRVT 从外部调用 Revit:批量创建柱
  • Matlab机器人工具箱6.2 导入stl模型——用urdf文件描述
  • 网页设计模板 HTML源码网站模板下载
  • 南京大学计算机学院 智能软件工程导论 + Luciano Baresi 教授讲座
  • Rust/C/C++ 混合构建 - Buck2构建工具一探究竟
  • Drawnix:开源一体化白板工具,让你的创意无限流动!
  • stm32 链接脚本没有 .gcc_except_table 段也能支持 C++ 异常
  • K8S集群管理(4)
  • flutter TabBar 设置isScrollable 第一个有间距
  • 学习 Android (二十一) 学习 OpenCV (六)
  • Maven项目中修改公共依赖项目并发布到nexus供三方引用全流程示例