使用 python 和 opencv 检测图像中的文本区域

2024-03-07

我想使用 python 2.7 和 opencv 2.4.9 检测图像的文本区域 并在其周围画一个矩形区域。就像下面的示例图片所示。

我对图像处理很陌生,所以任何想法如何做到这一点将不胜感激。


有多种方法可以检测图像中的文本。

我建议看看这个问题在这里 https://stackoverflow.com/questions/23506105/extracting-text-opencv,因为它也可以回答您的情况。虽然它不是用Python编写的,但代码可以很容易地从C++转换为Python(只需查看API并将方法从C++转换为Python,并不难。当我尝试他们的代码来解决我自己的单独问题时,我自己做到了) 。这里的解决方案可能不适用于您的情况,但我建议您尝试一下。

如果我要这样做,我会执行以下过程:

准备你的图像: 如果您要编辑的所有图像都大致类似于您提供的图像,其中实际设计由一系列灰色组成,并且文本始终为黑色。我首先会清除所有非黑色(或已经是白色)的内容。这样做只会留下黑色文本。

# must import if working with opencv in python
import numpy as np
import cv2

# removes pixels in image that are between the range of
# [lower_val,upper_val]
def remove_gray(img,lower_val,upper_val):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    lower_bound = np.array([0,0,lower_val])
    upper_bound = np.array([255,255,upper_val])
    mask = cv2.inRange(gray, lower_bound, upper_bound)
    return cv2.bitwise_and(gray, gray, mask = mask)

现在您拥有的只是黑色文本,目标是获得这些框。如前所述,有不同的方法可以解决这个问题。

笔划宽度变换 (SWT)

查找文本区域的典型方法:您可以使用描边宽度变换来查找文本区域,如下所示“通过笔划宽度变换检测自然场景中的文本” http://www.math.tau.ac.il/%7Eturkel/imagepapers/text_detection.pdf作者:鲍里斯·埃普斯坦 (Boris Epshtein)、埃亚尔·奥菲克 (Eyal Ofek) 和尤纳坦·韦克斯勒 (Yonatan Wexler)。老实说,如果这像我相信的那样快速可靠,那么这个方法是比我下面的代码更有效的方法。不过,您仍然可以使用上面的代码来删除蓝图设计,并且may有利于swt算法的整体性能。

这是一个c库 http://libccv.org/doc/doc-swt/实现了他们的算法,但据称它非常原始并且文档不完整。显然,为了在 python 中使用这个库,需要一个包装器,目前我没有看到提供官方的包装器。

我链接的库是CCV http://libccv.org/。它是一个旨在在您的应用程序中使用的库,而不是重新创建算法。所以这是一个要使用的工具,这违背了OP从“第一原则”中制作它的愿望,如评论中所述。不过,如果您不想自己编写算法,那么了解它的存在还是很有用的。


自制非 SWT 方法

如果您有每个图像的元数据(例如在 xml 文件中),该数据说明每个图像中标记了多少个房间,那么您可以访问该 xml 文件,获取有关图像中有多少个标签的数据,然后存储该数据某个变量中的数字说,num_of_labels。现在获取您的图像并将其放入一个 while 循环中,该循环以您指定的设定速率进行腐蚀,在每个循环中查找图像中的外部轮廓,并在获得与您的外部轮廓相同数量的外部轮廓后停止循环。num_of_labels。然后只需找到每个轮廓的边界框即可完成。

# erodes image based on given kernel size (erosion = expands black areas)
def erode( img, kern_size = 3 ):
    retval, img = cv2.threshold(img, 254.0, 255.0, cv2.THRESH_BINARY) # threshold to deal with only black and white.
    kern = np.ones((kern_size,kern_size),np.uint8) # make a kernel for erosion based on given kernel size.
    eroded = cv2.erode(img, kern, 1) # erode your image to blobbify black areas
    y,x = eroded.shape # get shape of image to make a white boarder around image of 1px, to avoid problems with find contours.
    return cv2.rectangle(eroded, (0,0), (x,y), (255,255,255), 1)

# finds contours of eroded image
def prep( img, kern_size = 3 ):    
    img = erode( img, kern_size )
    retval, img = cv2.threshold(img, 200.0, 255.0, cv2.THRESH_BINARY_INV) #   invert colors for findContours
    return cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) # Find Contours of Image

