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识别常用数字英文字母。这些技术是计算机视觉领域中不可或缺的一部分,也是深度学习应用的重要组成部分。