Opencv:从许可证中裁剪文本区域

2024-01-20

我有一张驾驶执照的下图,我想提取有关驾驶执照、姓名、出生日期等的信息。我的思考过程是找到一种方法将它们逐行分组,并裁剪出包含姓名的单个矩形、 eng 和 ara 的许可证等。但我却惨遭失败。

import cv2
import os
import numpy as np

scan_dir = os.path.dirname(__file__)
image_dir = os.path.join(scan_dir, '../../images')


class Loader(object):
    def __init__(self, filename, gray=True):
        self.filename = filename
        self.gray = gray
        self.image = None

    def _read(self, filename):
        rgba = cv2.imread(os.path.join(image_dir, filename))

        if rgba is None:
            raise Exception("Image not found")

        if self.gray:
            gray = cv2.cvtColor(rgba, cv2.COLOR_BGR2GRAY)

        return gray, rgba


    def __call__(self):
        return self._read(self.filename)


class ImageScaler(object):

    def __call__(self, gray, rgba, scale_factor = 2):
        img_small_gray = cv2.resize(gray, None, fx=scale_factor, fy=scale_factor, interpolation=cv2.INTER_AREA)
        img_small_rgba = cv2.resize(rgba, None, fx=scale_factor, fy=scale_factor, interpolation=cv2.INTER_AREA)


        return img_small_gray, img_small_rgba



class BoxLocator(object):
    def __call__(self, gray, rgba):
        # image_blur = cv2.medianBlur(gray, 1)
        ret, image_binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        image_not = cv2.bitwise_not(image_binary)

        erode_kernel = np.ones((3, 1), np.uint8)
        image_erode = cv2.erode(image_not, erode_kernel, iterations = 5)

        dilate_kernel = np.ones((5,5), np.uint8)
        image_dilate = cv2.dilate(image_erode, dilate_kernel, iterations=5)


        kernel = np.ones((3, 3), np.uint8)
        image_closed = cv2.morphologyEx(image_dilate, cv2.MORPH_CLOSE, kernel)
        image_open = cv2.morphologyEx(image_closed, cv2.MORPH_OPEN, kernel)

        image_not = cv2.bitwise_not(image_open)
        image_not = cv2.adaptiveThreshold(image_not, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 15, -2)

        image_dilate = cv2.dilate(image_not, np.ones((2, 1)), iterations=1)
        image_dilate = cv2.dilate(image_dilate, np.ones((2, 10)), iterations=1)

        image, contours, heirarchy = cv2.findContours(image_dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        for contour in contours:
            x, y, w, h = cv2.boundingRect(contour)
            # if w > 30 and h > 10:
            cv2.rectangle(rgba, (x, y), (x + w, y + h), (0, 0, 255), 2)

        return image_dilate, rgba



def entry():
    loader = Loader('sample-004.jpg')
    # loader = Loader('sample-004.jpg')
    gray, rgba = loader()

    imageScaler = ImageScaler()
    image_scaled_gray, image_scaled_rgba = imageScaler(gray, rgba, 1)

    box_locator = BoxLocator()
    gray, rgba = box_locator(image_scaled_gray, image_scaled_rgba)

    cv2.namedWindow('Image', cv2.WINDOW_NORMAL)
    cv2.namedWindow('Image2', cv2.WINDOW_NORMAL)

    cv2.resizeWindow('Image', 600, 600)
    cv2.resizeWindow('Image2', 600, 600)

    cv2.imshow("Image2", rgba)
    cv2.imshow("Image", gray)

    cv2.moveWindow('Image', 0, 0)
    cv2.moveWindow('Image2', 600, 0)

    cv2.waitKey()
    cv2.destroyAllWindows()

当我运行上面的代码时,我得到下面的分段。这与我想要的不接近

But below is what I want to achieve, for all input licenseenter image description here


从我的头脑中,我可以想到两种方法:

方法1.正如评论中提到的,您可以裁剪鹰符号在左上角和flag在右上角,使用它们作为模板,并根据找到的模板的位置找到您感兴趣的两个框,左下(小框)和中心(大框)。首先,您可以使用以下命令:

模板1

模板2

Code:

import numpy as np
import cv2
import matplotlib.pyplot as plt

image = cv2.imread("ID_card.jpg")

template_1 = cv2.imread("template_1.jpg", 0)
w_1, h_1 = template_1.shape[::-1]

template_2 = cv2.imread("template_2.jpg", 0)
w_2, h_2 = template_2.shape[::-1]

res_1 = cv2.matchTemplate(image=image, templ=template_1, method=cv2.TM_CCOEFF)
min_val_1, max_val_1, min_loc_1, max_loc_1 = cv2.minMaxLoc(res_1)

res_2 = cv2.matchTemplate(image=image, templ=template_2, method=cv2.TM_CCOEFF)
min_val_2, max_val_2, min_loc_2, max_loc_2 = cv2.minMaxLoc(res_2)

cv2.rectangle(image, max_loc_1, (max_loc_1[0] + w_1, max_loc_1[1] + h_1), 255, 2)
cv2.rectangle(image, max_loc_2, (max_loc_2[0] + w_2, max_loc_2[1] + h_2), 255, 2)

Result:

您可以使用找到的模板的中心来获取所需框(小和大)的相对位置。

方法 2. 与基于轮廓所做的类似,基本思想是使用形态学在更大的框中获得明确的线条。

Code:

import numpy as np
import cv2
import matplotlib.pyplot as plt

image = cv2.imread("ID_card.jpg")
imgray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

ret, thresh = cv2.threshold(imgray, 150, 255, 0)
# cv2.imwrite("thresh.jpg", thresh)

# Morphological operation
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, 
cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7)))

