Обработка изображений и распознавание текста при парсинге в Python

Обработка изображений и распознавание текста — это огромное направление с множеством задач и последствий, начиная от самоуправляемых автомобилей Google и заканчивая торговыми автоматами, распознающими поддельные купюры. Эта глава фокусируется на одном небольшом аспекте этой области: распознавании текста — конкретно, как распознавать и использовать изображения с текстом, найденные в интернете с помощью различных библиотек Python.

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

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

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

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

Введение в библиотеки

Python — отличный язык для обработки изображений и чтения, машинного обучения на основе изображений, а также создания изображений. Хотя существует множество библиотек для обработки изображений, мы сосредоточимся на двух: Pillow и Tesseract.

Эти две библиотеки составляют мощный дуэт при обработке и выполнении оптического распознавания символов (OCR) на изображениях из интернета. Pillow выполняет первичную обработку, очищая и фильтруя изображения, а Tesseract пытается сопоставить формы, найденные на этих изображениях, с его библиотекой известных текстов.

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

Pillow

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

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

from PIL import Image, ImageFilter

kitten = Image.open('kitten.jpg')
blurryKitten = kitten.filter(ImageFilter.GaussianBlur)
blurryKitten.save('kitten_blurred.jpg')
blurryKitten.show()

В этом примере изображение kitten.jpg будет открыто в вашем просмотрщике изображений по умолчанию с добавленным размытием и также будет сохранено в размытом состоянии как kitten_blurred.jpg в той же директории.

Это слайд-шоу требует JavaScript.

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

Tesseract

Tesseract — это библиотека оптического распознавания символов (OCR). Спонсируемая Google (компанией, очевидно, хорошо известной своими технологиями OCR и машинного обучения), Tesseract широко признана лучшей и наиболее точной открытой системой OCR.

Помимо точности, она также крайне гибкая. Ее можно обучить распознавать любое количество шрифтов (пока эти шрифты относительно последовательны внутри себя, как вы увидите далее). Она также может быть расширена для распознавания любого символа Unicode.

В этой главе используются как командная строка Tesseract, так и ее сторонняя оболочка для Python, называемая pytesseract. Обе будут явно названы как одно из этих двух, поэтому знайте, что когда вы видите «Tesseract», я имею в виду программное обеспечение командной строки, а когда вы видите «pytesseract», я конкретно имею в виду его стороннюю оболочку для Python.

Установка Tesseract

Для пользователей Windows есть удобный исполняемый установщик. На момент написания этого текста текущая версия — 3.02, хотя более новые версии также подойдут.

Пользователи Linux могут установить Tesseract с помощью apt-get:

$ sudo apt-get tesseract-ocr

Установка Tesseract на Mac немного сложнее, хотя это можно сделать легко с помощью множества сторонних установщиков, таких как Homebrew, который использовался в статье про хранение данных для установки MySQL. Например, вы можете установить Homebrew и использовать его для установки Tesseract в две строки:

$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/ \
install/master/install)"
$ brew install tesseract

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

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

Вы можете сделать это в большинстве систем Linux и на macOS следующим образом:

$ export TESSDATA_PREFIX=/usr/local/share/

Обратите внимание, что /usr/local/share/ — это местоположение данных по умолчанию для Tesseract, хотя вы должны проверить, чтобы убедиться, что это так для вашей собственной установки.

Аналогично для Windows, вы можете использовать следующее для использования переменной среды:

# setx TESSDATA_PREFIX C:\Program Files\Tesseract OCR\

pytesseract

Pytesseract — это оболочка для Python, которая использует установленную версию Tesseract для чтения изображений и вывода строк и объектов, которые могут быть использованы в сценариях Python.

Образцы кода требуют версию 0.1.9 pytesseract Будьте в курсе того, что между версиями 0.1.8 и 0.1.9 pytesseract произошли значительные изменения (с участием автора). Этот раздел описывает функции, доступные только в версии 0.1.9 библиотеки. Убедитесь, что вы устанавливаете правильную версию при выполнении примеров кода в этой главе.

Как обычно, вы можете установить pytesseract с помощью pip или загрузить его с веб-страницы проекта pytesseract и выполнить:

$ python setup.py install

Pytesseract можно использовать совместно с PIL для чтения текста из изображений:

from PIL import Image
import pytesseract

print(pytesseract.image_to_string(Image.open('files/test.png')))

