图像中漫画对话气泡区域的检测

2024-04-19 19:16:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一张连环漫画的灰度图像,上面有几个对话气泡(=语音信号灯等),它们是白色背景的封闭区域,黑色边框内包含文本,例如:

Sample comic strip image

我想检测这些区域并创建一个遮罩(二进制可以),它将覆盖对话气泡的所有内部区域,例如:

Sample resulting mask image

相同的图像,蒙版覆盖,完全清晰:

Sample image with transparent mask overlay

所以,我对算法的基本想法是:

  1. 检测文本的位置-在每个气泡中至少植入一个像素。稍微扩大这些区域并应用阈值以获得更好的起点;我已经完成了这一部分:

Text positions outlined

  1. 使用泛洪填充或某种类型的图形遍历,从步骤1中检测到的气泡内像素的每个白色像素开始,但处理初始图像,泛洪白色像素(应该在气泡内部)并停止在深色像素(应该是边框或文本)上。

  2. 使用某种binary_closing操作删除气泡内的暗区域(即对应于文本的区域)。这部分工作正常。

到目前为止,第一步和第三步是可行的,但是我在第二步中挣扎。我目前正在使用scikit-image,我没有看到任何现成的算法,如洪水填充在那里实现。显然,我可以使用一些琐碎的东西,比如广度优先遍历,基本上是as suggested here,但用Python完成时,速度非常慢。我怀疑ndimage或scikit image中的binary_erosion或{a9}等复杂的形态学内容,但我很难理解所有这些形态学术语,基本上我如何实现这样一个定制的泛洪填充(即从步骤1图像开始,处理原始图像并生成输出以分离输出图像)。在

我愿意接受任何建议,包括OpenCV中的建议等等


Tags: 图像image文本算法区域步骤像素scikit
2条回答

尽管您的实际问题是关于处理管道的第2步,但我想建议另一种方法,可能是,imho,更简单,正如您所说,您愿意接受建议。在

  1. 使用原始步骤1中的图像,您可以创建一个气泡中没有文本的图像。在

    实施

  2. 检测原始图像上已删除文本的边缘。这对于语音气泡应该很有效,因为气泡的边缘非常明显。在

    边缘检测

  3. 最后使用边缘图像和最初检测到的“文本位置”来查找边缘图像中包含文本的区域。在

    Watershed-Segmentation

对于这个非常笼统的答案,我很抱歉,但是对于我来说,现在进行实际编码已经太晚了,但是如果问题仍然悬而未决,并且您需要/想要更多关于我的建议的提示,我将更详细地阐述它。但是,您肯定可以看看scikit图像文档中的Region based segmentation。在

虽然您的总体任务目标更进一步,但您的实际问题是关于步骤2,如何在检测到气泡中文本的数据集上实现洪水填充算法。在

由于您没有给出源代码,所以我不得不从头开始创建一些东西,希望它与步骤1中的输出很好地接口。对于这个,我只取了2个固定的坐标,你可以在靠近blob中心的地方取一些白点,这些白点是从步骤1中提取的文本创建的。只要您提供适当的代码,就可以调整该接口。在

我冒昧地填补了所有你发现的字母造成的内部漏洞,如果你不想这样,你可以跳过第36行的代码。在

对于解决方案,我实际上从下面截图中引用的两段代码中获取了一些想法。你可以在那里找到更多有用的信息。在

让我们知道你的进展!在

import cv2
import numpy as np

# with ideas from:
# http://www.learnopencv.com/filling-holes-in-an-image-using-opencv-python-c/
# http://stackoverflow.com/questions/10316057/filling-holes-inside-a-binary-object
print cv2.__file__

# Read image
im_in = cv2.imread("gIEXY.png", cv2.IMREAD_GRAYSCALE);

# Threshold.
# Set values equal to or above 200 to 0.
# Set values below 200 to 255.

th, im_th = cv2.threshold(im_in, 200, 255, cv2.THRESH_BINARY_INV);

# Copy the thresholded image.
im_floodfill = im_th.copy()

# Mask used to flood filling.
# Notice the size needs to be 2 pixels than the image.
h, w = im_th.shape[:2]
mask = np.zeros((h+2, w+2), np.uint8)

# Floodfill from points inside baloons
cv2.floodFill(im_floodfill, mask, (80,400), 128);
cv2.floodFill(im_floodfill, mask, (610,90), 128);

# Invert floodfilled image
im_floodfill_inv = cv2.bitwise_not(im_floodfill)

# Combine the two images to get the foreground
im_out = im_th | im_floodfill_inv

# Create binary image from segments with holes
th, im_th2 = cv2.threshold(im_out, 130, 255, cv2.THRESH_BINARY)

# Create contours to fill holes
im_th3 = cv2.bitwise_not(im_th2)
contour,hier = cv2.findContours(im_th3,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)

for cnt in contour:
    cv2.drawContours(im_th3,[cnt],0,255,-1)

segm = cv2.bitwise_not(im_th3)


# Display image
cv2.imshow("Original", im_in)
cv2.imshow("Segmented", segm)
cv2.waitKey(0)

相关问题 更多 >