You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

复杂扫描工程文档表格结构化提取(含合并单元格、OCR)方案求助

复杂扫描工程文档表格结构化提取(含合并单元格、OCR)方案求助

我现在要处理的是扫描版工程文档里的表格提取,这个表格的情况特别棘手,具体有这些麻烦点:

  • 表头存在大量合并单元格
  • 行高、列宽完全不规则
  • 表格边框淡、有多处断裂
  • 每个单元格里都有文本内容
  • 文本里的竖笔画(比如I、|、1这类)和表格边框长得几乎一样
  • 还混着工程符号和logo

我的核心目标是1:1还原原表格的结构:包括正确的行列划分、合并单元格的准确识别、每个单元格的OCR文本都对应正确位置,最后输出成结构化格式(比如Pandas DataFrame)。


我需要的解决方案

我要的是能解决以下问题的完整方案:

  • 精准检测出真实的表格横竖线(不管是淡的、断的都要识别到)
  • 准确重建出表格的网格结构
  • 正确识别并处理合并单元格
  • 按人类阅读顺序逐个提取单元格的OCR文本
  • 输出和原表格布局完全匹配的结构化结果(比如Pandas DataFrame)

我已经尝试过的方法(附代码)但都失败了

我试了好几种OpenCV的经典表格检测方法,但全都踩了坑,下面是每个方法的情况:

1. 基于轮廓的单元格检测

代码片段:

cnts, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

❌ 遇到的问题:

  • 单元格内的文本会生成额外的小轮廓,严重干扰检测
  • 碰到文本的网格线会和文本轮廓合并成不规则的大多边形,根本没法区分
  • 完全搞不定单元格的阅读顺序
  • 合并单元格直接破坏了轮廓的层级关系
  • 表头行被拆成无数个子轮廓,根本没法正确识别

2. Hough直线变换

代码片段:

lines = cv2.HoughLinesP(binary, 1, np.pi/180, threshold=50)

❌ 遇到的问题:

  • 淡的、断裂的边框被检测成一堆零散的线段
  • 没法区分断裂的边框和噪声
  • 文本里的短竖笔画(I、|、1)会被误判成竖线
  • 要把零散的线段合并成完整的表格线,难度高到离谱

3. 形态学直线检测

代码片段:

# 检测水平线
h_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (80, 1))
h_lines = cv2.morphologyEx(bw, cv2.MORPH_OPEN, h_kernel)

# 检测竖直线
v_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 80))
v_lines = cv2.morphologyEx(bw, cv2.MORPH_OPEN, v_kernel)

❌ 遇到的问题:

  • 文本里的竖笔画(M、I、H、T、1这类)会被当成列线
  • 文本下方的短横笔画会被当成行线
  • 表头直接被拆成10-20个假列
  • 淡的断裂边框会生成多条零散的线

补充:尝试过连通域过滤但还是失败

我还加了强过滤规则,比如只保留高度≥图像高度70%、宽度≤10的竖线:

def filter_vertical(binary, min_height):
    num, _, stats, _ = cv2.connectedComponentsWithStats(binary)
    out = np.zeros_like(binary)
    for i in range(1, num):
        x,y,w,h,area = stats[i]
        if h >= min_height and w < 10:
            out[y:y+h, x:x+w] = 255
    return out

v_lines = filter_vertical(raw_v, int(0.7 * img.shape[0]))

❌ 还是不行:真实的断裂边框会被误过滤掉,而有些文本竖笔画的高度刚好超过阈值,还是会被当成表格线,把网格拆得乱七八糟。


为什么这个问题这么难

这个工程表格的特殊点,导致纯OpenCV的几何重建完全不靠谱:

  • 大量合并单元格,打破了规则的网格结构
  • 多层表头进一步增加了结构复杂度
  • 扫描质量差导致边框断裂、变淡
  • 文本和边框经常重叠
  • 文本里的竖笔画和表格边框几乎无法区分
  • 内部分隔线特别淡,容易被忽略

我想请教的问题

有没有推荐的方法(纯OpenCV、混合方案、或者基于ML的模型)能解决这个棘手的问题?具体要能:

  • 可靠检测表格网格(不管边框有多淡、多断)
  • 完整保留表格的原始结构(包括合并单元格)
  • 正确处理所有不规则的行高列宽
  • 按正确阅读顺序提取每个单元格的OCR文本

我能接受的方案类型:

  • 鲁棒的OpenCV流水线优化思路
  • 基于深度学习的模型(比如TableNet、CascadeTabNet、YOLO表格模型这类)
  • OpenCV+ML的混合方案
  • 现成的、能处理这种复杂表格的工具

最小可复现代码

下面是我当前的测试代码,即使加了过滤,还是会把文本竖笔画当成表格线:

import cv2
import numpy as np

img = cv2.imread("table.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
bw = cv2.adaptiveThreshold(
    gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 15, 8
)

# 形态学直线检测
h_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (80, 1))
raw_h = cv2.morphologyEx(bw, cv2.MORPH_OPEN, h_kernel)
v_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 80))
raw_v = cv2.morphologyEx(bw, cv2.MORPH_OPEN, v_kernel)

# 过滤竖直线(仍然失败)
def filter_vertical(binary, min_height):
    num, _, stats, _ = cv2.connectedComponentsWithStats(binary)
    out = np.zeros_like(binary)
    for i in range(1, num):
        x,y,w,h,area = stats[i]
        if h >= min_height and w < 10:
            out[y:y+h, x:x+w] = 255
    return out

v_lines = filter_vertical(raw_v, int(0.7 * img.shape[0]))
cv2.imwrite("vlines_debug.png", v_lines)

期望输出

最终能得到一个Pandas DataFrame,满足:

  • 每个单元格的位置完全对应原表格
  • 合并单元格的结构被正确保留(比如跨列/跨行的单元格在DataFrame里也能体现)
  • 文本按正确的阅读顺序填充
  • 整体布局和扫描件里的表格完全一致

麻烦各位大佬给点建议,不管是优化思路、工具推荐还是模型用法都可以!万分感谢🙏

火山引擎 最新活动