Я написал сценарий на python с использованием pytesseract для встраивания текста в изображение. Когда я запускаю свой скрипт, скребок выполняет свою работу странно, что означает, что текст, который я получаю в результате, сильно отличается от того, что находится на изображении.
Скрипт, с которым я пробовал:
import requests, io, pytesseract
from PIL import Image
response = requests.get('http://skoleadresser.no/4DCGI/WC_Pedlex_Adresse/864928.jpg')
img = Image.open(io.BytesIO(response.content))
imagetext = pytesseract.image_to_string(img)
print(imagetext)
Текст на картинке выглядит так:
Результат у меня:
Adresse WM 0an Hanssensm 7 A
4u21 Slavanqer
warm 52 m so no
Te‘efaks 52 m 90 m
E'Dus‘x Van’s strandflanlmu
Как я могу получить точный результат?
Нет, я полагаю, что нет, потому что, когда я пытаюсь распечатать текст из этого изображения локально, результат все тот же.
Я не голосовал против, но согласен, кто бы это ни сделал, должен указать причину.






tl; dr:
import requests
import io
import pytesseract
from PIL import Image
response = requests.get('http://skoleadresser.no/4DCGI/WC_Pedlex_Adresse/864928.jpg')
img = Image.open(io.BytesIO(response.content))
width, height = img.size
new_size = width*6, height*6
img = img.resize(new_size, Image.LANCZOS)
img = img.convert('L')
img = img.point(lambda x: 0 if x < 155 else 255, '1')
imagetext = pytesseract.image_to_string(img)
print(imagetext)
Результаты в:
Adresse Prof. Olav Hanssens vei 7 A
4021 StavangerTelefon 52 70 90 00
Telefaks 52 70 90 01
E-post [email protected]
OCR предназначено для сканирования букв с печатных, рукописных или машинописных документов, которые сканируются с высоким разрешением, практически без размытия - возможно, существуют некоторые инструменты, предназначенные для сканирования цифровых изображений с низким разрешением и большим количеством размытия, но как правило, они не могут угадывать буквы из таких входных данных с любой разумной скоростью - они слишком размыты и содержат слишком мало пикселей, чтобы инструмент распознавания текста мог сделать что-то полезное с этими данными.
Это может звучать так, как будто у него мало шансов заставить его работать - простое масштабирование без какой-либо дополнительной обработки не поможет, как вы увидите позже, изображение все равно будет слишком далеко от похожего на что-либо подобное. печатный / печатный текст.
Я провел несколько проб и ошибок с коэффициентом масштабирования и обнаружил, что 6 лучше всего работают с этим изображением, поэтому:
width, height = img.size
new_size = width*6, height*6
Увеличение в 6 раз без повторной выборки:
img = img.resize(new_size)
Предоставляет нам это изображение, которое довольно бесполезно, потому что это в основном то же самое нечитаемое изображение, что и раньше, просто 1px * 1px теперь 6px * 6px (обратите внимание на серые области, которые почти пересекаются между буквами - особенно Pr, s и k будут приводят к большим проблемам):
К счастью, есть несколько формул передискретизации, которые дают очень хорошие результаты, для PIL есть PIL.Image.LANCZOS (среди других), который применяет Формула передискретизации Ланцоша:
img = img.resize(new_size, Image.LANCZOS)
Поначалу разница может показаться не такой уж большой - но теперь у нас есть лучшая заливка для букв вместо этих черных и серых блоков - и гораздо более естественное размытие, с которым мы можем работать на следующем шаге. Теперь, глядя на Pr, s и k, мы видим, что они больше не пересекаются так сильно.
Что нужно сделать дальше, чтобы изображение больше походило на фактически напечатанный документ, сделав его черно-белым, удалив размытие - первый шаг - заставить изображение работать с mode L (8-битные пиксели ч / б)
img = img.convert('L')
Конечно, практически нет разницы, поскольку исходное изображение было черным текстом на белом фоне, но все же вам нужен этот шаг, чтобы иметь возможность работать с порогом яркости, чтобы преобразовать его в черно-белое изображение.
Это делается путем оценки каждого пикселя изображения по его 8-битному значению - хорошее значение для начала - 128, который на 50% черный:
img = img.point(lambda x: 0 if x < 128 else 255, '1')
Это дает нам слишком тонкий текст - инструмент OCR распознает большинство 5 как S и некоторые 0 как O:
Теперь установив порог яркости на 200, мы получим следующее изображение:
Инструмент OCR может обрабатывать этот текст, поскольку он выглядит так же, как полужирный шрифт, но, как указывалось ранее, инструменты OCR нацелены на сканирование обычно печатаемого текста, поэтому есть вероятность, что он не сможет распознать фактический полужирный текст в изображении, поскольку он будет слишком жирный по сравнению с обычным текстом.
Давайте установим порог где-то между 128 и 200, чтобы мы получили естественно выглядящий печатный текст - немного проб и ошибок я обнаружил, что 155 работает отлично и выглядит так же, как и в исходном изображении:
Поскольку это очень похоже на сканирование в высоком разрешении плохо напечатанного ч / б документа, инструмент OCR теперь может правильно выполнять свою работу.
это кодировка?