im2, contours, heirarchy = cv2.findContours(thresh, cv2.RETR_TREE, 
cv2.CHAIN_APPROX_SIMPLE)

# Sort the contours based on area
cntsSorted = sorted(contours, key=lambda x: cv2.contourArea(x), reverse=True)

approxes = []

for cnt in cntsSorted[1:10]:
    peri = cv2.arcLength(cnt, True)
    # approximate the contour shape
    approx = cv2.approxPolyDP(cnt, 0.04 * peri, True)
    approxes.append(approx)
    if len(approx) == 4:
    # length of 4 means 4 vertices so it should be a quadrilateral
        cv2.drawContours(image, approx, -1, (0, 255, 0), 10)

cv2.imwrite("ID_card_contours.jpg", image)
print(approxes)

Results:

阈值图像

形态学开放后

最终图像,两个预期框的各自角标有绿色

因此,这种方法非常简单,我相信您可以完成剩下的工作,从大盒子中找到较小的子集。如果没有,请给我留言,我很乐意提供帮助(基本上从图像中裁剪该区域,使用霍夫林斯P https://docs.opencv.org/3.4.0/d9/db0/tutorial_hough_lines.html你应该没问题。或者,我可以看到较小的子集具有相同的宽度,因此您可以根据 y 坐标裁剪它们)

附言。希望“更大”、“更小”的盒子能被很好地理解,为我的懒惰而没有在图像中显示它们的内容表示歉意。

Note:仅给出一张图像,我无法确定它是否适用于数据集中的所有图像。你可能需要调整临界点 and 变形开放参数。如果您可以上传更多图片,我可以尝试一下。

礼貌:OpenCV 形状检测 https://www.pyimagesearch.com/2016/02/08/opencv-shape-detection/用于检测轮廓中的形状。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Opencv:从许可证中裁剪文本区域 的相关文章

  • 从数据框中按索引删除行

    我有一个数组wrong indexes train其中包含我想从数据框中删除的索引列表 0 63 151 469 1008 要删除这些索引 我正在尝试这样做 df train drop wrong indexes train 但是 代码失败
  • Python中Decimal类型的澄清

    每个人都知道 或者至少 每个程序员都应该知道 http docs oracle com cd E19957 01 806 3568 ncg goldberg html 即使用float类型可能会导致精度错误 然而 在某些情况下 精确的解决方
  • 使用 python 进行串行数据记录

    Intro 我需要编写一个小程序来实时读取串行数据并将其写入文本文件 我在读取数据方面取得了一些进展 但尚未成功地将这些信息存储在新文件中 这是我的代码 from future import print function import se
  • python future 和元组解包

    实现像使用 future 进行元组解包这样的事情的优雅 惯用的方法是什么 我有这样的代码 a b c f x y g a b z h y c 我想将其转换为使用期货 理想情况下我想写一些类似的东西 a b c ex submit f x y
  • python 模拟第三方模块

    我正在尝试测试一些处理推文的类 我使用 Sixohsix twitter 来处理 Twitter API 我有一个类充当 Twitter 类的外观 我的想法是模拟实际的 Sixohsix 类 通过随机生成新推文或从数据库检索它们来模拟推文的
  • 如何使用 imaplib 获取“消息 ID”

    我尝试获取一个在操作期间不会更改的唯一 ID 我觉得UID不好 所以我认为 Message ID 是正确的 但我不知道如何获取它 我只知道 imap fetch uid XXXX 有人有解决方案吗 来自 IMAP 文档本身 IMAP4消息号
  • Pandas 中允许重复列

    我将一个大的 CSV 包含股票财务数据 文件分割成更小的块 CSV 文件的格式不同 像 Excel 数据透视表之类的东西 第一列的前几行包含一些标题 公司名称 ID 等在以下列中重复 因为一家公司有多个属性 而不是一家公司只有一栏 在前几行
  • 如何计算numpy数组中元素的频率?

    我有一个 3 D numpy 数组 其中包含重复的元素 counterTraj shape 13530 1 1 例如 counterTraj 包含这样的元素 我只显示了几个元素 array 136 129 130 103 102 101 我
  • OpenCv读/写视频色差

    我试图简单地使用 openCV 打开视频 处理帧并将处理后的帧写入新的视频文件 我的问题是 即使我根本不处理帧 只是打开视频 使用 VideoCapture 读取帧并使用 VideoWriter 将它们写入新文件 输出文件看起来比输入更 绿
  • TensorFlow的./configure在哪里以及如何启用GPU支持?

    在我的 Ubuntu 上安装 TensorFlow 时 我想将 GPU 与 CUDA 结合使用 但我却停在了这一步官方教程 http www tensorflow org get started os setup md 这到底是哪里 con
  • Python urllib.request.urlopen:AttributeError:'bytes'对象没有属性'data'

    我正在使用 Python 3 并尝试连接到dstk 我收到错误urllib包裹 我对SO进行了很多研究 但找不到与这个问题类似的东西 api url self api base street2coordinates api body jso
  • 首先对列表中最长的项目进行排序

    我正在使用 lambda 来修改排序的行为 sorted list key lambda item item lower len item 对包含元素的列表进行排序A1 A2 A3 A B1 B2 B3 B 结果是A A1 A2 A3 B
  • Pandas 根据 diff 列形成簇

    我正在尝试使用 Pandas 根据表示时间 以秒为单位 的列中的差异来消除数据框中的一些接近重复项 例如 import pandas as pd numpy as np df pd DataFrame 1200 1201 1233 1555
  • 将 2D NumPy 数组按元素相乘并求和

    我想知道是否有一种更快的方法 专用 NumPy 函数来执行 2D NumPy 数组的元素乘法 然后对所有元素求和 我目前使用np sum np multiply A B 其中 A B 是相同维度的 NumPy 数组m x n 您可以使用np
  • 无法在 osx-arm64 上安装 Python 3.7

    我正在尝试使用 Conda 创建一个带有 Python 3 7 的新环境 例如 conda create n qnn python 3 7 我收到以下错误 Collecting package metadata current repoda
  • 使用yield 进行字典理解

    作为一个人为的例子 myset set a b c d mydict item yield join item s for item in myset and list mydict gives as cs bs ds a None b N
  • 使用 PyTorch 分布式 NCCL 连接失败

    我正在尝试使用 torch distributed 将 PyTorch 张量从一台机器发送到另一台机器 dist init process group 函数正常工作 但是 dist broadcast 函数中出现连接失败 这是我在节点 0
  • 迭代 my_dict.keys() 并修改字典中的值是否会使迭代器失效?

    我的例子是这样的 for my key in my dict keys my dict my key mutate 上述代码的行为是否已定义 假设my dict是一本字典并且mutate是一个改变其对象的方法 我担心的是 改变字典中的值可能
  • 无法在前端使用 JavaScript Fetch API 将文件上传到 FastAPI 后端

    我正在尝试弄清楚如何将图像发送到我的 API 并验证生成的token那是在header的请求 到目前为止 这就是我所处的位置 app post endreProfilbilde async def endreProfilbilde requ
  • 迭代 pandas 数据框的最快方法?

    如何运行数据框并仅返回满足特定条件的行 必须在之前的行和列上测试此条件 例如 1 2 3 4 1 1 1999 4 2 4 5 1 2 1999 5 2 3 3 1 3 1999 5 2 3 8 1 4 1999 6 4 2 6 1 5 1

随机推荐

  • 3 月 14 日不是 86400 秒长吗?

    在我的 Web 应用程序中 我让用户在简单的文本框中输入日期 该输入 当然是经过清理之后 通过 strtotime 运行 并向其中添加 86399 以使该时间戳成为所写入的当天的结束时间 11 59 59 这是出于截止日期的目的 因此 如果
  • 为什么 jQuery 模板 {{each}} 标签与 jQuery $.each 对 JavaScript 字符串数组的解释不同?

    强制性的jsFiddle 示例 http jsfiddle net patridge wuEyp 当我通过 jQuery 运行字符串数组时 each函数 我得到了我所期望的 each abc 123 def 456 function i v
  • 使用 RSpec 测试 searchkick

    我想创建用于在我的实践管理应用程序中搜索患者的功能规范 到目前为止 我已经在网上搜索并遵循了以下建议的解决方案 http bitsandbit es post 11295134047 unit testing with tire and e
  • 模板参数推导失败

    我正在尝试使用标签和enable if对模板参数实施约束 这是代码 include
  • iOS7 SKScene如何让精灵从屏幕边缘反弹?

    我正在开发一款球在 iPad 屏幕内弹跳的游戏 类似于乒乓球游戏 我看到 SKScene 的 SKPhysicsWorld 具有重力属性 并且还控制对象如何相互碰撞 有什么方法可以自动检测精灵的边缘是否与屏幕边缘发生碰撞 以便它可以反弹 或
  • WPF 应用程序转换为 ASP

    有没有办法把WPF应用程序变成ASP应用程序 或者它们是完全不相关的技术 XAML 格式让我想起了 HTML 似乎有一种方法 WPF 应用程序是 Windows 应用程序 而 ASP Net 应用程序是 Web 应用程序 这两个平台存在巨大
  • 无法使用 Namecheap 通过 Firebase 验证自定义域

    当我按照说明将 firebase 提供的文本记录 1 插入到我的 NameCheap 中后 不断弹出此错误消息 当前状态 抱歉 我们无法验证您的域名 该消息已经出现大约 5 天了 我捕获了 firebase 和 namecheap 设置的屏
  • H2数据库中auto_increment字段自增32?

    我有这个简单的表 仅供测试 create table table key int not null primary key auto increment name varchar 30 然后我执行以下请求 insert into table
  • 数据库恢复到特定状态以进行测试

    我们使用 Oracle 或 postgres 数据库和应用程序服务器来执行集成测试 为了将每个测试与另一个测试隔离 在每个测试之前都会删除并重新创建数据库模式 如您所见 这是一个耗时的过程 该应用程序使用 100 多个表 我们正在考虑编写自
  • C语言中的“静态”是什么意思?

    我见过这个词static在C代码中的不同地方使用 这是否像 C 中的静态函数 类 其中实现在对象之间共享 函数内的静态变量在调用之间保留其值 静态全局变量或函数仅在声明它的文件中 可见 如果你是新手 1 是一个比较陌生的话题 所以这里有一个
  • 为什么 document.addEventListener('load', function) 在 Greasemonkey 脚本中不起作用?

    它没有给出错误 我放了一个console log loaded userscript wifi autologin the console log有效 但 document addEventListener 的预期效果没有发生 在进行更多调
  • 如何使用 Visual Studio Code git Push 到不同的分支?

    我意识到在 VSCode 中提交后 有一个 推送 菜单选项可以将提交推送到默认分支 然而 我经常需要将它推送到不同的分支 有没有办法做到这一点或运行git push progress origin DEFAULT BRANCH OTHER
  • 如何找出哪个缺失的 DLL 导致我的 .NET 应用程序在启动时崩溃?

    当对第 3 方程序集的依赖项添加到典型的 NET 应用程序时 很容易忘记将它们添加到安装程序中 这个问题往往只有在应用程序安装后才会显现出来 并且以启动时崩溃的形式出现 几乎没有可用的有用信息 找出需要将哪些程序集添加到安装程序的最佳工具和
  • 头盔快递 ERR_BLOCKED_BY_RESPONSE.NotSameOrigin 200

    请我需要帮助 我检查了所有谷歌 但没有得到打开我的问题的真正答案 我想使用头盔来保护我的 Express 服务器 但是当我使用它时 我收到此错误 ERR BLOCKED BY RESPONSE NotSameOrigin 200 从数据库加
  • 使用 Matplotlib 创建 CSV 数据的实时绘图

    我正在尝试使用 Matplotlib 来可视化一些测量结果 测量通常持续约 24 小时 并将在 csv 中包含约 3 万行数据 我一直在努力让我的情节真正动画化 我可以执行代码 它将显示截至当前时间点的快照 但不会显示其他内容 当我尝试自动
  • 如何让 GridView 在添加项目时调整其高度

    我试图在 GridView 中显示一个带有复选框的动态增长的字符串列表 该复选框本身位于 TableLayout 中 我可以连续显示 复选框 字符串 当我让用户在 GridView 中动态添加新字符串时 就会出现问题 我创建了一个接收字符串
  • 如何使用 expo React Native 调整照片大小

    给定用户设备上照片的 uri 文件 和内容 我如何调整照片大小 我正在运行一个托管的博览会应用程序 因此理想情况下我们能够在不分离的情况下执行此操作 这可以通过世博会来完成图像操纵器 https docs expo io versions
  • GoogleMobileAds 的未定义符号问题

    我正在构建动态框架 在其中导入 GoogleMobileAds 框架 我没有将其链接为二进制 我只是将其导入到类代码中 同时将框架保留在项目路径上 而不在构建阶段的 链接二进制文件 中链接它 import GoogleMobileAds 我
  • Heroku 无法满足tensorflow==2.3.0 的要求

    我正在尝试将 Flask 应用程序部署到 Heroku 为了使应用程序能够正确使用 Keras Tensorflow 必须至少为 2 2 版本 所以我做了pipenv install tensorflow 就像我对所有依赖项所做的那样 它将
  • Opencv:从许可证中裁剪文本区域

    我有一张驾驶执照的下图 我想提取有关驾驶执照 姓名 出生日期等的信息 我的思考过程是找到一种方法将它们逐行分组 并裁剪出包含姓名的单个矩形 eng 和 ara 的许可证等 但我却惨遭失败 import cv2 import os impor