Рубрики
Без рубрики

Как использовать предварительную обработку изображений для повышения точности Tesseract

Автор оригинала: FreeCodeCapm Team.

Berk Kaan Kuguoglu

Ранее, на Как начать с Tesseract Я дал вам практический урок быстрого начала на Tesseract с помощью Python. Это довольно простой обзор, но оно должно помочь вам начать с Tesseract и очистить несколько препятствий, которые я столкнулся с тем, когда я был в твоих обуви. Теперь я увлекаюсь показывать вам еще несколько трюков и вещей, которые вы можете сделать с Tesseract и OpenCV, чтобы улучшить вашу общую точность.

Где мы уехали в прошлый раз?

В предыдущая история Я не беспокоился о деталях по большей части. Но если вам понравилась первая история, вот продолжение! Так куда мы уходили?

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

Рекантралирование

Изображения, которые повторно, сжатые, либо увеличены. Если вы заинтересованы в сокращении вашего изображения, Inter_area это способ пойти на тебя. (Кстати, параметры FX и FY обозначить коэффициент масштабирования в функции ниже.)

img = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)

С другой стороны, как и в большинстве случаев, вам может понадобиться масштабировать свое изображение в большем размере, чтобы распознать небольшие символы. В этом случае Inter_cubic Как правило, выполняет лучше, чем другие альтернативы, хотя он также медленнее, чем другие.

img = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)

Если вы хотите обзорить некоторые из ваших качеств изображения для более быстрой производительности, вы можете попробовать Inter_linear Для увеличения изображений.

img = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)

Размытие

Стоит отметить, что в Make Blur Filters, доступных в Библиотека Opencv Отказ Размытие изображения обычно достигается путем сгрупп изображения с ядром фильтра низкого прохода. В то время как фильтры обычно используются для размытия изображения или уменьшения шума, существует несколько различий между ними.

1. усреднение

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

img = cv.blur(img,(5,5))

2. Гауссово размытие

Это работает аналогично усреднению, но он использует гауссовое ядро вместо нормированного фильтра коробки для свертывания. Здесь размеры ядра и стандартных отклонений в обоих направлениях могут быть определены независимо. Гауссовское размытие очень полезно для удаления – угадайте, что? – Гауссовский шум от изображения. Наоборот, Гаусский размытие не сохраняет края на входе.

img = cv2.GaussianBlur(img, (5, 5), 0)

3. Среднее размытие

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

Среднее размытие – нелинейный фильтр. В отличие от линейных фильтров, медиана размытия заменяет значения пикселей с средним значением, доступным в целях соседства. Таким образом, срединные размытия сохраняют края, поскольку средняя ценность должна быть ценностью одного из соседних пикселей.

img = cv2.medianBlur(img, 3)

4. Двусторонняя фильтрация

Говоря о том, чтобы держать края острые, двусторонняя фильтрация довольно полезна для удаления шума без сглаживания краев. Подобно гауссовому размыванию, двусторонняя фильтрация также использует гауссовый фильтр, чтобы найти средневзвешенное средневзвешенное в окрестностях гаусса. Однако он также принимает разницу в пикселе во время размытия близлежащих пикселей.

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

img = cv.bilateralFilter(img,9,75,75)

В целом, если вы заинтересованы в сохранении краев, перейдите со средней размытой или двусторонней фильтрацией. Напротив, гауссовое размытие, вероятно, будет быстрее, чем медианы размытия. Благодаря своей вычислительной сложности двусторонняя фильтрация является самым медленным из всех методов.

Опять же, ты делаешь тебя.

Пороговое значение изображения

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

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

1. Простой порог

Вы можете вспомнить своего друга, который дает вам несколько советов о своей жизни, говоря: «Все не всегда черные и белые». Ну, для простого порога, все довольно прямые.

cv.threshold(img,127,255,cv.THRESH_BINARY)

Во-первых, вы выбираете пороговое значение, скажем 127. Если значение пикселя больше порогового значения, он становится черным. Если меньше, это становится белым. OPENCV предоставляет нам различные типы методов пороговых средств, которые могут быть переданы в качестве четвертого параметра. Я часто использую двоичный порог для большинства задач, но для других методов пороговых средств вы можете посетить официальная документация.

2. Адаптивный порог

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

cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2)

Существует два адаптивных метода для расчета порогового значения. В то время как Adaptive Thresh означает Возвращает среднее значение окрестности, Adaptive Gaussian означает рассчитывает взвешенную сумму ценностей соседства.

У нас есть еще два параметра, которые определяют размер зоны соседства и постоянное значение, которое вычтено из результата: пятый и шестой параметры соответственно.

