OpenCV如何通过识别表格网格线提取非均等尺寸单元格?
网格线识别法提取表格单元格实现方案
核心思路
不需要假设单元格尺寸均等,通过识别表格的水平、垂直网格线获得准确的分割坐标,再按坐标切割得到单个单元格。
具体实现步骤
- 图像预处理
先将原图转为灰度图,做高斯模糊过滤噪声,再用自适应阈值二值化后反色,让网格线变为白色前景,背景为黑色,提升后续线条检测的准确率。 - 网格线提取
使用形态学开运算分别分离水平和垂直网格线:- 水平线条:创建宽度远大于高度的水平矩形结构元,做开运算过滤掉垂直方向的文字、噪点,仅保留水平网格线
- 垂直线条:创建高度远大于宽度的垂直矩形结构元,同理做开运算提取垂直网格线
- 分割坐标计算
对提取到的水平线条图像,按行统计像素和,和大于阈值的行即为水平网格线的y轴坐标,排序后去重相邻的重复坐标;同理按列统计垂直线条图像的像素和,得到垂直网格线的x轴坐标,排序去重。 - 单元格切割
遍历相邻的x、y坐标,两两组合截取对应图像区域,即为单个单元格。
示例代码(基于OpenCV+Python)
import cv2 import numpy as np def get_table_cells(img): # 预处理:灰度、去噪、二值化反色 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (3, 3), 0) thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 提取水平网格线 h_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (img.shape[1]//9, 1)) h_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, h_kernel, iterations=2) # 提取垂直网格线 v_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, img.shape[0]//9)) v_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, v_kernel, iterations=2) # 计算水平网格线y坐标,去重相邻重复值 h_proj = np.sum(h_lines, axis=1) y_coords = np.where(h_proj > np.max(h_proj)*0.6)[0] y_list = [] last_y = -10 for y in sorted(y_coords): if y - last_y > 3: y_list.append(y) last_y = y # 计算垂直网格线x坐标,去重相邻重复值 v_proj = np.sum(v_lines, axis=0) x_coords = np.where(v_proj > np.max(v_proj)*0.6)[0] x_list = [] last_x = -10 for x in sorted(x_coords): if x - last_x > 3: x_list.append(x) last_x = x # 切割所有单元格 cells = [] for i in range(len(y_list)-1): row_cells = [] for j in range(len(x_list)-1): cell = img[y_list[i]:y_list[i+1], x_list[j]:x_list[j+1]] row_cells.append(cell) cells.append(row_cells) return cells # 调用示例 # img = cv2.imread("你的表格路径.jpg") # cells = get_table_cells(img)
可调优方向
- 如果输入表格存在倾斜,可以先通过霍夫线变换检测表格边缘,做透视变换校正表格角度后再提取网格线
- 阈值、结构元尺寸、相邻坐标去重的差值参数,可以根据你的图像实际分辨率和线条粗细调整,避免漏检或多检网格线
- 提取到的单元格如果带多余的边框,可以向内裁剪1-3个像素,消除边框对后续内容识别的干扰
内容的提问来源于stack exchange,提问作者Сalendula
相关产品推荐
相关产品推荐