# given img & number of desired blobs, returns contours of blobs.
def blobbify(img, num_of_labels, kern_size = 3, dilation_rate = 10):
    prep_img, contours, hierarchy = prep( img.copy(), kern_size ) # dilate img and check current contour count.
    while len(contours) > num_of_labels:
        kern_size += dilation_rate # add dilation_rate to kern_size to increase the blob. Remember kern_size must always be odd.
        previous = (prep_img, contours, hierarchy)
        processed_img, contours, hierarchy = prep( img.copy(), kern_size ) # dilate img and check current contour count, again.
    if len(contours) < num_of_labels:
        return (processed_img, contours, hierarchy)
    else:
        return previous

# finds bounding boxes of all contours
def bounding_box(contours):
    bBox = []
    for curve in contours:
        box = cv2.boundingRect(curve)
    bBox.append(box)
    return bBox

上述方法生成的框将在标签周围有空间,如果将框应用于原始图像,这可能包括原始设计的一部分。为了避免这种情况,通过新找到的框创建感兴趣的区域并修剪空白区域。然后将该 roi 的形状保存为新盒子。

也许您无法知道图像中有多少个标签。如果是这种情况,那么我建议尝试使用侵蚀值,直到找到最适合您的情况并获得所需的斑点。

或者,您可以尝试在删除设计后在剩余内容上找到轮廓,并根据边界框彼此之间的距离将边界框组合成一个矩形。

找到盒子后,只需根据原始图像使用这些盒子即可完成。


OpenCV 3 中的场景文本检测模块

正如对您的问题的评论中提到的,opencv 3中已经存在一种场景文本检测(不是文档文本检测)的方法。我知道您无法切换版本,但对于那些有相同问题且不受限制的人对于较旧的 opencv 版本,我决定将其包含在最后。通过简单的谷歌搜索即可找到场景文本检测的文档。

用于文本检测的opencv模块还附带了实现tessaract的文本识别,tessaract是一个免费的开源文本识别模块。 tessaract 以及 opencv 的场景文本识别模块的衰落在于它不如商业应用那么精致,并且使用起来很耗时。因此降低了它的性能,但它是免费使用的,所以如果你也想要文本识别,它是我们无需付费就能得到的最好的。

Links:

  • OpenCv 文档 http://docs.opencv.org/3.1.0/d4/d61/group__text.html#gsc.tab=0
  • 较旧的文档 http://docs.opencv.org/3.0-beta/modules/text/doc/erfilter.html
  • 源码位于此处,方便分析和理解 https://github.com/opencv/opencv_contrib/tree/master/modules/text

老实说,我缺乏 opencv 和图像处理方面的经验和专业知识,无法提供实现其文本检测模块的详细方法。与SWT算法相同。过去几个月我刚刚开始研究这个东西,但随着我了解更多,我将编辑这个答案。

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

使用 python 和 opencv 检测图像中的文本区域 的相关文章

