前段时间,工作中有个需求,需要提取图片表格中的内容,但是如何定位表格的坐标让我很是头疼,开始尝试了 matchTemplate 方法,但不是太理想,可能定位出多个重复目标,并且容易受到干扰,比如,如果有其他笔迹和表格线交叉,可能会影响匹配结果。后来在 opencv 官网上面看到了一个例子,效果非常好,在这里介绍给大家。
import cv2
import numpy as np
def showImage(winname, img):
cv2.imshow(winname, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
#删除表格的横线和竖线,但是保留表格内容
def removelines(imageurl):
image = cv2.imread(imageurl)
result = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# 移除水平线
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (40,1))
remove_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(remove_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
#通过画白线来清除水平线
cv2.drawContours(result, [c], -1, (255,255,255), 3)
# 移除垂直线
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,20))
remove_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(remove_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
#通过画白线来清除垂直线
cv2.drawContours(result, [c], -1, (255,255,255), 3)
showImage('result', result)
#提取表格
def extracttable(imageurl):
img = cv2.imread(imageurl)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
if len(img.shape) != 2:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
gray = img
gray = cv2.bitwise_not(gray)
bw = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 15, -2)
# 创建图像副本
horizontal = np.copy(bw)
vertical = np.copy(bw)
cols = horizontal.shape[1]
horizontal_size = cols // 5
# 定义结构元素
horizontalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (horizontal_size, 1))
# 图像形态学操作 腐蚀、膨胀
horizontal = cv2.erode(horizontal, horizontalStructure)
horizontal = cv2.dilate(horizontal, horizontalStructure)
rows = vertical.shape[0]
verticalsize = rows // 5
# 定义结构元素
verticalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (1, verticalsize))
# 图像形态学操作 腐蚀、膨胀
vertical = cv2.erode(vertical, verticalStructure)
vertical = cv2.dilate(vertical, verticalStructure)
mask = horizontal + vertical
result = cv2.bitwise_not(mask)
showImage("", result)
removelines('testimgnew/lines.png')
extracttable('testimgnew/lines.png')
复制
原始图片:
去除表格线的结果:
仅保留表格线:
除了使用适当的函数外,非常重要的一点是基于实际情况定义适合的结构元素。
在 removelines 方法中,循环 cnts 时,可以得到表格的具体坐标,进而就可以获取相应坐标内(也就是表格内各行列)图片内容,再基于具体业务进行后续处理。
文章转载自林员外聊编程,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
python排序sort()和sorted()区别
wzf0072
58次阅读
2025-04-09 19:57:46
AI与我共创WEB界面
布衣
50次阅读
2025-04-14 22:13:51
解决pyqt5 textbrowser控件超链接锚点问题
zayki
32次阅读
2025-04-27 16:58:59
python 实现消费者优先级队列
天翼云开发者社区
25次阅读
2025-04-25 11:08:21
优雅遍历和删除特定开头的key
陌殇流苏
24次阅读
2025-04-25 12:17:03
python中标识符的命名规则和命名规范
周同学带您玩AI
22次阅读
2025-04-21 10:34:44
《深入剖析Python的生成器表达式与列表推导式:探寻代码背后的哲学与艺术》
程序员阿伟
21次阅读
2025-04-27 16:22:14
python自动更新dns A记录
godba
11次阅读
2025-04-23 11:19:04
Python运维神器:这些模块让你事半功倍
韩公子的Linux大集市
11次阅读
2025-04-09 11:13:18
python中不同数据类型转换-布尔型
周同学带您玩AI
8次阅读
2025-04-22 10:12:05