使用Python,OpenCV+OCR检测护照图像中的机器可读区域(MRZ Machine-Readable Zones)

  • 1. 效果图
  • 2. 原理
  • 3. 源码
  • 参考

这篇博客将介绍如何只使用基本的图像处理技术(例如阈值处理,形态运算和轮廓属性)来检测护照图像中的机器可读区域(MRZ Machine-Readable Zones)。

1. 效果图

原始图,来自pyimageblog示例图像~,图中个人信息非真实

灰度图 VS 阈值化图像1 应用矩形内核减少了字母间间距:

阈值化图像2:应用正方形内核+腐蚀,减少了各行间隙,腐蚀去除了无关的小斑点

阈值化图像3 去掉了MRZ区域俩边的斑点
结果图及MRZ区域:

2. 原理

护照或旅行卡中的机读区分为两类:1类和3类。1类机读区分为三行,每行包含30个字符。3类机读区只有两行,但每行包含44个字符。在任何一种情况下,机读区都对给定公民的身份信息进行编码,包括护照的类型,护照ID,签发国家,姓名,国籍,有效期等。

机读区是在图片的顶部还是底部都没有关系。通过应用形态学运算,提取轮廓并计算轮廓属性,能够准确地提取MRZ。

该方法适用于包含三行的Type 1机读区,仅包含两行的Type 3机读区同样适用。

这篇博客将介绍如何仅使用基本图像处理技术来检测护照扫描中的机器可读区域(MRZ),即:

  • Thresholding 阈值化
  • Gradients 梯度
  • Morphological operations (specifically, closings and erosions).形态学操作(特别是闭合、侵蚀)
  • Contour properties轮廓属性

这些操作虽然简单,却能够检测图像中的MRZ区域,而不必依靠更高级的特征提取和机器学习方法(例如Linear SVM + HOG)来进行对象检测。

3. 源码

# 检测护照图像上的 MRZ Machine Readable Zones
# USAGE
# python detect_mrz.py --images images/origin.jpg# 导入必要的类
import numpy as np
import argparse
import imutils
import cv2# 构建命令行参数及解析
# --images 护照图像目录
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--images", required=True, help="path to images directory")
args = vars(ap.parse_args())# 初始化矩形和正方形结构内核
# 稍后将在应用形态学操作时使用它们,特别是关闭操作。
# 暂时,只需注意第一个内核是矩形,其宽度大约比高度大3倍。
# 第二个内核是正方形。这些内核将能够缩小MRZ字符之间的间隙和MRZ行之间的开口。
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (13, 5))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 21))# 加载图像,缩放高度未600px,转换为灰度图
image = cv2.imread(args['images'])
image = imutils.resize(image, height=600)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("origin", image)
cv2.waitKey(0)# 使用3*3高斯核平滑图像以减少高频噪声,然后应用blackhat形态运算符可在浅色背景上找到黑暗区域
# blackhat操作用于在浅色背景(即护照本身的背景)下显示深色区域(即MRZ文本)。由于护照文本在浅色背景上始终是黑色的
gray = cv2.GaussianBlur(gray, (3, 3), 0)
blackhat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, rectKernel)# MRZ检测的下一步是使用Scharr运算符计算blackhat图像的梯度幅度表示,并缩放结果在[0,255]范围内
# 沿着blackhat图像的x轴计算Scharr梯度,揭示出图像的区域不仅在浅色背景下变暗,而且还包含梯度的垂直变化,例如MRZ文本区域。
# 然后使用最小/最大缩放比例拍摄此渐变图像并将其缩放回[0,255]范围
# 计算blackhat图像的梯度可以提高MRZ检测的准确性,应用此操作对于减少误报机读区非常有帮助。没有它可能会意外地将护照上装饰或设计的区域标记为MRZ
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")# 使用矩形核执行关闭操作以关闭字母之间的间距-然后应用Otsu's thresholding阈值方法
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv2.imshow("gray VS thresh1", np.hstack([gray, thresh]))
cv2.imwrite("gray.jpg", gray)
cv2.imwrite("thresh1.jpg", thresh)
cv2.waitKey(0)# 下一步是缩小实际线条之间的间隙, 以提供一个与机读区相对应的大矩形区域
# 使用正方形内核执行另一个关闭操作以缩小MRZ各个行之间的间隙,从而提供一个对应于MRZ的大区域。
# 然后执行一系列腐蚀,以断开可能在关闭操作时已连接的连接组件,腐蚀也有助于去除与机读区无关的小斑点。
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)
thresh = cv2.erode(thresh, None, iterations=4)
cv2.imshow("thresh2", thresh)
cv2.imwrite("thresh2.jpg", thresh)
cv2.waitKey(0)# 对于某些护照扫描, 在阈值化过程中, 护照的边框可能已附着到MRZ区域。为了解决这个问题,将图片的左右边框的5%设置为零(即黑色)
p = int(image.shape[1] * 0.05)
thresh[:, 0:p] = 0
thresh[:, image.shape[1] - p:] = 0
cv2.imshow("thresh3", thresh)
cv2.imwrite("thresh3.jpg", thresh)
cv2.waitKey(0)# 最后一步是在阈值图像中找到轮廓,并使用轮廓属性来识别机读区
# 在阈值图像种寻找轮廓,并根据其面积倒序排列
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)# 遍历所有轮廓
for c in cnts:# 计算轮廓的边界框, 并使用它来计算两个属性:纵横比和覆盖率。长宽比就是边界框的宽度除以高度。覆盖率是边界框的宽度除以实际图像的宽度。(x, y, w, h) = cv2.boundingRect(c)ar = w / float(h)crWidth = w / float(gray.shape[1])# 检查机读区的正确性,机读区为矩形宽度远大于高度。机读区应至少覆盖输入图像的75%。# 检查长宽比率和覆盖度是否在可接受的标准if ar > 5 and crWidth > 0.75:# 填充边界框,因为应用了腐蚀,现在需要重新生长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))# 从图像中提取ROI区域,并绘制边界框在MRZ上roi = image[y:y + h, x:x + w].copy()cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)break# 展示输出图像
cv2.imshow("Result", image)
cv2.imshow("ROI", roi)
cv2.waitKey(0)

