Python+Opencv身份证号码区域提取及识别实现

1. Opencv初识

Opencv是开源计算机视觉库,可以实现图像处理、计算机视觉和机器学习等功能。Python是Opencv支持的语言之一,因为它具有易用性和灵活性。我们可以使用Python和Opencv对图像进行处理和分析。在这篇文章中,我们将使用Python和Opencv提取身份证号码并进行十分类别的识别。

2. 身份证号码区域提取

2.1 读取图片

使用Opencv读取图片非常简单,只需引入库并调用cv2.imread()函数读取图片即可。该函数中需要传入的参数为图片路径,并返回图像的numpy数组。

import cv2

# 读取图片

img = cv2.imread('id_card.jpg')

上述代码中,我们使用cv2.imread()函数读取一张身份证图片,并将其放入img变量中。

2.2 灰度化处理

为了提取身份证号码区域,我们首先需要进行灰度化处理,将彩色图像转成灰度图像。这是因为在灰度图像中,身份证号码的二值化处理更为方便。

# 灰度化处理

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

上述代码中,我们使用cv2.cvtColor()函数将img图像转换为灰度图像,并将其放入gray变量中。

2.3 图像模糊处理

由于身份证照片存在一些噪点和细节,进行图像模糊可以去除这些干扰。常用的模糊处理方法有高斯模糊和中值模糊。

# 高斯模糊

blur = cv2.GaussianBlur(gray, (5, 5), 0)

# 中值模糊

blur = cv2.medianBlur(gray, 5)

上述代码中,我们用cv2.GaussianBlur()和cv2.medianBlur()函数分别对灰度图像进行高斯模糊和中值模糊处理,模糊均值为5。最后将结果存放在blur变量中。

2.4 图像二值化处理

图像二值化可以将图像转化为黑白图像,这是在身份证号码区域提取中必须进行的处理。通常情况下,我们可以使用cv2.threshold()函数来进行二值化处理。

# 二值化处理

ret, threshold = cv2.threshold(blur, 170, 255, cv2.THRESH_BINARY)

上述代码中,我们使用cv2.threshold()函数将blur模糊后的图像进行二值化处理,阈值设置为170。函数返回的ret变量表示选定的阈值,threshold变量为二值化后的图像。

2.5 查找轮廓

提取身份证号码区域需要先找到证件区域的轮廓。使用cv2.findContours()函数可以找到图像中的轮廓。函数返回的是轮廓的点的集合,每个轮廓是一个Numpy数组,点的序号表示轮廓中的像素点位置。

# 查找轮廓

contours, hierarchy = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

在上述代码中,我们使用cv2.findContours()函数获取threshold阈值处理后的轮廓。该函数的第一个参数为二值图像,第二个参数cv2.RETR_TREE表示轮廓的检索方式,第三个参数cv2.CHAIN_APPROX_SIMPLE表示轮廓的近似方法。

2.6 确定身份证号码区域

找到轮廓后,需要从轮廓中找到身份证号码的位置。在实际操作中,可以根据以下特征推导:身份证号码周围一般有一个矩形框或多边形框,且身份证号码在图像的上方,并且宽度较窄,高度较大。因此,我们需要根据这些特征去判断找到的轮廓是否是身份证号码框。

# 确定身份证号码区域

ID_card_index = -1

ID_card_kps = []

for i, contour in enumerate(contours):

x, y, w, h = cv2.boundingRect(contour)

if 285 < h < 320 and 350 < w < 404 and y < 200:

ID_card_index = i

ID_card_kps.append([(x, y), (x + w, y), (x + w, y + h), (x, y + h)])

break

在上述代码中,我们遍历所有找到的轮廓,通过判断身份证号码的区域特征,确定身份证号码的轮廓。具体地,我们将身份证号码的框定在了宽度在350~404像素,高度在285~320像素的区域。并且这个框必须在轮廓顶部,即y<200。ID_card_index表示找到的身份证号码轮廓的索引。

3. 身份证号码识别

3.1 加载训练数据

在身份证号码识别之前,我们需要加载训练好的模型和数据。模型训练的过程不是本文要讨论的内容,因此我们直接加载已经训练好的数据即可。

# 加载训练好的数据和模型

with open('label_dict.pkl', 'rb') as f:

label_dict = pickle.load(f)

model = load_model('IDCard.h5')

上述代码中,我们使用pickle库加载训练好的标签和模型。其中,标签数据存储在label_dict.pkl文件中,模型保存在IDCard.h5文件中。

3.2 图像预处理

在进行文本识别前,需要将身份证号码进行一定的预处理。与身份证号码区域的提取类似,预处理需要将身份证号码进行二值化、去噪、分割等处理。

# 将身份证号码切割成单个数字

res = []

for kps in ID_card_kps:

warp_img = four_point_transform(img.copy(), np.array(kps))

gray = cv2.cvtColor(warp_img, cv2.COLOR_BGR2GRAY)

blur = cv2.GaussianBlur(gray, (3, 3), 0)

_, threshold = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

res.extend(segmentation(threshold, kps))

具体到本文实现当中,我们需要将提取到的身份证号码矩形区域,切割成独立的数字,并且对每个数字进行图像预处理。具体到预处理方案,包括:1)灰度化;2)高斯模糊;3)二值化;4)图像分割。上述代码中,我们使用four_point_transform函数对身份证号码进行透视变换。最后返回的res列表包括的是一串数字,每个数字都是一个图像numpy数组。

3.3 图像识别

得到预处理后的数字图像后,我们可以使用本次所加载的模型进行识别。具体代码如下:

# 进行识别

result = ""

for digit in res:

img = cv2.resize(digit, (28, 28)).reshape((1, 28, 28, 1)).astype('float32') / 255

label = np.argmax(model.predict(img))

result += label_dict[label]

print("识别的身份证号码为:", result)

在上述代码中,我们遍历预处理后得到的每个数字,使用cv2.resize()函数将数字大小调整为28x28像素,并通过reshape()函数调整其形状。最后经过模型的识别,返回的结果在label_dict中进行查询,最后得到的是身份证号码。

4. 总结

随着Opencv和Python的广泛应用,通过将两者结合使用可以实现图像处理、计算机视觉和机器学习等功能。在本文中,我们介绍了如何利用Python和Opencv提取身份证号码区域并进行识别。具体来说,我们向读者介绍了如何对图片进行预处理、轮廓查找和OCR识别常用数字英文字母。这些技术是计算机视觉领域中不可或缺的一部分,也是深度学习应用的重要组成部分。

后端开发标签