Обнаружение текстовой области в изображении с использованием python и opencv

Я хочу обнаружить текстовую область изображений с использованием python 2.7 и opencv 2.4.9 и нарисовать вокруг нее прямоугольную область. Как показано на рисунке ниже.

Я новичок в обработке изображений, поэтому любая идея, как это сделать, будет оценена по достоинству.

план здания с маркированными комнатами

python,opencv,image-processing,ocr,

18

Ответов: 1


Существует несколько способов поиска текста в изображении.

Я рекомендую посмотреть этот вопрос здесь , так как он также может ответить на ваш вопрос. Хотя это не в 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)

Типичный способ поиска текстовых областей: вы можете найти текстовые области, используя преобразование ширины штриха, как показано в «Обнаружении текста в естественных сценах с преобразованием ширины штриха » Бориса Эпштейна, Эяля Офэка и Йонатана Векслера. Если честно, если это так же быстро и надежно, как я считаю, то этот метод является более эффективным методом, чем мой код ниже. Вы все равно можете использовать приведенный выше код, чтобы удалить проект чертежа, и это может помочь общей производительности алгоритма swt.

Вот библиотека ac, которая реализует их алгоритм, но, как утверждается, она очень грубая, и документация заявлена ??как неполная. Очевидно, для использования этой библиотеки с 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 уже существует средство обнаружения текста сцены (не распознавание текста документа). Я понимаю, что у вас нет возможности переключать версии, но для тех, у кого одинаковый вопрос и не ограничен к более старой версии opencv, я решил включить это в конце. Документацию для обнаружения текста сцены можно найти с помощью простого поиска в Google.

Модуль opencv для обнаружения текста также имеет распознавание текста, которое реализует tessaract, который является бесплатным модулем распознавания текста с открытым исходным кодом. Падение tessaract и, следовательно, модуль распознавания текста сцены opencv заключается в том, что он не так утончен, как коммерческие приложения и требует много времени. Таким образом, снижение его производительности, но его бесплатное использование, поэтому его лучшее, что мы получили, не заплатив деньги, если вы хотите также распознавать текст.

Ссылки:

Честно говоря, мне не хватает опыта и опыта как в opencv, так и в обработке изображений, чтобы предоставить подробный способ реализации их модуля обнаружения текста. То же самое с алгоритмом SWT. В последние несколько месяцев я попал в этот материал, но, узнав больше, я отредактирую этот ответ.

Python, OpenCV, обработки изображений, OCR,
Похожие вопросы