Python & OpenCV:如何在无网格表中添加线条
Posted
技术标签:
【中文标题】Python & OpenCV:如何在无网格表中添加线条【英文标题】:Python & OpenCV: How to add lines to gridless table 【发布时间】:2021-07-12 08:58:35 【问题描述】:我有下表:
我想编写一个脚本,根据表格文本上的自然中断创建行。结果如下所示:
是否有可以绘制这些线条的 OpenCV 实现?我查看了here 和here 问题的答案,但都没有奏效。解决这个问题的最佳方法是什么?
【问题讨论】:
转换为灰度和阈值,这样所有白色的东西都保持白色,而其他所有的东西都变成黑色。然后计算每行中非零像素的数量(np.count_nonzero)。您的线条将绘制在每组全白行的中间。 正是我需要的,谢谢!由于某种原因出现脑梗塞 【参考方案1】:这是在 Python/OpenCV 中获取水平线的一种方法,方法是计算图像每行中白色像素的数量,以找到它们的中心 y 值。垂直线可以通过类似的过程添加。
输入:
import cv2
import numpy as np
# read image
img = cv2.imread("table.png")
hh, ww = img.shape[:2]
# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# threshold gray image
thresh = cv2.threshold(gray, 254, 255, cv2.THRESH_BINARY)[1]
# count number of non-zero pixels in each row
count = np.count_nonzero(thresh, axis=1)
# threshold count at ww (width of image)
count_thresh = count.copy()
count_thresh[count==ww] = 255
count_thresh[count<ww] = 0
count_thresh = count_thresh.astype(np.uint8)
# get contours
contours = cv2.findContours(count_thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
# loop over contours and get bounding boxes and ycenter and draw horizontal line at ycenter
result = img.copy()
for cntr in contours:
x,y,w,h = cv2.boundingRect(cntr)
ycenter = y+h//2
cv2.line(result, (0,ycenter), (ww-1,ycenter), (0, 0, 0), 2)
# write results
cv2.imwrite("table_thresh.png", thresh)
cv2.imwrite("table_lines.png", result)
# display results
cv2.imshow("THRESHOLD", thresh)
cv2.imshow("RESULT", result)
cv2.waitKey(0)
阈值图像:
带有线条的结果:
添加
这是一种稍微简单的替代方法。它将图像平均到一列,而不是计算白色像素。
import cv2
import numpy as np
# read image
img = cv2.imread("table.png")
hh, ww = img.shape[:2]
# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# average gray image to one column
column = cv2.resize(gray, (1,hh), interpolation = cv2.INTER_AREA)
# threshold on white
thresh = cv2.threshold(column, 254, 255, cv2.THRESH_BINARY)[1]
# get contours
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
# loop over contours and get bounding boxes and ycenter and draw horizontal line at ycenter
result = img.copy()
for cntr in contours:
x,y,w,h = cv2.boundingRect(cntr)
ycenter = y+h//2
cv2.line(result, (0,ycenter), (ww-1,ycenter), (0, 0, 0), 2)
# write results
cv2.imwrite("table_lines2.png", result)
# display results
cv2.imshow("RESULT", result)
cv2.waitKey(0)
结果:
【讨论】:
非常有帮助 - 比我想出的更优雅 更新:我运行了代码,它运行良好。再次感谢周到的回答! 在我的回答中添加一个稍微简单的方法。 更简单的方法效果很好。如果它不会太麻烦,我想知道你将如何使用更简单的方法来实现垂直线。我尝试将column = cv2.resize(gray, (1, hh), interpolation=cv2.INTER_AREA) thresh = cv2.threshold(column, 254, 255, cv2.THRESH_BINARY)[1]
更改为row = cv2.resize(gray, (1, ww), interpolation=cv2.INTER_AREA) thresh = cv2.threshold(row, 254, 255, cv2.THRESH_BINARY)[1]
,但是在调用cv2.drawContours
时,看到轮廓仍在逐行绘制。我错过了什么吗?这是我使用 OpenCV 的第一天
几乎可以使用第一个版本。我只是在中心值方面遇到了麻烦。我目前有xcenter = y+h//2
,这会导致线条略微偏离。 (我使用了另一张图片,因为实心标题干扰了列标识。)以上是关于Python & OpenCV:如何在无网格表中添加线条的主要内容,如果未能解决你的问题,请参考以下文章