pytesseract和OpenCV在平面图上进行OCR

时间:2019-09-20 14:58:39

标签: python opencv ocr tesseract python-tesseract

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

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

例如当前 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 个答案:

答案 0 :(得分:1)

文本周围的所有像素化使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?

     

IN

     

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

     

所有尺寸仅是估计值,可能不是精确的测量计划   是主题更改吗? renderngs图matenala,熔岩,   观点

     开发人员,管理公司,所有者和其他关联企业   删除所有的主要离散内容,并且没有任何异常

     

jejes Araxs是近似的

处理后的图像:

enter image description here

答案 1 :(得分:1)

通过应用以下几行来调整并调整第二张图像上的对比度/亮度,后裁剪图像的底部四分之一:

nameof()

我设法得到了这个结果:

  

总约数。面积528 SQ.FT. (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输入相关数据,这样也可以使其速度更快。

编辑: 如果您还在寻找一种从文本中提取平方英尺的方法:

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

5471平方英尺