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

时间:2015-12-18 13:18:09

标签: python numpy scipy computer-vision scikit-image

我有一个漫画页面的灰度图像,其中包含几个对话气泡(=语音气球等),这些气泡是带有白色背景的封闭区域和内部包含文本的纯黑色边框,即类似的东西:

Sample comic strip image

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

Sample resulting mask image

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

Sample image with transparent mask overlay

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

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

    1. 使用泛光填充或某种图形遍历,从在步骤1中检测为像素内部气泡的每个白色像素开始,但是处理初始图像,淹没白色像素(应该在内部)气泡)并停在暗像素(应该是边框或文字)上。

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

    3. 到目前为止,第1步和第3步都有效,但我正在努力完成第2步。我目前正在使用scikit-image,我没有看到任何现成的算法,例如在那里实施了泛洪填充。显然,我可以使用像广度优先遍历这样的小事,基本上是as suggested here,但是在Python中完成时它确实很慢。我怀疑在ndimage或scikit-image中复杂的形态学东西如binary_erosiongenerate_binary_structure,但我很难理解所有形态学术语,基本上我如何用它来实现这样的自定义泛滥填充(即开始使用第1步图像,处理原始图像并生成输出以分离输出图像。)

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

2 个答案:

答案 0 :(得分:2)

即使你的实际问题与你的处理流程的第2步有关,我还是建议另一种方法,可能是,imho,更简单,并且正如你所说,你愿意接受建议。

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

    实施

  2. 使用删除的文本检测原始图像上的边缘。这应该适用于气泡,因为气泡边缘非常明显。

    边缘检测

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

    Watershed-Segmentation

  4. 我很抱歉这个非常一般的答案,但是这对我来说实际编码为时已晚,但如果问题仍然存在,你需要/想要更多关于我的建议的提示,我会详细说明。但你绝对可以看看scikit-image文档中的Region based segmentation

答案 1 :(得分:1)

虽然您的整体任务目标更进一步,但您的实际问题是关于您的第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)