【问题标题】:OCR on floorplan screenshots with pytesseract and OpenCV带有 tesseract 和 OpenCV 的平面图屏幕截图上的 OCR
【发布时间】:2020-01-21 15:47:36
【问题描述】:

我正在尝试编写一个函数,该函数将获取房屋平面图的 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

但是我并没有取得太大的成功。只有大约四分之一的图像实际输出包含平方英尺的文本。

例如目前 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 sq ft”(以及所有可能的写法)

有没有更好的方法来做到这一点?

非常感谢。

【问题讨论】:

  • 可能更容易识别墙壁、比例和单位,然后自己进行计算,不是吗? ;)
  • 我不知道为什么会有关于低 DPI 是否重要的​​争论。这很重要。如果您查看阈值图像的质量,那么您从 tesseract 中获得任何文本都是一个奇迹。如果可以的话,推荐更高的 DPI,最好是无损格式(PNG 通常是一个不错的选择)。对于这样的图像,无损压缩通常仍会产生较小的文件大小。
  • 您是否只想提取“近似总内部面积 = 50.7 平方米 / 546 平方英尺”这一行?
  • @bfris 争论似乎在 DPI 和分辨率之间,因为 DPI 只是一个显示指令。即分辨率很重要,但 DPI 不重要。
  • @nathancy 是的,就是这条线,或者更具体地说是“546 平方英尺”

标签: python opencv ocr tesseract python-tesseract


【解决方案1】:

通过应用这几行来调整第二张图像的大小和更改对比度/亮度,裁剪图像的底部四分之一之后:

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 平方英尺。 (49.0 平方米)

虽然已尽一切努力确保地板的准确性 此处包含的平面图,尺寸:门、窗、房间和任何 其他项目是近似的,不承担任何责任 错误、遗漏或错误陈述。该计划适用于@ustrative 仅供任何潜在购买者使用。 所示的服务、系统和设备未经测试,也没有 保证a8对可操作性或效率可以给予 Metropix ©2019

我没有设置图像的阈值,因为您的图像结构各不相同,并且由于图像不仅仅是文本,OTSU 阈值没有找到正确的值。

回答所有问题:Tesseract 实际上最适合灰度图像(白色背景上的黑色文本)。

关于 DPI/分辨率问题,确实存在一些争论,但也有一些经验事实:DPI 值并不重要(因为相同 DPI 的文本大小可能会有所不同)。为了使 Tesseract OCR 发挥最佳效果,您的角色需要(已编辑 :) 30-33 像素(高度),小几 px 会使 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 平方英尺

【讨论】:

    【解决方案2】:

    文本周围的所有像素化使 Tesseract 更难做它的事情。 我使用了一个简单的brightness/contrast algorithm from here 来消除这些点。我没有做任何阈值/二值化。但我确实必须缩放图像才能识别字符。

    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())
    

    tesseract 的输出(我添加了粗体以强调平方英尺):

    TT xs?

    输入

    大约总内部面积 = 50.7 平方米 / 546 平方英尺

    所有尺寸仅为估计值,可能不是准确的测量计划 是主题 lo 更改草图。渲染图 matenala,熔岩, 方面

    ne 开发商、管理公司、业主和其他附属公司 re rng oo all of ma ther sole discrebon 并且没有 enor scbioe

    jements Araxs 是近似值

    处理后的图像:

    【讨论】:

    • 更新了编写输出图像的代码。我正在使用您发布的图片。如果您的输出图像看起来不像我的,那么可能我们正在处理不同的源图像。我正在使用 tesseract 4.0.0-beta.1。
    • @bfris config='--remove-background' 在 Tesseract 上工作吗?对我来说,当我删除前两个破折号config='remove-background'
    • @singrium,感谢您的关注。我已经更新了答案。除非我删除了选项上的双破折号,否则我无法让 tesseract 在 Windows 上运行。
    猜你喜欢
    • 2019-11-02
    • 2014-02-25
    • 2015-09-16
    • 1970-01-01
    • 2010-09-07
    • 2016-07-28
    • 1970-01-01
    • 1970-01-01
    • 2015-10-30
    相关资源
    最近更新 更多