随机推荐

  • Python将整列添加到csv文件中,而不读取文件内容

    我需要使用 Python 将列添加到 csv 文件 我能想到的唯一方法是读取整个文件 编辑每一行以添加 1 个元素 然后再次写入文件 然而 我真的不想这样做 因为文件的大小 超过 32000 行 每次我想添加列时似乎需要大量的读写 即使使用
  • 如何从 fgets 中检测空字符串

    我试图将 stdin 中的 fgets 输入检测为空 当我按 Enter 键而不输入任何内容时 这是我的程序 int main char input 1000 printf Enter fgets input 1000 stdin inpu
  • 如何使用 box2d 在 libgdx 中拖动对象?

    我已将对象添加到box2d世界在libgdx 我想知道是否可以用鼠标拖动对象 如果是这样 怎么办 thanks 这里有几个选项 您可以使用鼠标关节 也可以使用运动体并手动设置其位置 看看如何使用鼠标关节的一个很好的例子 http code
  • 图像作为绘制形状的“背景”

    是否可以使用图像而不是颜色来 填充 HTML5 画布上的形状 我画了一堆形状 各个角以 45 度角切掉的正方形 我希望能够用图像而不是颜色来 填充 这些形状 目前我有一行指出 context fillStyle 123456 example
  • 如何使用 Meteor.js、Twitter 和 Oauth 发布推文

    我在使用 Meteor 和 Twitter 时遇到了一些问题 我想做的就是通过点击按钮发布一条推文 为此 我必须通过 Oauth 向 Twitter 服务验证自己的身份 目前 我正在以一种非常复杂的方式进行身份验证 从客户端到服务器并返回
  • 适用于 Android 的本机 OpenCV 示例抛出 UnsatisfiedLinkError

    我尝试在模拟器上运行 opencv android 示例 带有本机代码的示例 例如示例 教程 2 高级 1 添加本机 OpenCV 失败 我有一个Win7 x86系统 我可以构建本机库 但如果运行示例 我总是会遇到以下异常 10 04 08
  • 每个线程组的概率

    如果我的测试计划中有 3 个线程组 如何为每个组设置恒定概率 请求权重 我是 JMeter 的新手 您能在屏幕截图上显示您的设置吗 只需将每组的线程数设置为测试总线程数的一个因子即可 如果有 100 个 VU 则 g1 设置为 50 g2
  • 我如何使用 iOS 中的 Fabric 框架从我的应用程序中注销 Twitter

    在我的 iOS 应用程序中 我使用集成 Twitter 登录织物框架 TWTR作曲家 第一次登录并在 Twitter 上发布推文时 它工作正常 但我无法在我的应用程序中从 Twitter 注销 当我第二次尝试登录时 twitterlogin
  • LINQ 和递归

    考虑以下 public class Box public BoxSize Size get set public IEnumerable
  • 无法在 django 模板中使用 unicode 字符串

    我在 django 模板中使用了 B M N TO N 字符串 它引发了错误 utf8 编解码器无法解码位置 569 中的字节 0xd4 无效的连续字节 但是当我使用 BO MON TOAN 字符串时 它不会引发错误 所以 我在模板中使用了
  • 红宝石:能被4整除

    这工作正常 但我想让它更漂亮 并容纳所有能被 4 整除的值 if i 4 i 8 i 12 i 16 i 20 i 24 i 28 i 32 end 有什么聪明 简短的方法可以做到这一点吗 尝试这个 if i 4 0 这被称为 模运算符 h
  • 对于 C++ 插件系统来说什么是安全的?

    C 中的插件系统很困难 因为 ABI 没有正确定义 并且每个编译器 或其版本 都遵循自己的规则 然而 Windows 上的 COM 表明创建一个最小的插件系统是可能的 该系统允许具有不同编译器的程序员使用简单的接口为主机应用程序创建插件 让
  • 使用声明的可变基类无法在 MSVC 中编译

    我正在尝试实现一个可变访问者类 template
  • 如何以Python方式将 scipy.optimize.OptimizeResult 结果对象保存到文件中以便以后轻松访问?

    从 scipy optimize OptimizeResult 保存结果对象的最佳方法是什么 以便可以从保存的文件轻松访问其参数 我目前正在将结果保存为字符串 但这样 当我需要再次引用它时 我需要解析整个字符串来识别参数数组或函数值等对象
  • 我可以欺骗 libc (GLIBC_2.13) 加载它没有的符号(来自 GLIBC_2.15)吗?

    在我尝试让 Steam for Linux 在 Debian 上运行时 我遇到了一个问题 libcef Chromium 嵌入式框架 可以很好地工作GLIBC 2 13 Debian 测试中的eglibc 可以提供 但是需要一个讨厌的额外功
  • NVIDIA GPU 的 CUDA 核心和 OpenCL 计算单元之间有什么关系?

    我的电脑有一块 GeForce GTX 960M NVIDIA 声称它有 640 个 CUDA 核心 然而 当我运行 clGetDeviceInfo 来查找计算机中的计算单元数量时 它打印出 5 见下图 听起来 CUDA 核心与 OpenC
  • Facebook Messenger 如何与 Wit.ai Bot Engine 连接?

    在 Facebook 的文档中 他们提到了 wit ai Bot Engine 但我在网上找不到任何地方解释如何将您在 Wit 中构建的故事与 Facebook Messenger 应用程序连接起来 Wit ai 需要一个输入 用户输入 句
  • SVG旋转变换矩阵

    我从 SVG 文件中的元素解析了一个转换属性 例如rotate 45 30 50 我想将其转换为矩阵形式 我搜索了它 我所能找到的只是rotate a 没有坐标 看起来像这样 cos a sin a sin a cos a 0 0 谁能告诉
  • C# Linq 合并两个字典[重复]

    这个问题在这里已经有答案了 如何使以下方法更具函数式 linq 风格 public static Dictionary
  • 使用 python 和 opencv 检测图像中的文本区域

    我想使用 python 2 7 和 opencv 2 4 9 检测图像的文本区域 并在其周围画一个矩形区域 就像下面的示例图片所示 我对图像处理很陌生 所以任何想法如何做到这一点将不胜感激 有多种方法可以检测图像中的文本 我建议看看这个问题