Сегментация букв в изображении Captcha

Я написал этот алгоритм на Python для чтения CAPTCHA с использованием scikit-image:

from skimage.color import rgb2gray
from skimage import io

def process(self, image):
    """
    Processes a CAPTCHA by removing noise

    Args:
        image (str): The file path of the image to process
    """

    input = io.imread(image)
    histogram = {}

    for x in range(input.shape[0]):
        for y in range(input.shape[1]):
            pixel = input[x, y]
            hex = '%02x%02x%02x' % (pixel[0], pixel[1], pixel[2])

            if hex in histogram:
                histogram[hex] += 1
            else:
                histogram[hex] = 1

    histogram = sorted(histogram, key = histogram.get, reverse=True)
    threshold = len(histogram) * 0.015

    for x in range(input.shape[0]):
        for y in range(input.shape[1]):
            pixel = input[x, y]
            hex = '%02x%02x%02x' % (pixel[0], pixel[1], pixel[2])
            index = histogram.index(hex)

            if index < 3 or index > threshold:
                input[x, y] = [255, 255, 255, 255]

    input = rgb2gray(~input)
    io.imsave(image, input)

До:

До

После:

После

Он работает довольно хорошо, и я получаю неплохие результаты после проверки его с помощью Google Tesseract OCR, но я хочу сделать его лучше. Я думаю, что выпрямление букв даст гораздо лучший результат. Мой вопрос, как мне это сделать?

Я понимаю, что мне нужно как-то упаковать буквы, вот так:

В штучной упаковке

Затем для каждого символа поверните его на некоторое количество градусов в зависимости от вертикальной или горизонтальной линии.

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

Какие общие приемы используются при сегментации изображений для достижения такого результата?

Изменить:

В конце концов, дальнейшее уточнение цветовых фильтров и ограничение Tesseract только символами дало почти 100% точный результат без какого-либо исправления перекосов.


person bkvaluemeal    schedule 23.10.2015    source источник
comment
Я голосую за то, чтобы закрыть этот вопрос как не относящийся к теме, потому что он больше подходит для computergraphics.stackexchange.com или dsp.stackexchange.com   -  person wallyk    schedule 23.10.2015
comment
Хм.. Подмечено. Можем ли мы вместо этого переместить его туда?   -  person bkvaluemeal    schedule 23.10.2015


Ответы (1)


Операция, которую вы хотите выполнить, технически известна в компьютерном зрении как выравнивание объектов, для этого вам нужно применить геометрическое преобразование к объектам, у меня есть фрагмент кода для применения выравнивания объектов (двоичный). вот код (использует библиотеку opencv):

def deskew(image, width):
    (h, w) = image.shape[:2]
    moments = cv2.moments(image)
    skew = moments["mu11"] / moments["mu02"]
    M = np.float32([[1, skew, -0.5 * w * skew],[0, 1, 0]])
    image = cv2.warpAffine(image, M, (w, h), flags = cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR) 
    return image
person Ankit Dixit    schedule 23.10.2015
comment
OpenCV кажется намного более полезным, чем любой другой модуль для этого приложения, но они пока не поддерживают Python 3. Спасибо тебе за это. Мне все еще нужен метод для поиска областей для устранения перекосов. - person bkvaluemeal; 23.10.2015
comment
Что такое момент изображения? - person bkvaluemeal; 23.10.2015
comment
поддержка open cv 3 появилась для python 3, проверьте их веб-сайт для получения дополнительной информации, вам не нужно находить определенные области для устранения перекоса, вам просто нужно отправить каждый ограничивающий прямоугольник в виде изображения на вход метода, и если буква выровнена в любой ориентации он автоматически находит правильный коэффициент выравнивания, если буква правильно выровнена, она не изменит свою геометрию. Во-вторых, момент изображения - это определенное средневзвешенное значение (момент) интенсивности пикселей изображения или индексов пикселей или функция таких моментов, обычно выбираемая для того, чтобы иметь какое-то привлекательное свойство или интерпретацию. - person Ankit Dixit; 23.10.2015
comment
skimage.moments.regionprops подарит вам моменты. Исправить перекос можно с помощью skimage.transform, используя ту же идею, которую Анкит упоминает выше. - person Stefan van der Walt; 23.10.2015
comment
У меня есть регионы для устранения перекоса, предоставленные функцией regionprops. Я смог нарисовать прямоугольники вокруг них, как я описал выше, используя draw.line. Я вижу, что есть transform.AffineTransform. Предполагая, что это то преобразование, которое я хочу, как мне соединить эти два вместе? - person bkvaluemeal; 23.10.2015
comment
Я не понимаю, что такое mu11 и mu02 и как их деление дает перекос (вектор?). Я думаю, что M — это то же самое, что карта координат в skimage, но я не знаю, как это вывести. - person bkvaluemeal; 23.10.2015