Обнаружение областей пузырьков диалога комиксов в изображениях
У меня есть изображение в градациях серого страницы комиксов, в котором есть несколько диалоговых пузырьков (= речевые балуны и т.д.), которые заключены в области с белым фоном и сплошными черными границами, которые содержат текст внутри, то есть что-то вроде этого:
![Пример изображения комикса]()
Я хочу обнаружить эти области и создать маску (двоичный код в порядке), который будет охватывать все внутренние области диалогов, т.е. что-то вроде:
![Образец результата маскирования]()
То же изображение, наложенный на маску, будет полностью понятным:
![Пример изображения с прозрачным наложением маски]()
Итак, моя основная идея алгоритма была примерно такой:
- Определите, где находится текст - запустите по крайней мере один пиксель в каждом пузыре. Немного развейте эти районы и примените порог, чтобы получить лучшую начальную почву; Я сделал эту часть:
![Текстовые позиции, очерченные]()
-
Используйте заливку заливки или некоторый вид обхода графика, начиная с каждого белого пикселя, который был обнаружен как пиксельный внутри пузыря на шаге 1, но работает над исходным изображением, заливая белые пиксели (которые должны быть внутри пузырь) и остановка на темных пикселях (которые должны быть границей или текстом).
-
Используйте некоторую операцию binary_closing для удаления темных областей (т.е. областей, соответствующих тексту) внутри пузырьков). Эта часть работает нормально.
Пока что шаги 1 и 3 работают, но я боюсь с шага 2. В настоящее время я работаю с scikit-image, и я не вижу никаких готовых алгоритмов, таких как заливка заливок. Очевидно, что я могу использовать что-то тривиальное, как обход ширины, в основном как предлагается здесь, но на самом деле это очень медленно, когда это делается на Python. Я подозреваю, что сложная морфология вроде binary_erosion или generate_binary_structure in ndimage или scikit-image, но я изо всех сил пытаюсь понять всю эту морфологическую терминологию и в основном как реализовать такую пользовательскую заливку заливки (т.е. начиная с изображения с шага 1, работая над исходным изображением и производя вывод для отдельного выходного изображения).
Я открыт для любых предложений, в том числе в OpenCV и т.д.
Ответы
Ответ 1
Несмотря на то, что ваш фактический вопрос касается этапа 2 вашего конвейера обработки, я хотел бы предложить другой подход, который может быть, imho, проще, и, как вы заявили, что вы открыты для предложений.
-
Используя изображение с исходного шага 1, вы можете создать изображение без текста в пузырьках.
Реализована
-
Обнаружение ребер на исходном изображении с удаленным текстом. Это должно хорошо работать для речевых пузырьков, так как края пузырьков довольно отчетливы.
Обнаружение кромок
-
Наконец, используйте краевое изображение и первоначально обнаруженные "текстовые местоположения", чтобы найти те области в краевом изображении, которые содержат текст.
Водораздел-сегментация
Прошу прощения за этот общий ответ, но здесь слишком поздно для фактического кодирования для меня, но если вопрос все еще открыт, и вам нужно/нужно еще несколько советов относительно моего предложения, я подробно рассмотрю его. Но вы можете определенно взглянуть на сегментирование по регионам в документах scikit-image.
Ответ 2
В то время как ваша общая задача направлена дальше, ваш фактический вопрос касается вашего шага 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/info/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)