我有许多蓝图,我想要检测蓝图上的数字,以便我可以将它们转换为适当的模型。例如,我有以下图像

并且想要这个图像上的所有数字,所以我运行了以下代码:
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)确实改变了一些事情,但在图像的一个部分所做的任何增益都会被出现在其他部分的错误所抵消。
特别困难的情况是,比如在左边的建筑中,我们有接近甚至重叠部分设计的线条和数字。
在这里我们可以看到两个这种情况的例子。


另请注意,不同图像之间的字体使用不一致。
值得注意的是,线条几乎总是明显地比用于数字的fond更细,所以也许可以用它来做一些事情?
我也用下面的代码尝试使用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张图片,最终需要处理大约40万张图片。
发布于 2021-01-26 16:01:22
我建议使用一个应用神经网络的解决方案,比如keras-ocr,它应用了CRAFT和CRNN。它在检测与设计重叠的文本方面做得更好。这是我用它开箱即用得到的:
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)结果:

发布于 2021-01-20 04:33:38
运行你的tesseract代码,但只使用3位或3位以上的结果。这将为您提供足够多的数字示例。提取每个数字到单独的文件中,并保存它们的位置。现在,您可以选择两种方式。
如果你会发现这些数字的字体非常相似,你可以使用简单的方法。然后,您可以为数字(例如15-30)创建一组模板。还记得你可以得到特定图像的数字大小吗?将您的digits模板调整为合适的大小,并运行最简单的模板匹配。这肯定会产生一些错误检测(特别是对于“1”),您必须找到一种方法将它们的数量减少到可接受的水平。
更复杂的方法是构建一个自定义的CNN检测器,并根据您的数据对其进行训练。因此,从第一阶段开始,您将获得数百个您想要检测的数字(及其位置)的示例。您可以将此project或此one视为参考。此外,此article还可以为您提供一些指导。
还有一件事是有用的。你的图像有很多长长的垂直线。如果您将它们与轴对齐,则可以通过将原始图像二值化、将结果(向右或向下)移位几个像素并对其执行ANDing操作来非常容易地删除线条。这样就只剩下很长的行了。找到它们的长度,您将能够删除原始图像中超过特定长度的行。
https://stackoverflow.com/questions/65627843
复制相似问题