如何用Python OpenCV为表格图像横竖线定义最小宽高以统计行列
问题:请愿书表格行列提取时误捕获文本的解决方法
问题背景
我正在处理8.5×11英寸的请愿书图像,目标是识别出包含类签名内容的行,计划通过反转图像隔离每行并统计白色像素数量。目前已经成功隔离请愿书中放置签名的表格区域,但提取行列时会误捕获到文本,不知道该怎么给横竖线段定义最小宽高来剔除这些干扰文本。
相关图像
处理后的图像

未处理的图像

当前代码实现
# 加载图像,转为灰度图,Otsu阈值处理 image = cv2.imread(img) 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, (25, 1)) horizontal = cv2.morphologyEx( thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2 ) cnts = cv2.findContours(horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] rows = 0 for c in cnts: cv2.drawContours(image, [c], -1, (36, 255, 12), 2) rows += 1 # 检测列数 vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 25)) vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2) cnts = cv2.findContours(vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] columns = 0 for c in cnts: cv2.drawContours(image, [c], -1, (36, 255, 12), 2) columns += 1 logger.info(f"Rows {rows - 1}") logger.info(f"Columns {columns - 1}") cv2.imshow("image", image) cv2.waitKey()
解决方案
核心是通过轮廓特征过滤,利用表格线条和文本轮廓的宽高差异,剔除干扰文本:
1. 水平行线过滤
表格的水平线通常长而窄,遍历轮廓时计算外接矩形宽度,设置最小宽度阈值(根据图像尺寸调整,比如200),只保留宽度达标的轮廓作为行线:
rows = 0 min_row_width = 200 # 可根据实际图像尺寸微调 for c in cnts: x, y, w, h = cv2.boundingRect(c) if w > min_row_width: # 过滤文本类窄小轮廓 cv2.drawContours(image, [c], -1, (36, 255, 12), 2) rows += 1
2. 垂直线过滤
表格的垂直线高而窄,计算轮廓外接矩形高度,设置最小高度阈值(比如150),只保留高度达标的轮廓作为列线:
columns = 0 min_col_height = 150 # 可根据实际图像尺寸微调 for c in cnts: x, y, w, h = cv2.boundingRect(c) if h > min_col_height: # 过滤文本类低矮轮廓 cv2.drawContours(image, [c], -1, (36, 255, 12), 2) columns += 1
3. 额外优化建议
- 阈值可结合图像实际分辨率调整:因为是8.5×11英寸的图像,扫描后分辨率不同,建议先查看图像像素宽高,按表格比例设置阈值(比如取表格宽度的1/2作为最小行宽)。
- 可叠加面积过滤:文本轮廓面积远小于表格线条,设置最小面积阈值进一步减少干扰。
内容的提问来源于stack exchange,提问作者Chris Keller
相关产品推荐
相关产品推荐

