Ответ 1
Существует несколько способов поиска текста в изображении.
Я рекомендую посмотреть этот вопрос здесь, так как он также может ответить на ваш вопрос. Хотя это не в python, код можно легко перевести с С++ на python (просто посмотрите на API и конвертируйте методы из С++ в 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)
Типичный способ поиска текстовых областей: вы можете найти текстовые области, используя преобразование ширины штриха, как показано в "Обнаружение текста в естественных сценах с преобразованием ширины штриха" Бориса Эпштейна, Эяля Офэка и Йонатана Векслера. Если честно, если это так же быстро и надежно, как я считаю, то этот метод является более эффективным методом, чем мой код ниже. Вы все равно можете использовать приведенный выше код, чтобы удалить проект чертежа, и это может помочь общей производительности алгоритма swt.
Вот c-библиотека, которая реализует их алгоритм, но, как утверждается, она очень сырая, и документация заявлена как неполная. Очевидно, для использования этой библиотеки с python потребуется оболочка, и на данный момент я не вижу официального предложения.
Связанная мной библиотека CCV. Это библиотека, предназначенная для использования в ваших приложениях, а не для воссоздания алгоритмов. Таким образом, это инструмент, который нужно использовать, что противоречит стремлению 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 уже существует средство обнаружения текста сцены (не распознавание текста документа). Я понимаю, что у вас нет возможности переключать версии, но для тех, у кого есть тот же вопрос и не ограничиваясь более старой версией, я решил включить это в конце. Документацию для обнаружения текста сцены можно найти с помощью простого поиска в Google.
Модуль opencv для обнаружения текста также поставляется с распознаванием текста, который реализует tessaract, который является бесплатным модулем распознавания текста с открытым исходным кодом. Падение tessaract и, следовательно, модуль распознавания текста сцены opencv заключается в том, что он не так утончен, как коммерческие приложения и требует много времени. Таким образом, снижение его производительности, но его бесплатное использование, поэтому его лучшее, что мы получили, не заплатив деньги, если вы хотите также распознавать текст.
Ссылки:
Честно говоря, мне не хватает опыта и опыта как в opencv, так и в обработке изображений, чтобы предоставить подробный способ реализации их модуля обнаружения текста. То же самое с алгоритмом SWT. В последние несколько месяцев я попал в этот материал, но, узнав больше, я отредактирую этот ответ.