参考

  • https://www.pyimagesearch.com/2015/11/30/detecting-machine-readable-zones-in-passport-images/

使用Python,OpenCV+OCR检测护照图像中的机器可读区域(MRZ Machine-Readable Zones)相关推荐

  1. python图片目标检测_图像中的目标检测(HOG)

    我想探测显微镜图像细胞内的物体.我有很多带注释的图片(app.有对象的图像为50000,没有对象的图像为500000).在 到目前为止,我尝试使用HOG提取特征,并使用logistic回归和Linea ...

  2. 使用 OpenCV 和 Tesseract 对图像中的感兴趣区域 (ROI) 进行 OCR

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 在这篇文章中,我们将使用 OpenCV 在图像的选定区域上应用 O ...

  3. OpenCV在相机或图像中检测QR码的实例(附完整代码)

    OpenCV在相机或图像中检测QR码的实例 OpenCV在相机或图像中检测QR码的实例 OpenCV在相机或图像中检测QR码的实例 #include "opencv2/objdetect.h ...

  4. 教你如何用Python检测出图像中的黄色?都在这里!

    首先,这里不搞黄色,只搞学习,希望大家好好学习,争取早日变成大佬,升职加薪.当上总经理.出任CEO.迎娶白富美.走上人生巅峰,想想是不是有点小激动. 等等,别跑偏了,接下来开始学习. 有时我们需要检测 ...

  5. Python OpenCv 车牌检测识别(边缘检测、HSV色彩空间判断)

    Python OpenCv 车牌检测识别 背景 车牌识别在交通.停车等方面有着广泛应用,在网上也有很多种基于OpenCV方案进行识别,本文是综合了两种比较流行的方案,首先是提取出疑似车牌区域的轮廓,然 ...

  6. 要点初见:Python+OpenCV校正并提取表格中的各个框

    最近做了个手写汉字简历识别比赛,需要先提取表格中含有指定信息的各个框,再用TensorFlow对框中的信息进行汉字.数字.英文识别.代码已开源:https://github.com/BingLiHan ...

  7. OpenCV使用dnn从图像中解析人体部位的实例(附完整代码)

    OpenCV使用dnn从图像中解析人体部位的实例 OpenCV使用dnn从图像中解析人体部位的实例 OpenCV使用dnn从图像中解析人体部位的实例 #include <opencv2/dnn. ...

  8. opencv 从原始的图像中找出ROI区域

    http://blog.csdn.net/chentravelling/article/details/45331225 opencv 从原始的图像中找出ROI区域 #include <iost ...

  9. 平行坐标系下采用CHT方法检测自然图像中的消失点(VanishingPoint)

    --------------------20210826更新-------------------- code和paper链接:https://pan.baidu.com/s/13RyRu0rg7Fh ...

最新文章

  1. 填个小坑,Vue不支持IE8及以下,跨域ajax不支持IE9
  2. 1滴血,2小时,验13种癌症,精度99%!日本东芝新技术引热议
  3. 在quartus 和 ISE 里直接调用modelsim的方法(转)
  4. 【JavaScript基础】js中关于声明提前的几个误区
  5. Pandas之:深入理解Pandas的数据结构
  6. linux xguest用户,在/etc/passwd中得到普通用户列表
  7. 联想开机启动项按哪个_联想电脑开机按f12后,怎么设置默认启动项
  8. Gentoo Linux 学习笔记1
  9. 偏向锁java_Java偏向锁
  10. python安装pygame教程_Pygame安装教程
  11. PS(Photoshop)去水印的4个方法
  12. 手游内存辅助开发教程
  13. 对微信小程序的一些用法的感悟和总结
  14. 豆知识( DNS; HTTP入门;网络协议)
  15. Ubuntu下载常用软件和使用Caffe时的常见问题
  16. 5455. 最多 K 次交换相邻数位后得到的最小整数
  17. TCP/IP第四章笔记ARP协议
  18. Windows变慢原因分析及解决方法
  19. SAP中物料单位更改处理案例
  20. Azure虚拟机挂载数据磁盘

热门文章

  1. 摄像头和相机模型和内参原理
  2. 2021年大数据Flink(二十六):​​​​​​​State代码示例
  3. 微信小程序下拉刷新和上拉加载
  4. 前端之css引入方式/长度及颜色单位/常用样式
  5. 洛谷P1550 [USACO08OCT]打井Watering Hole
  6. Go 学习笔记(6)— 变量定义、变量声明、变量作用域
  7. java NIO详解
  8. SharePreference工具类
  9. 设有一数据库,包括四个表:学生表(Student)、课程表(Course)、成绩表(Score)以及教师信息表(Teacher)。...
  10. JavaScript对象掺杂点原型