Если ваша библиотека Tesseract установлена в вашем пути Python, вы можете указать pytesseract местоположение, включив эту строку:

pytesseract.pytesseract.tesseract_cmd = '/path/to/tesseract'

Он также может возвращать полный вывод всех данных, таких как оценки уверенности, номера страниц и строк, данные о рамках, а также другую информацию:

print(pytesseract.image_to_data(Image.open('files/test.png')))

По умолчанию вывод для этих двух последних файлов представлен в виде строковых файлов с разделением пробелами или табуляцией, но вы также можете получить вывод в виде словарей или (если декодирование в UTF-8 недостаточно) байт-строк:

from PIL import Image
import pytesseract
from pytesseract import Output

print(pytesseract.image_to_data(Image.open('files/test.png'), output_type=Output.DICT))
print(pytesseract.image_to_string(Image.open('files/test.png'), output_type=Output.BYTES))

В этой статье используется комбинация библиотеки pytesseract, а также командной строки Tesseract, и запуск Tesseract из Python с использованием библиотеки subprocess. Хотя библиотека pytesseract полезна и удобна, есть некоторые функции Tesseract, которые она не может выполнить, поэтому полезно быть знакомым со всеми методами.

Распознавание русского текста

Для распознавания русского текста с использованием pytesseract вам нужно установить и сконфигурировать Tesseract для поддержки русского языка. Вот как это сделать:

  1. Установите Tesseract: Убедитесь, что у вас установлена библиотека Tesseract OCR. Вы можете использовать инструкции для вашей операционной системы, указанные в предыдущем сообщении.
  2. Настройте pytesseract: Укажите pytesseract путь к исполняемому файлу Tesseract. Если Tesseract установлен в стандартном местоположении, вам может не потребоваться это делать. В противном случае установите путь следующим образом:
    pytesseract.pytesseract.tesseract_cmd = '/path/to/tesseract'
    
  3. Используйте pytesseract для распознавания русского текста: После установки и настройки вы можете использовать pytesseract для чтения русского текста из изображений:
    from PIL import Image
    import pytesseract
    
    # Укажите путь к изображению с русским текстом
    image_path = 'path/to/your/image.png'
    
    # Прочтите текст с изображения
    text = pytesseract.image_to_string(Image.open(image_path), lang='rus')
    
    print(text)
    

NumPy

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

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

NumPy можно установить с помощью любого стороннего установщика Python, такого как pip, или, загрузив пакет, установить с помощью $ python setup.py install.

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

По соглашению, NumPy импортируется как np и может использоваться следующим образом:

import numpy as np
numbers = [100, 102, 98, 97, 103]
print(np.std(numbers))
print(np.mean(numbers))

Обработка хорошо форматированного текста

В надежде, что большая часть текста, который вам придется обрабатывать, будет относительно чистым и хорошо отформатированным. Хорошо отформатированный текст обычно соответствует нескольким требованиям, хотя граница между тем, что является «неряшливым» и что является «хорошо отформатированным», может быть субъективной.

В общем, хорошо отформатированный текст:

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

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

На рисунке показан идеальный пример хорошо отформатированного текста.

Хороший текст

Вы можете запустить Tesseract из командной строки, чтобы прочитать этот файл и записать результаты в текстовый файл:

$ tesseract text.tif textoutput | cat textoutput.txt

Результатом будет строка информации о библиотеке Tesseract для указания ее работы, за которой следует содержимое только что созданного текстового файла textoutput.txt:

Tesseract Open Source OCR Engine v3.02.02 with Leptonica
Это хороший текст. Здесь есть символы @#$%&

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

После размытия текста на изображении, создания артефактов сжатия JPG и добавления небольшого фонового градиента результаты становятся гораздо хуже.

Текст похуже

Tesseract не может обработать это изображение так хорошо, в основном из-за фонового градиента, и выводит следующий результат:

Eто текст похуже. Здесь естb символы _

Обратите внимание, что текст обрывается, как только фоновый градиент делает его сложнее различить, и последний символ в каждой строке неправильный, так как Tesseract безрезультатно пытается его распознать. Кроме того, артефакты JPG и размытие делают сложным различение между русской буквой ь и латинской b.