3. порог Оцу

Этот метод особенно хорошо работает с Бимодальные изображения , который является изображением, гистограмма которого имеет два пика. Если это так, мы можем быть увлеченным при выборе порогового значения между этими пиками. Это то, что на самом деле делает бинализацию Оцу на самом деле.

cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

Это довольно полезно для некоторых случаев. Но это может не в бинаризировать изображения, которые не являются бимодальными. Итак, пожалуйста, возьмите этот фильтр с зерном соли.

Типы порогов

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

Что дальше?

До сих пор мы обсудили некоторые из методик обработки изображений. Вы можете задаться вопросом, когда именно вы собираетесь грязные руки. Ну, время пришло. Прежде чем вернуться к своему любимому Python IDE – мой это Пычарм , кстати – я собираюсь показать вам несколько строк кода, который сэкономит вам некоторое время, пытаясь найти, какая комбинация фильтров и манипуляций изображений хорошо работает с вашими документами.

Давайте начнем с определения функции коммутатора, которая содержит несколько комбинаций фильтров пороговых средств и методов размытия. Как только вы получите идею, вы также можете добавить больше фильтров, включающих другие методы предварительной обработки изображений, такие как отставка в ваш фильтр.

Здесь я создал 20 различных комбинаций методов пороговых средств изображения, методы размытия и размеров ядра. Функция коммутатора, apply_threshold , принимает два аргумента, а именно изображение OpenCV и целое число, которое обозначает фильтр. Точно так же, поскольку эта функция возвращает изображение OpenCV в результате, он может быть легко интегрирован в наше get_string Функция с предыдущего поста.

def apply_threshold(img, argument):    switcher = {        1: cv2.threshold(cv2.GaussianBlur(img, (9, 9), 0), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1],        2: cv2.threshold(cv2.GaussianBlur(img, (7, 7), 0), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1],        3: cv2.threshold(cv2.GaussianBlur(img, (5, 5), 0), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1],
                              ...              
        18: cv2.adaptiveThreshold(cv2.medianBlur(img, 7), 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2),        19: cv2.adaptiveThreshold(cv2.medianBlur(img, 5), 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2),        20: cv2.adaptiveThreshold(cv2.medianBlur(img, 3), 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2)    }    return switcher.get(argument, "Invalid method")

И вот это приходит.

def get_string(img_path, method):    # Read image using opencv    img = cv2.imread(img_path)    # Extract the file name without the file extension    file_name = os.path.basename(img_path).split('.')[0]    file_name = file_name.split()[0]    # Create a directory for outputs    output_path = os.path.join(output_dir, file_name)    if not os.path.exists(output_path):        os.makedirs(output_path)
    # Rescale the image, if needed.    img = cv2.resize(img, None, fx=1.5, fy=1.5, interpolation=cv2.INTER_CUBIC)
    # Convert to gray    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)    # Apply dilation and erosion to remove some noise    kernel = np.ones((1, 1), np.uint8)    img = cv2.dilate(img, kernel, iterations=1)    img = cv2.erode(img, kernel, iterations=1)
    # Apply threshold to get image with only black and white    img = apply_threshold(img, method)
    # Save the filtered image in the output directory    save_path = os.path.join(output_path, file_name + "_filter_" + str(method) + ".jpg")    cv2.imwrite(save_path, img)    # Recognize text with tesseract for python    result = pytesseract.image_to_string(img, lang="eng")
    return result

Последние слова

Теперь все, что нам нужно сделать, это написать простоту для цикла, который итерации по поводу входного каталога для сбора изображений и применяет каждый фильтр на собранных изображениях. Я предпочитаю использовать шаблон или ОС , для сбора изображений из каталогов, и argparse Для прохождения аргументов через терминал, как и любой другой здравый человек.

Здесь я сделал почти то же самое, что и в моем Гист , если вы хотели бы посмотреть на это. Однако не стесняйтесь использовать инструменты, с которыми вы чувствуете себя комфортно.

До сих пор я пытался охватить несколько полезных концепций и реализаций для предварительной обработки изображений, хотя это, вероятно, только верхушка айсберга. Я не знаю, насколько «свободное время» я собираюсь иметь в предстоящих неделях, поэтому я не могу дать вам определенные временные рамки для публикации моего следующего поста. Тем не менее, я рассматриваю возможность добавления по крайней мере еще одну часть этой серии, которая объясняет несколько вещей, которые я оставил, например, вращение и перекос на изображениях.

До тех пор, BEST BEST – просто держать вас с вами и продолжать искать знаки. *