OCR на скриншотах плана этажа с помощью pytesseract и OpenCV - PullRequest
0 голосов
/ 20 сентября 2019

Я пытаюсь написать функцию, которая возьмет jpg плана этажа дома и использует OCR, чтобы извлечь квадратные метры, которые написаны где-то на изображении

    import requests
    from PIL import Image
    import pytesseract
    import pandas as pd
    import numpy as np
    import cv2
    import io

    def floorplan_ocr(url):
    """ a row-wise function to use pytesseract to scrape the word data from the floorplan
    images, requires tesseract 
    to be installed https://github.com/tesseract-ocr/tesseract/wiki"""

    if pd.isna(url):
        return np.nan

    res = ''
    response = requests.get(url, stream=True)
    if response.status_code == 200:
        img = response.raw
        img = np.asarray(bytearray(img.read()), dtype="uint8")
        img = cv2.imdecode(img, cv2.CV_8UC1)
        img = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
            cv2.THRESH_BINARY,11,2)
        #img = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2)
        res = pytesseract.image_to_string(img, lang='eng', config='--remove-background')
        del response
        del img
    else:
        return np.nan

    #print(res)
    return res

enter image description here

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

например, в настоящее время floorplan_ocr(https://i.imgur.com/9qwozIb.jpg) выводит 'K\'Fréfiéfimmimmuuéé\n2|; apprnxx 135 max\nGArhaPpmxd1m max\n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\nTOTAL APPaux noon AREA 523 so Fr, us. a 50. M )\nav .Wzms him "a! m m... mi unwary mmnmrmm mma y“ mum“;\n‘ wmduw: reams m wuhrmmm mm“ .m nanspmmmmy 3 mm :51\nmm" m mmm m; wan wmumw- mm my and mm mm as m by any\nwfmw PM” rmwm mm m .pwmwm m. mum mud ms nu mum.\n(.5 n: ma undammmw an we Ewen\nM vagw‘m Mewpkeem' (и это занимает много времени)

floorplan_ocr(https://i.imgur.com/sjxMpVp.jpg) выводит' '.

Я думаю, что некоторые проблемы, с которыми я сталкиваюсь, следующие:

  1. текст может быть в оттенках серого
  2. Изображения с низким DPI (кажется, некоторые дебатыесли это действительно важно, или если это общее разрешение)
  3. Текст не отформатирован последовательно

Я застрял и изо всех сил пытаюсь улучшить свои результаты.Все, что я хочу извлечь, это «XXX кв. Фут» (и все способы, которые могут быть написаны)

Есть ли лучший способ сделать это?

Большое спасибо.

Ответы [ 2 ]

1 голос
/ 23 сентября 2019

Применяя эти несколько строк для изменения размера и изменения контраста / яркости вашего второго изображения, после обрезки нижней четверти изображения:

img = cv2.imread("download.jpg")

img = cv2.resize(img, (0, 0), fx=2, fy=2)

img = cv2.convertScaleAbs(img, alpha=1.2, beta=-40)

text = pytesseract.image_to_string(img, config='-l eng --oem 1 --psm 3')

мне удалось получить этот результат:

ВСЕГО ОК.НАПОЛЬНАЯ ПЛОЩАДЬ 528 SQ.FT.(49,0 кв. М.)

Несмотря на то, что были предприняты все усилия для обеспечения точности приведенного здесь плана этажа, размеры: дверей, окон, помещений и любых других предметов являются приблизительными и не несут ответственности залюбая ошибка, упущение или неправильное утверждение.Этот план предназначен только для ознакомительных целей и должен использоваться любым потенциальным покупателем.Показанные услуги, системы и устройства не были протестированы, и нельзя дать никаких гарантий относительно работоспособности или эффективности. Сделано с Metropix © 2019

Я не пороговую составляющую изображения, поскольку структура ваших изображений отличается от однойдругое, и поскольку изображение не только текстовое, OTSU Thresholding не находит правильное значение.

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

Что касается вопроса о разрешении / разрешении, действительно, есть некоторые споры, но есть и эмпирическая правда: значение DPI на самом деле не имеет значения (поскольку размер текста может варьироваться для одного и того же DPI).Чтобы Tesseract OCR работал лучше всего, ваши персонажи должны иметь (отредактировано :) 30–33 пикселя (высота), уменьшение на несколько пикселей может сделать Tesseract практически бесполезным, а большие символы фактически снижают точность, хотя и незначительно.(правка: найден источник -> https://groups.google.com/forum/#!msg/tesseract-ocr/Wdh_JJwnw94/24JHDYQbBQAJ)

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

РЕДАКТИРОВАТЬ: Если вы также искали способ извлечь квадратные метры из текста ocr'ed:

text = "some place holder text 5471 square feet some more text"
# store here all the possible way it can be written
sqft_list = ["sq ft", "square feet", "sqft"]
extracted_value = ""

for sqft in sqft_list:
    if sqft in text:
        start = text.index(sqft) - 1
        end = start + len(sqft) + 1
        while text[start - 1] != " ":
            start -= 1
        extracted_value = text[start:end]
        break

print(extracted_value)

5471 квадратных футов

1 голос
/ 22 сентября 2019

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

import pytesseract   
import numpy as np
import cv2

img = cv2.imread('floor_original.jpg', 0) # read as grayscale
img = cv2.resize(img, (0,0), fx=2, fy=2)  # scale image 2X

alpha = 1.2
beta = -20
img = cv2.addWeighted( img, alpha, img, 0, beta)
cv2.imwrite('output.png', img)  

res = pytesseract.image_to_string(img, lang='eng', config='--remove-background')
print(res)

Редактировать Может быть некоторая зависимость платформы / версии от приведенного выше кода.Он работает на моей машине с Linux, но не на моей машине с Windows.Чтобы запустить его в Windows, я изменил последние две строки на

res = pytesseract.image_to_string(img, lang='eng', config='remove-background')
print(res.encode())

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

TT xs?

IN

Приблизительная общая внутренняя площадь = 50,7 кв. М / 546 кв. Футов

Все размеры являются приблизительными и могут не быть точными.тема изменена. Эскизы.renderngs graph matenala, lava, apectes

ne Девелопер, управляющая компания, владельцы и другие аффилированные лица, относящиеся ко всем отдельным дисконбонам и без enor scbioe

jements. Аракс приблизительные

Изображение после обработки:

enter image description here

...