Это то место, где использование сценария на Python для очистки ваших изображений приходит на помощь. Используя библиотеку Pillow, вы можете создать фильтр порога, чтобы избавиться от серого фона, выделить текст и сделать изображение более четким для чтения Tesseract.

Кроме того, вместо использования Tesseract из командной строки, вы можете использовать библиотеку pytesseract для выполнения команд Tesseract и чтения результирующего файла:

from PIL import Image
import pytesseract

def cleanFile(filePath, newFilePath):
    image = Image.open(filePath)
    # Установите пороговое значение для изображения и сохраните
    image = image.point(lambda x: 0 if x < 143 else 255)
    image.save(newFilePath)
    return image

image = cleanFile('files/textBad.png', 'files/textCleaned.png')
# вызовите Tesseract для выполнения OCR на только что созданном изображении
print(pytesseract.image_to_string(image))

Результирующее изображение, автоматически созданное как textCleaned.png, показано на рисунке

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

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

Точки и запятые, будучи крайне маленькими, становятся первыми жертвами этой обработки изображения и практически исчезают как из нашего взгляда, так и из взгляда Tesseract. Также есть неприятное неверное толкование «Arial» как «Anal», результат того, что Tesseract интерпретирует буквы r и i как один символ n.

Тем не менее, это улучшение по сравнению с предыдущей версией, в которой почти половина текста была обрезана.

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

Изображения, которые определенно стоит исправить перед подачей на Tesseract, — это те, которые наклонены, имеют большие области без текста или имеют другие проблемы.

Улучшение изображения автоматически

В предыдущем примере значение 143 было выбрано экспериментально как «идеальный» порог, чтобы настроить все пиксели изображения на черный или белый цвет, чтобы Tesseract мог прочитать изображение. Но что, если у вас есть много изображений, все с немного разными проблемами градации серого цвета, и вы не в состоянии вручную настроить их все?

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

Какой именно алгоритм использовать может немного различаться от приложения к приложению, но это один пример итерации через пороги обработки изображений для поиска «лучшей» настройки:

import pytesseract
from pytesseract import Output
from PIL import Image
import numpy as np

def cleanFile(filePath, threshold):
    image = Image.open(filePath)
    # Установить пороговое значение для изображения, и сохранить
    image = image.point(lambda x: 0 if x < threshold else 255)
    return image

def getConfidence(image):
    data = pytesseract.image_to_data(image, output_type=Output.DICT)
    text = data['text']
    confidences = []
    numChars = []
    for i in range(len(text)):
        if data['conf'][i] > -1:
            confidences.append(data['conf'][i])
            numChars.append(len(text[i]))
    return np.average(confidences, weights=numChars), sum(numChars)

filePath = 'files/textBad.png'
start = 80
step = 5
end = 200

for threshold in range(start, end, step):
    image = cleanFile(filePath, threshold)
    scores = getConfidence(image)
    print("порог: " + str(threshold) + ", уверенность: " + str(scores[0]) + " numChars " + str(scores[1]))

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

Этот скрипт состоит из двух функций:

cleanFile

Принимает исходный «плохой» файл и переменную порога для запуска инструмента порога PIL. Он обрабатывает файл и возвращает объект изображения PIL.

getConfidence

Принимает очищенный объект изображения PIL и запускает его через Tesseract. Он вычисляет среднюю уверенность каждой распознанной строки (взвешенную по числу символов в этой строке), а также количество распознанных символов.

Изменяя значение порога и получая уверенность и количество распознанных символов при каждом значении, получается вывод:

порог: 80, уверенность: 61.8333333333 numChars 18 
порог: 85, уверенность: 64.9130434783 numChars 23 
порог: 90, уверенность: 62.2564102564 numChars 39 
порог: 95, уверенность: 64.5135135135 numChars 37 
порог: 100, уверенность: 60.7878787879 numChars 66 
порог: 105, уверенность: 61.9078947368 numChars 76 
порог: 110, уверенность: 64.6329113924 numChars 79 
порог: 115, уверенность: 69.7397260274 numChars 73 
порог: 120, уверенность: 72.9078947368 numChars 76 
порог: 125, уверенность: 73.582278481 numChars 79 
порог: 130, уверенность: 75.6708860759 numChars 79 
порог: 135, уверенность: 76.8292682927 numChars 82 
порог: 140, уверенность: 72.1686746988 numChars 83 
порог: 145, уверенность: 75.5662650602 numChars 83 
порог: 150, уверенность: 77.5443037975 numChars 79 
порог: 155, уверенность: 79.1066666667 numChars 75 
порог: 160, уверенность: 78.4666666667 numChars 75 
порог: 165, уверенность: 80.1428571429 numChars 70 
порог: 170, уверенность: 78.4285714286 numChars 70 
порог: 175, уверенность: 76.3731343284 numChars 67 
порог: 180, уверенность: 76.7575757576 numChars 66 
порог: 185, уверенность: 79.4920634921 numChars 63 
порог: 190, уверенность: 76.0793650794 numChars 63 
порог: 195, уверенность: 70.6153846154 numChars 65

