You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python单独识别表格图片中的每个单元格

解决方案

核心思路

基于OpenCV做图像分析,利用已知网格线颜色先提取网格结构,再分割出每个单元格的坐标区域,最后关联对应行首和表头单元格进行展示。

步骤实现

1. 图像预处理与网格线提取

已知网格线颜色(黑/白),先将图像转为灰度图,再通过阈值分割提取网格线区域,最后用形态学操作强化网格线的连通性:

import cv2
import numpy as np

# 读取图像
img = cv2.imread("table_image.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 根据网格线颜色设置阈值:黑色网格线取低阈值,白色取高阈值
grid_color = "black"  # 替换为"white"如果是白色网格线
if grid_color == "black":
    _, grid_mask = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY_INV)
else:
    _, grid_mask = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)

# 形态学操作:让网格线更连贯
kernel = np.ones((2,2), np.uint8)
grid_mask = cv2.morphologyEx(grid_mask, cv2.MORPH_CLOSE, kernel)

2. 检测行/列分割线

通过霍夫变换检测水平和垂直方向的直线,提取所有分割线的坐标并排序:

# 检测水平线
horizontal_lines = cv2.HoughLinesP(grid_mask, 1, np.pi/180, threshold=100, minLineLength=img.shape[1]//2, maxLineGap=10)
# 提取并排序y坐标
y_coords = sorted(list(set([line[0][1] for line in horizontal_lines])))

# 检测垂直线
vertical_lines = cv2.HoughLinesP(grid_mask, 1, np.pi/180, threshold=100, minLineLength=img.shape[0]//2, maxLineGap=10)
# 提取并排序x坐标
x_coords = sorted(list(set([line[0][0] for line in vertical_lines])))

3. 生成所有单元格坐标

通过行和列的分割线坐标组合,得到每个单元格的矩形区域:

cells = []
# 遍历行(跳过最后一条线)
for i in range(len(y_coords)-1):
    row_cells = []
    # 遍历列(跳过最后一条线)
    for j in range(len(x_coords)-1):
        x1, y1 = x_coords[j], y_coords[i]
        x2, y2 = x_coords[j+1], y_coords[i+1]
        # 存储单元格区域和对应的行/列索引
        row_cells.append({"region": (x1, y1, x2, y2), "row_idx": i, "col_idx": j})
    cells.append(row_cells)

4. 关联行首与表头单元格

提前提取表头(第一行所有单元格)和行首(每一行第一个单元格)的区域:

# 提取表头单元格(第一行)
headers = [cell["region"] for cell in cells[0]]
# 提取行首单元格(每一行第一个)
row_headers = [row[0]["region"] for row in cells]

5. 循环展示单元格及对应行首、表头

遍历每个单元格,截取对应区域并展示:

for row in cells:
    for cell in row:
        # 跳过表头和行首自身(可选,根据需求调整)
        if cell["row_idx"] == 0 or cell["col_idx"] == 0:
            continue
        # 截取当前单元格
        x1, y1, x2, y2 = cell["region"]
        current_cell = img[y1:y2, x1:x2]
        # 截取对应行首
        rh_x1, rh_y1, rh_x2, rh_y2 = row_headers[cell["row_idx"]]
        row_header_cell = img[rh_y1:rh_y2, rh_x1:rh_x2]
        # 截取对应表头
        h_x1, h_y1, h_x2, h_y2 = headers[cell["col_idx"]]
        header_cell = img[h_y1:h_y2, h_x1:h_x2]
        
        # 合并展示(这里用水平拼接,可根据需求调整)
        combined = np.hstack((row_header_cell, header_cell, current_cell))
        cv2.imshow("Cell Analysis", combined)
        # 等待用户操作(比如按任意键进入下一个单元格)
        cv2.waitKey(0)

cv2.destroyAllWindows()

注意事项

  • 如果网格线有轻微倾斜,可先做图像矫正(比如基于霍夫变换的直线角度调整)
  • 霍夫变换的参数(threshold、minLineLength等)需要根据实际图片尺寸调整,确保准确检测到网格线
  • 若单元格存在合并情况,需要额外处理(比如检测相邻单元格的分割线是否缺失)

内容的提问来源于stack exchange,提问作者Dolev Mitz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 23:32:45