1、什么是机器可读区域(MRZ)
护照或旅行卡中的machine-readable zone(MRZ)区域分为两类:类型 1和类型 3。1类机读区是三行,每行包含30个字符。3 类机读区只有两行,但每行包含44个字符。在任何一种情况下,机读区都会对给定公民的身份信息进行编码,包括护照类型、护照 ID、签发国、姓名、国籍、到期日期等。
为了检测护照的 MRZ 区域,您需要进行一些机器学习,也许使用Linear SVM + HOG框架来构建“MRZ 检测器”——但这有点过头了。相反,我们可以仅使用基本的图像处理技术(例如阈值处理、形态学操作和轮廓属性)来执行 MRZ 检测。
2、检测机器可读区域(MRZ)
开始尝试使用基础的数字图像处理技术进行自动检测护照图像中的机器可读区域(MRZ)。
让我们创建一个名为detect_mrz.py的文件。
# import the necessary packages
from imutils import paths
import numpy as np
import argparse
import imutils
import cv2
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--images", required=False, help="path to images directory", default="C:/Users/xiaomao/Desktop/1")
args = vars(ap.parse_args())
# initialize a rectangular and square structuring kernel
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (13, 5))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 21))
# loop over the input image paths
for imagePath in paths.list_images(args["images"]):
# 加载图像并改变大小,转灰度
image = cv2.imread(imagePath)
image = imutils.resize(image, height=600)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 使用 3x3 高斯平滑图像,然后应用 blackhat
# 在浅色背景上寻找暗区的形态算子
gray = cv2.GaussianBlur(gray, (3, 3), 0)
blackhat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, rectKernel)
# 计算黑帽图像的 Scharr 梯度并缩放
# result into the range [0, 255]
gradX = cv2.Sobel(blackhat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
gradX = np.absolute(gradX)
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255 * ((gradX - minVal) / (maxVal - minVal))).astype("uint8")
# 使用矩形核应用关闭操作来关闭
# gaps in between letters -- then apply Otsu's thresholding method
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
# 执行另一个关闭操作
# 一系列腐蚀以分离连接的组件
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)
thresh = cv2.erode(thresh, None, iterations=4)
# during thresholding, it's possible that border pixels were
# included in the thresholding, so let's set 5% of the left and
# right borders to zero
p = int(image.shape[1] * 0.05)
thresh[:, 0:p] = 0
thresh[:, image.shape[1] - p:] = 0
# find contours in the thresholded image and sort them by their
# size
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
# loop over the contours
for c in cnts:
# compute the bounding box of the contour and use the contour to
# compute the aspect ratio and coverage ratio of the bounding box
# width to the width of the image
(x, y, w, h) = cv2.boundingRect(c)
ar = w / float(h)
crWidth = w / float(gray.shape[1])
# check to see if the aspect ratio and coverage width are within
# acceptable criteria
if ar > 5 and crWidth > 0.43:
# pad the bounding box since we applied erosions and now need
# to re-grow it
pX = int((x + w) * 0.03)
pY = int((y + h) * 0.03)
(x, y) = (x - pX, y - pY)
(w, h) = (w + (pX * 2), h + (pY * 2))
# extract the ROI from the image and draw a bounding box
# surrounding the MRZ
roi = image[y:y + h, x:x + w].copy()
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
break
# show the output images
cv2.imshow("Image", image)
cv2.imshow("ROI", roi)
cv2.waitKey(0)
应用黑帽形态算子在浅色护照背景下显示黑色MRZ文本。
使用矩形内核(宽度大于高度)应用闭合操作来闭合 MRZ 字符之间的间隙
下面是一个示例护照以及识别结果。