【问题标题】:How do I improve the number detection for blueprints (OCR)如何改进蓝图的数字检测 (OCR)
【发布时间】:2021-04-14 02:13:27
【问题描述】:

我有许多蓝图,我想检测蓝图上的数字,以便将它们变成合适的模型。 例如,我有以下图片,并且想要这张图片上的所有数字,所以我运行了以下代码:

import pytesseract
from pytesseract import Output
import cv2
import numpy as np
img = cv2.imread('vdb7C.jpg')

custom_config = r' (--oem 2 --psm 10'
d = pytesseract.image_to_data(img,config=custom_config,lang='eng', output_type=Output.DICT)

n_boxes = len(d['level'])
for i in range(n_boxes):
    text=d["text"][i]
    print(text+ str(str.isdigit(text)))
    if str.isdigit(text):
        (x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i])
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)


cv2.imwrite("output.jpg" , img)

这给了我以下结果:。正如您所看到的,它确实正确识别了蓝图上的一些数字,但是它错过了很多其他数字并错误地检测到了一些实际上并不存在的数字。我更关心获得所有数字而不是一些误报,但仍希望将这些数字保持在最低限度,所以有什么建议吗?

我已经尝试过细化操作、重新缩放图像、旋转图像和平滑图像,但所有这些似乎都没有太大区别,极端重新缩放(*0.1 或 *10)确实改变了一些事情但是在图像的某一部分取得的任何进步都会被其他部分出现的错误所抵消。

特别困难的情况是在左侧建筑物中,我们的行号接近甚至重叠设计的一部分。
在这里,我们看到 2 个此类情况的示例

还要注意图片之间的字体使用不一致。

值得注意的是,线条几乎总是明显比用于数字的线条更细,所以也许可以用它来做点什么?

我也尝试过使用 EAST OCR 系统,代码如下: img = cv2.imread('vdb7C.jpg')

W=5664
H=4000
dim = (W, H)
img = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
net = cv2.dnn.readNet("frozen_east_text_detection.pb")
blob = cv2.dnn.blobFromImage(img, 1.0, (W, H),
(123.68, 116.78, 103.94), swapRB=True, crop=False)
net.setInput(blob)
(scores, geometry) = net.forward(["feature_fusion/Conv_7/Sigmoid",
"feature_fusion/concat_3"])
(numRows, numCols) = scores.shape[2:4]
rects = []
confidences = []
# loop over the number of rows
for y in range(0, numRows):
    # extract the scores (probabilities), followed by the geometrical
    # data used to derive potential bounding box coordinates that
    # surround text
    scoresData = scores[0, 0, y]

    xData0 = geometry[0, 0, y]
    xData1 = geometry[0, 1, y]
    xData2 = geometry[0, 2, y]
    xData3 = geometry[0, 3, y]
    anglesData = geometry[0, 4, y]
    for x in range(0, numCols):

        if scoresData[x] < confidence:
            continue

        (offsetX, offsetY) = (x * 4.0, y * 4.0)

        angle = anglesData[x]
        cos = np.cos(angle)
        sin = np.sin(angle)

        h = xData0[x] + xData2[x]
        w = xData1[x] + xData3[x]

        endX = int(offsetX + (cos * xData1[x]) + (sin * xData2[x]))
        endY = int(offsetY - (sin * xData1[x]) + (cos * xData2[x]))
        startX = int(endX - w)
        startY = int(endY - h)

        rects.append((startX, startY, endX, endY))
        confidences.append(scoresData[x])
    boxes = non_max_suppression(np.array(rects), probs=confidences)
    for box in boxes:
        (y,h,x,w) = box
        print(box)
        print(np.shape(img))
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imwrite("output.jpg" , img)

但是这会导致相当多的边界框位于图像之外,并且通常边界框似乎与内容无关,所以有人知道那里是什么吗? 有什么建议?我现在有 8000 张图片,最终总共需要处理大约 400k 张图片。

【问题讨论】:

  • 欢迎任何建议(即使只是批评我的代码风格),如果您有任何问题,请发表评论,以便我改进问题。
  • 有趣的项目。我认为 yxour 的代码有点短,无法正确检测到东西。查看其中一些教程pyimagesearch.com/category/optical-character-recognition-ocr
  • @user3732793 感谢您的链接,我将查看这些建议
  • @MadMike 不幸的是,在大多数情况下,数据不以 .png 形式存在,大部分数据是 .jpg,我认为这是不可逆的。
  • 删除大于数字的高或宽的行

标签: python python-3.x machine-learning computer-vision ocr


【解决方案1】:

我建议使用应用神经网络的解决方案,例如应用 CRAFT 和 CRNN 的 keras-ocr。它在检测与设计重叠的文本方面做得更好。这是我开箱即用的:

import matplotlib.pyplot as plt
import keras_ocr

detector = keras_ocr.detection.Detector()

image = keras_ocr.tools.read('vdb7C.jpg')
boxes = detector.detect(images=[image])[0]
canvas = keras_ocr.tools.drawBoxes(image, boxes)
plt.imshow(canvas)

结果:

【讨论】:

    【解决方案2】:

    运行您的 tesseract 代码,但只使用 3 位或更多位的结果。这应该为您提供足够好的数字示例。将每个数字提取到单独的文件并保存它们的位置。现在你可以走两条路。

    如果您会看到数字的字体非常相似,您可以采用简单的方法。然后,您可以为数字创建一组模板(例如 15-30)。还记得您可以获得特定图像的数字大小吗?将您的数字模板调整到合适的大小并运行最简单的模板匹配。这肯定会产生一些错误检测(尤其是对于“1”),您必须找到一种方法将它们的数量减少到可接受的水平。

    更复杂的方法是构建自定义 CNN 检测器并根据您的数据对其进行训练。因此,从第一阶段开始,您将获得数百个您想要检测的数字(及其位置)示例。您可以查看此project 或此one 作为参考。还有这个article可以给你一些指导。

    还有一件有用的东西。您的图像有很多长的垂直线。如果将它们与轴对齐,则可以通过将原件二值化、将结果(向右或向下)移动几个像素并对它们进行与运算来轻松删除线条。这将只留下长线。求出它们的长度,就可以把原图中超过一定长度的线去掉。

    【讨论】:

    • 删除线的方法似乎是一个好计划,但让我担心的一件事是,有时线会穿过值,如果发生这种情况不会;您的方法不会导致出现间隙价值? tesserect 接受非连续数字还是我必须以某种方式修复它们(可能通过检查线像素是否接触非线像素)?
    • 是的,它会造成差距。是的,Tesseract 能够检测具有小间隙的字符。对于较大的间隙(粗线),您可以恢复间隙。只需扫描移除(水平)线的下方和上方,如果您发现上方和下方都有黑色像素,请将它们连接起来。我使用这种方法的目的是在使用模板匹配时减少垂直线上“1”的错误检测,而不是为了清理图像。
    猜你喜欢
    • 2015-03-27
    • 2020-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    相关资源
    最近更新 更多