Существует явный тренд как по средней уверенности в результате, так и по количеству распознанных символов. Оба показателя имеют пик вокруг порога 145, что близко к ручному найденному «идеальному» результату 143.

Пороги 140 и 145 дают максимальное количество распознанных символов (83), но порог 145 дает самую высокую уверенность для этих найденных символов, поэтому, вероятно, стоит выбрать этот результат и вернуть текст, который был распознан на этом пороге, как «лучшее предположение» о том, какой текст содержится на изображении.

Конечно, просто нахождение «большего» количества символов не обязательно означает, что все эти символы реальные. При некоторых порогах Tesseract может разбивать отдельные символы на несколько, или интерпретировать случайный шум на изображении как символ текста, который на самом деле не существует.

В этом случае вам, вероятно, придется больше полагаться на среднюю уверенность каждого результата. Например, если вы получили результаты, которые читаются (частично) следующим образом:

порог: 145, уверенность: 75.5662650602 numChars 83

порог: 150, уверенность: 97.1234567890 numChars 82

вероятно, будет логичным выбрать результат, который дает вам более 20% повышение уверенности при потере всего одного символа, и предположить, что результат с порогом 145 просто неправильный, или, возможно, разбил символ или обнаружил что-то, чего на самом деле нет.

Это то место, где некоторые начальные эксперименты по усовершенствованию вашего алгоритма выбора порога могут пригодиться. Например, вы можете выбрать оценку, для которой произведение уверенности и количества символов максимально (в этом случае 145 по-прежнему побеждает с произведением 6272, и в нашем воображаемом примере порог 150 побеждает с произведением 7964), или некий другой показатель.

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

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

Вместо того чтобы пытаться каждый порог от 80 до 200, вам, вероятно, реалистично будет попробовать только пороги от 130 до 180. Вы можете даже выбрать другой подход и выбирать пороги, которые, скажем, отличаются на 20 на первом этапе, а затем использовать жадный алгоритм для нахождения лучшего результата путем уменьшения шага для порогов между «лучшими» решениями, найденными на предыдущей итерации. Этот подход также может быть наиболее эффективным при работе с несколькими переменными.

Сбор текста с изображений на веб-сайтах

Использование Tesseract для чтения текста с изображения на вашем жестком диске может показаться не таким уж захватывающим, но это может быть мощным инструментом, когда он используется вместе с веб-скрейпером. Изображения могут ненамеренно затруднять чтение текста на веб-сайтах (как в случае с JPG-копией меню на сайте местного ресторана), но они также могут намеренно скрывать текст, как я покажу в следующем примере.

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

Следующий скрипт достигает этого именно этого: он переходит к крупногабаритному изданию 1 книги Толстого «Смерть Ивана Ильича», открывает чтение, собирает URL-адреса изображений, а затем систематически загружает, считывает и выводит текст из каждого изображения.

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

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

import time
from urllib.request import urlretrieve
from PIL import Image
import tesseract
from selenium import webdriver

