python - 如何从图像中删除背景线条和形状以进行文本提取?
问题描述
我只想提取文本并从下图中删除所有其他内容:
现在,我想删除除矩形形状中的文本之外的所有其他内容。那是我的代码:
import cv2
import pytesseract
import numpy as np
from imutils.perspective import four_point_transform
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
# Load image, convert to HSV, color threshold to get mask
image = cv2.imread('1.png')
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0, 0, 0])
upper = np.array([100, 175, 110])
mask = cv2.inRange(hsv, lower, upper)
# Morph close to connect individual text into a single contour
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
close = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=3)
# Find rotated bounding box then perspective transform
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
rect = cv2.minAreaRect(cnts[0])
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(image,[box],0,(36,255,12),2)
warped = four_point_transform(255 - mask, box.reshape(4, 2))
# OCR
data = pytesseract.image_to_string(warped, lang='eng', config='--psm 6')
print(data)
cv2.imshow('mask', mask)
cv2.imshow('close', close)
cv2.imshow('warped', warped)
cv2.imshow('image', image)
cv2.waitKey()
这是代码的输出:
我的代码的错误是它遮蔽了图像中的所有内容,我只想提取文本,而不是其他内容:
解决方案
由于您的图像中有“完美”的矩形,我想出了以下方法:
灰度和反向二值化输入图像以消除可能的伪影,并在黑色背景上有白色框和文本。
在下文中,将使用模板匹配来找到感兴趣的框的左上角。所以,设置一个模板和面具来模仿那些左上角。
模板本身类似于 50 像素长和 20 像素高的“角”,因为所有感兴趣的框至少具有以下尺寸:
相应的掩码将模板限制为沿“角”的 5 个像素宽的“条纹”:
由于所有文本与框的边界至少有 5 个像素的边距,因此将有“完美”的匹配结果,因为没有文本干扰匹配。
从“完美”的匹配结果中,
(x, y)
推导出每个感兴趣框的坐标,并进行迭代。盒子里充满了一些灰色(由于一开始的二值化,图像中只有黑色和白色)
然后使用该灰色遮罩:
由此确定边界矩形,并将该部分从原始图像复制粘贴到一些干净的图像中。此外,
pytesseract
对内容执行。
这是完整的代码:
import cv2
import numpy as np
import pytesseract
# Read image as grayscale
img = cv2.imread('M7X8C.png', cv2.IMREAD_GRAYSCALE)
# Inverse binarize image to get rid of possible artifacts, and to have
# white boxes and text on black background
thr = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY_INV)[1]
# Set up a template and mask mimicking the upper left corner of the
# boxes of interest
templ = np.full((20, 50), 255, dtype=np.uint8)
templ[1:, 1:] = 0
mask = np.full_like(templ, 255)
mask[5:, 5:] = 0
# Template matching
res = cv2.matchTemplate(thr, templ, cv2.TM_CCORR_NORMED, mask=mask)
# Extract upper left corners of the boxes of interest
boxes_tl = np.argwhere(res == 1)
# Initialize new clean image
clean = np.full_like(img, 255)
# For each upper left corner...
for i in np.arange(boxes_tl.shape[0]):
# Get coordinates of upper left corner
y, x = boxes_tl[i, :]
print('x: {}, y: {}'.format(x, y))
# Flood fill inner part of box, and mask that area
box_mask = cv2.floodFill(thr.copy(), None, (x + 1, y + 1), 128)[1] == 128
# Extract the bounding rectangle of that area
x, y, w, h = cv2.boundingRect(box_mask.astype(np.uint8))
# Copy box content to clean image
clean[y:y+h, x:x+w] = img[y:y+h, x:x+w]
# Run pytesseract on box content
text = pytesseract.image_to_string(thr[y:y+h, x:x+w], config='--psm 6')
print(text.replace('\f', ''))
# Output
cv2.imshow('clean', clean)
cv2.waitKey(0)
那是干净的图像:
而且,这是前两个pytessract
结果:
x: 1, y: 0
PGGEOS KKCI 100600
x: 199, y: 39
ISOL
EMBD
CB
400
XXX
如您所见,结果并不完美(S
而不是5
),很可能是由于等宽字体。traineddata
为这种字体获取(或生成)一些 Tesseract肯定会有助于克服这个问题。
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.19041-SP0
Python: 3.9.1
PyCharm: 2021.1.1
NumPy: 1.19.5
OpenCV: 4.5.2
pytesseract: 5.0.0-alpha.20201127
----------------------------------------
推荐阅读
- jquery - AJAX 发布执行操作但返回 403 Forbidden
- flask - 集成 Flask 安全性和 Flask Rest-JSONAPI
- reactjs - React + Redux-Observable + Typescript - 编译,参数不可分配错误
- php - Wordpress ACF get_field 虽然字段已填充但返回空数据/null
- c# - “给定的键不在字典中。” 结束对话框时出错
- java - 使用 ExecutorService 时 JavaFX 线程挂起
- typescript - Jest + Vue - SyntaxError: Unexpected token <
- vb.net - VB.Net BalloonTipText 显示为黑色矩形
- maxima - 更改最大值乘法的标准tex输出
- javascript - 当为 webpack 输入命令“npm run dev”时,它会创建一个以 NaN 结尾的文件夹