def getImageText(imageUrl):
    urlretrieve(image, 'page.jpg')
    p = subprocess.Popen(['tesseract', 'page.jpg', 'page'], stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    p.wait()
    f = open('page.txt', 'r')
    print(f.read())

# Создание нового драйвера Selenium
driver = webdriver.Chrome(executable_path='<Путь к chromedriver>')
driver.get('https://www.amazon.com/Death-Ivan-Ilyich'\
'-Nikolayevich-Tolstoy/dp/1427027277')
time.sleep(2)

# Нажатие на кнопку предварительного просмотра книги
driver.find_element_by_id('imgBlkFront').click()
imageList = []

# Ожидание загрузки страницы
time.sleep(5)

while 'pointer' in driver.find_element_by_id('sitbReaderRightPageTurner').get_attribute('style'):
    # Пока правая стрелка доступна для нажатия, перелистывайте страницы
    driver.find_element_by_id('sitbReaderRightPageTurner').click()
    time.sleep(2)
    # Получение всех новых загруженных страниц (одновременно может загружаться несколько страниц,
    # но дубликаты не будут добавлены в множество)
    pages = driver.find_elements_by_xpath('//div[@class=\'pageImage\']/div/img')
    if not len(pages):
        print("No pages found")
    for page in pages:
        image = page.get_attribute('src')
        print('Found image: {}'.format(image))
        if image not in imageList:
            imageList.append(image)
            getImageText(image)

driver.quit()

Хотя этот скрипт, в теории, может быть запущен с любым типом веб-драйвера Selenium, я обнаружил, что в настоящее время он наиболее надежно работает с Chrome.

Как вы уже заметили из ранее прочитанного, этот скрипт печатает множество длинных отрывков из книги в основном читаемым образом, как видно в предварительном просмотре первой главы:

Глава I Во время перерыва в судебном процессе Мельвинского в большом здании судов участники и обвинитель встретились в частной комнате Ивана Егоровича Шебека, где разговор зашел о знаменитом деле Красовского. Федор Васильевич категорически утверждал, что это не подлежит их компетенции, а Иван Егорович настаивал на обратном, в то время как Петр Иванович, не вступив в дискуссию с самого начала, не принимал в ней участия, но просматривал только что принесенную газету. "Господа", - сказал он, - "Иван Ильич умер!"

Однако многие слова имеют явные ошибки, например, «Мельвинси» вместо имени «Мельвинский» и «дискуссион» вместо «дискуссия». Многие ошибки такого рода можно исправить, делая предположения на основе словарного списка (возможно, с дополнениями на основе соответствующих имен собственных, таких как «Мельвинский»).

Иногда ошибка может затронуть всё слово, как на странице 3 текста: он мертв, а не 1. В этом случае слово «я» заменено символом «1». Здесь анализ цепей Маркова может быть полезен, помимо словаря слов. Если какая-то часть текста содержит крайне необычное выражение («а не 1»), можно предположить, что текст на самом деле содержит более распространенное выражение («а не я»). Конечно, помогает то, что эти замены символов следуют предсказуемым шаблонам: «vi» становится «w», а «я» становится «1».

Если эти замены происходят часто в вашем тексте, можно создать список из них, который можно использовать для «попыток» новых слов и фраз, выбирая решение, которое имеет наибольший смысл. Один из подходов может заключаться в замене часто путаемых символов и использовании решения, которое совпадает с словом в словаре или является распознанным (или наиболее распространенным) n-граммой.

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

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

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

Чтение каптчи и тренировка tesseract

Хотя слово CAPTCHA знакомо многим, гораздо меньше людей знают, что это означает: полностью автоматизированный публичный тест Тьюринга для различения компьютеров и людей. Его громоздкий акроним намекает на его довольно громоздкую роль в препятствовании в противном случае вполне пригодным веб-интерфейсам, так как как люди, так и не люди, роботы часто борются с решением тестов CAPTCHA.

Тест Тьюринга был впервые описан Аланом Тьюрингом в его статье 1950 года «Вычислительная техника и интеллект». В статье он описал ситуацию, в которой человек мог бы общаться как с людьми, так и с программами искусственного интеллекта через компьютерный терминал. Если человек не мог отличить людей от программ искусственного интеллекта в ходе неформального разговора, программы искусственного интеллекта считались бы прошедшими тест Тьюринга, и искусственный интеллект, по мнению Тьюринга, на самом деле «думал» для всех целей и намерений.

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

Большинство других CAPTCHA немного проще. Например, Drupal, популярная система управления контентом на PHP, имеет популярный модуль CAPTCHA, который может генерировать изображения CAPTCHA разной сложности. Изображение по умолчанию выглядит как на рисунке.

CAPTCHA

Что делает эту CAPTCHA такой простой для чтения как для людей, так и для машин по сравнению с другими CAPTCHA?

  • Символы не перекрывают друг друга, и они не пересекаются горизонтально. То есть, вокруг каждого символа можно нарисовать аккуратный прямоугольник без перекрытия с другим символом.
  • Нет фоновых изображений, линий или другого мусора, который мог бы запутать программу OCR.
  • Изображения CAPTCHA используют мало вариаций шрифта. Они чередуются между чистым без засечек (как в символах «4» и «M») и рукописным шрифтом (как в символах «m», «C» и «3»).
  • Высокий контраст между белым фоном и темными символами.

Однако эта CAPTCHA подкидывает несколько курьезов, которые делают ее сложной для чтения программ OCR:

  • Используются и буквы, и цифры, увеличивая количество потенциальных символов.
  • Случайное наклонение букв может запутать программное обеспечение OCR, но остается легким для чтения людьми.
  • Относительно странный рукописный шрифт представляет особые трудности, с дополнительными линиями в «C» и «3» и необычно маленькой строчной буквой «m», требующей дополнительной тренировки для компьютеров, чтобы разобраться.

Когда вы запускаете Tesseract над этим изображением с помощью команды

$ tesseract captchaExample.png output

вы получаете этот файл output.txt: 4N,,,C<3 Он правильно определил 4, C и 3, но явно не сможет заполнить поле, защищенное CAPTCHA, в ближайшем будущем.

Обучение tesseract

Чтобы обучить Tesseract распознавать текст, будь то сложный и трудночитаемый шрифт или CAPTCHA, вам нужно предоставить ему несколько примеров каждого символа.

Это тот момент, когда вам, возможно, захочется подготовить хороший подкаст или фильм, потому что вас ждут пара часов довольно скучной работы. Первый шаг — загрузить несколько примеров вашей CAPTCHA в один каталог. Количество примеров будет зависеть от сложности CAPTCHA; я использовал 100 образцов (всего 500 символов, примерно 8 примеров на символ в среднем) для обучения моей CAPTCHA, и это кажется довольно хорошим результатом.

Я рекомендую называть изображения в соответствии с решением CAPTCHA (например, 4MmC3.jpg). Я нашел, что это помогает быстро проверять ошибки среди большого количества файлов; вы можете просматривать все файлы в виде миниатюр и сравнивать изображение с его именем файла легко. Это решение  очень помогает при проверке ошибок на следующих этапах.

Второй шаг — точно сообщить Tesseract, что каждый символ и где он находится на изображении. Это включает создание файлов box, по одному для каждого изображения CAPTCHA. Файл box выглядит следующим образом:

4 15 26 33 55 0

M 38 13 67 45 0

m 79 15 101 26 0

C 111 33 136 60 0

3 147 17 176 45 0

Первый символ — это представленный символ, следующие четыре числа представляют собой координаты прямоугольной рамки вокруг изображения, а последнее число — «номер страницы», используемое для обучения с многопоточными документами (0 для нас).

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

Загрузите изображение, нажмите кнопку «Add» внизу, если вам нужны дополнительные рамки, при необходимости отрегулируйте размер рамок, и скопируйте и вставьте текст вашего нового файла .box в новый файл.

Файлы box должны быть сохранены в формате обычного текста с расширением .box. Как и с изображениями, удобно называть файлы box в соответствии с решениями CAPTCHA, которые они представляют (например, 4MmC3.box). Снова это облегчает двойную проверку содержимого файла .box с именем файла, а затем снова с изображением, с которым он связан, если вы отсортируете все файлы в вашем каталоге данных по их именам файлов.

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

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

Существует полдюжины шагов для выполнения всего анализа данных и создания необходимых для Tesseract файлов обучения. Есть инструменты, которые делают это за вас на основе соответствующих исходных изображений и файлов .box, но на данный момент нет ничего для Tesseract 3.02, к сожалению.

Есть решение на Python, которое работает с файлом, содержащим как изображения, так и файлы box, и автоматически создает все необходимые файлы для обучения. Начальные настройки и шаги этой программы можно увидеть в методах __init__ и runAll класса:

def __init__(self):
    languageName = 'eng'
    fontName = 'captchaFont'
    directory = '<путь к изображениям>'

def runAll(self):
    self.createFontFile()
    self.cleanImages()
    self.renameFiles()
    self.extractUnicode()
    self.runShapeClustering()
    self.runMfTraining()
    self.runCnTraining()
    self.createTessData()

Единственные три переменные, которые вам нужно установить здесь, довольно просты:

  • languageName: Трехбуквенный код языка, который использует Tesseract, чтобы понять, с каким языком он имеет дело. В большинстве случаев вы, вероятно, захотите использовать eng для английского.
  • fontName: Название выбранного вами шрифта. Это может быть что угодно, но должно быть одним словом без пробелов.
  • directory: Каталог, содержащий все ваши изображения и файлы box. Я рекомендую использовать абсолютный путь, но если вы используете относительный путь, он должен быть относительным к тому месту, откуда вы запускаете код Python. Если это абсолютный путь, вы можете запустить код откуда угодно на вашем компьютере. Давайте посмотрим на отдельные функции, используемые здесь.
  • createFontFile создает обязательный файл font_properties, который позволяет Tesseract узнать о новом создаваемом вами шрифте.
  • cleanImages создает версии изображений с более высоким контрастом для всех найденных файлов изображений, преобразует их в оттенки серого и выполняет другие операции, которые упрощают чтение файлов изображений программами OCR.
  • renameFiles переименовывает все ваши файлы .box и соответствующие им файлы изображений с именами, требуемыми Tesseract.
  • extractUnicode анализирует все созданные файлы .box и определяет общий набор символов, доступных для обучения. Полученный файл Unicode сообщит вам, сколько различных символов вы обнаружили, и может быть хорошим способом быстро проверить, не упустили ли что-то.

Следующие три функции, runShapeClustering, runMfTraining и runCnTraining, создают файлы shapetable, pfftable и normproto соответственно. Они все предоставляют информацию о геометрии и форме каждого символа, а также предоставляют статистическую информацию, которую Tesseract использует для расчета вероятности того, что данный символ является тем или иным.

Наконец, Tesseract переименовывает каждую из скомпилированных папок данных, чтобы они начинались с требуемого имени языка (например, shapetable переименовывается в eng.shapetable), и компилирует все эти файлы в окончательный файл данных для обучения eng.traineddata. Единственный шаг, который вам нужно выполнить вручную, — переместить созданный файл eng.traineddata в вашу корневую папку tessdata с помощью следующих команд в Linux и Mac:

$cp /path/to/data/eng.traineddata $TESSDATA_PREFIX/tessdata

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

$ tesseract captchaExample.png output|cat output.txt
4MmC3

Успех! Существенное улучшение по сравнению с предыдущим толкованием изображения как 4N,,,C<3. Это всего лишь краткий обзор полной мощи функций обучения и распознавания шрифтов Tesseract. Если вы заинтересованы в том, чтобы обучить Tesseract более подробно, возможно, начать собственную библиотеку файлов обучения CAPTCHA или поделиться новыми возможностями распознавания шрифтов с миром, я рекомендую ознакомиться с документацией.

Решения по получению, разгадыванию и отправки решения Captcha

Многие популярные системы управления контентом часто становятся объектом спама со стороны ботов, которые заранее программируются с известным местоположением страниц регистрации пользователей.

Например, даже CAPTCHA (хотя и слабая) на сайте http://pythonscraping.com мало что меняет в потоке регистраций. Как же это делают эти боты? Мы успешно разгадали CAPTCHA в изображениях на нашем жестком диске, но как создать полностью функционирующего бота?

В этом разделе объединяются многие техники, рассмотренные в предыдущих статьях. Если вы еще этого не сделали, рекомендуется хотя бы пробежаться по статье про краулинг форм. У большинства CAPTCHA, основанных на изображениях, есть несколько свойств:

  • Они динамически создаются на сервере с помощью программы на сервере. У них могут быть источники изображений, которые не выглядят как традиционные изображения, например, <img src="WebForm.aspx?id=8AP85CQKE9TJ">, но их можно загрузить и обрабатывать как любое другое изображение.
  • Решение для изображения хранится в базе данных на сервере.
  • Многие CAPTCHA завершаются по тайм-ауту, если вы занимаетесь их разгадыванием слишком долго. Это обычно не проблема для ботов, но постановка решений CAPTCHA в очередь для последующего использования или другие практики, которые могут задержать момент между запросом CAPTCHA и отправкой решения, могут оказаться неудачными. Общий подход к этому заключается в загрузке файла изображения CAPTCHA на ваш жесткий диск, его очистке, использовании Tesseract для анализа изображения и возвращении решения в соответствующий параметр формы.

Страница по адресу http://pythonscraping.com/humans-only  с защищенной CAPTCHA формой комментариев используется для написания бота для ее разгадывания. Этот бот использует библиотеку командной строки Tesseract, а не обертку pytesseract (хотя может использовать любую из них) и выглядит следующим образом:

from urllib.request import urlretrieve
from urllib.request import urlopen
from bs4 import BeautifulSoup
import subprocess
import requests
from PIL import Image
from PIL import ImageOps

def cleanImage(imagePath):
    image = Image.open(imagePath)
    image = image.point(lambda x: 0 if x<143 else 255)
    borderImage = ImageOps.expand(image,border=20,fill='white')
    borderImage.save(imagePath)

html = urlopen('http://www.pythonscraping.com/humans-only')
bs = BeautifulSoup(html, 'html.parser')

# Собираем предварительно заполненные значения формы
imageLocation = bs.find('img', {'title': 'Image CAPTCHA'})['src']
formBuildId = bs.find('input', {'name':'form_build_id'})['value']
captchaSid = bs.find('input', {'name':'captcha_sid'})['value']
captchaToken = bs.find('input', {'name':'captcha_token'})['value']
captchaUrl = 'http://pythonscraping.com'+imageLocation

urlretrieve(captchaUrl, 'captcha.jpg')
cleanImage('captcha.jpg')

p = subprocess.Popen(['tesseract', 'captcha.jpg', 'captcha'], stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p.wait()
f = open('captcha.txt', 'r')

# Убираем пробельные символы
captchaResponse = f.read().replace(' ', '').replace('\n', '')
print('Попытка решения CAPTCHA: '+captchaResponse)

if len(captchaResponse) == 5:
    params = {'captcha_token':captchaToken, 'captcha_sid':captchaSid, 'form_id':'comment_node_page_form', 'form_build_id': formBuildId, 'captcha_response':captchaResponse, 'name':'Ryan Mitchell', 'subject': 'I come to seek the Grail', 'comment_body[und][0][value]': '...and I am definitely not a bot'}
    r = requests.post('http://www.pythonscraping.com/comment/reply/10', data=params)
    responseObj = BeautifulSoup(r.text, 'html.parser')
    if responseObj.find('div', {'class':'messages'}) is not None:
        print(responseObj.find('div', {'class':'messages'}).get_text())
    else:
        print('Проблема с правильным чтением CAPTCHA!')

Обратите внимание, что этот скрипт не сработает в двух случаях: если Tesseract не извлечет ровно пять символов из изображения (потому что известно, что все правильные решения для этой CAPTCHA должны содержать пять символов), или если он отправит форму, но CAPTCHA будет решена неверно. Первый случай происходит примерно в 50% случаев, в которых он не беспокоится отправкой формы и завершается с сообщением об ошибке. Второй случай происходит примерно в 20% случаев, что в сумме дает точность около 30% (или около 80% точности для каждого символа из пяти).

Хотя этот результат может показаться низким, стоит помнить, что обычно нет ограничений на количество попыток, разрешенных пользователям для CAPTCHA, и большинство этих неправильных попыток можно прервать, не отправляя форму. Когда форма отправляется, CAPTCHA почти всегда распознается правильно. Если это вас не убеждает, также имейте в виду, что простое угадывание даст вам точность в 0.0000001%. Запустив программу три или четыре раза вместо 900 миллионов угадываний, вы сэкономите массу времени!

Индивидуальное и групповое обучение «Аналитик данных»
Если вы хотите стать экспертом в аналитике, могу помочь. Запишитесь на мой курс «Аналитик данных» и начните свой путь в мир ИТ уже сегодня!

Контакты
Для получения дополнительной информации и записи на курсы свяжитесь со мной:

Телеграм: https://t.me/Vvkomlev
Email: victor.komlev@mail.ru

Объясняю сложное простыми словами. Даже если вы никогда не работали с ИТ и далеки от программирования, теперь у вас точно все получится! Проверено десятками примеров моих учеников.

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

Практическая направленность. 80%: практики, 20% теории. У меня множество авторских заданий, которые фокусируются на практике. Вы не просто изучаете теорию, а сразу применяете знания в реальных проектах и задачах.

Разнообразие учебных материалов: Теория представлена в виде текстовых уроков с примерами и видео, что делает обучение максимально эффективным и удобным.

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

Понравилась статья? Поделиться с друзьями:
Школа Виктора Комлева
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

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