多模态科研内容理解 04:图表与公式——论文里的视觉信息

· 约 4 分钟 ·
本文目录(9 节)

论文不只有文字。实验结果在表格里、方法架构在示意图里、核心贡献常常是图 3 的那条曲线。平台的”多模态理解”这一环,就是把 PDF 里的视觉信息(图、表、公式)抽出来并赋予结构。这一课做这件事的最小可用版本:检测 → 抽取 → 图注配对 → 粗分类。

前置阅读:第 1 课 PDF 解析、OpenCV 基础见 OpenCV 系列、CNN 图像分类见 深度学习课程 04。

版面分析:先找到”图在哪”

PDF 里抽图有两条路线:

路线 1:直接提取嵌入图片。 PDF 里的位图是独立对象,PyMuPDF 可以直接挖出来:

import fitz
from pathlib import Path

Path("figures").mkdir(parents=True, exist_ok=True)
doc = fitz.open("paper.pdf")
for page_num, page in enumerate(doc):
    for img_index, img in enumerate(page.get_images(full=True)):
        xref = img[0]
        pix = fitz.Pixmap(doc, xref)
        if pix.width < 100 or pix.height < 100:
            continue                      # 滤掉装饰性小图/图标
        pix.save(f"figures/p{page_num}_{img_index}.png")

这里有个容易误解的地方:get_images 列出的是图片对象,不是读者看到的所有图表。矢量曲线、文字排成的表格可能根本不在这个列表中。同一张图也可能被拆成多个对象。要保留页面上完整的视觉区域,需要先确定边界,再渲染和裁剪页面,而不能把“抽到了图片”当作“抽全了图表”。

路线 2:版面检测模型。 把页面渲染成图片,再检测正文、标题、列表、表格和插图。下面的 LayoutParser + PubLayNet 示例只包含这五类,不能直接检测公式;公式需要另选支持该类别的模型,或增加独立识别步骤。检测框坐标属于渲染图片,映射回 PDF 时还要换算缩放比例。

import layoutparser as lp
import cv2

model = lp.Detectron2LayoutModel(
    "lp://PubLayNet/faster_rcnn_R_50_FPN_3x/config",
    label_map={0: "Text", 1: "Title", 2: "List", 3: "Table", 4: "Figure"})

img = cv2.imread("page_render.png")      # PDF 页面渲染成图
layout = model.detect(img)
figures = [b for b in layout if b.type == "Figure" and b.score > 0.7]

for i, fig in enumerate(figures):
    crop = fig.pad(left=5, right=5).crop_image(img)   # 留边裁出
    cv2.imwrite(f"figures/detected_{i}.png", crop)

路线 2 的优势是图、表、公式一视同仁——不管它在 PDF 里怎么实现,渲染成页面图后都是像素。工程上两条路线常混用:嵌入图走路线 1(保真度高),矢量图和表格区域走路线 2。

图注配对:图的意义在图注里

一张孤立的架构图没有上下文信息,它的语义在”图 3:模型总体架构”这句图注里。GROBID 解析出的 TEI 里有 figure 元素含图注文本;版面检测给出的图区域有坐标。按页面 + 垂直距离最近的原则配对:

def pair_figures_captions(detected_figs, grobid_figs):
    pairs = []
    for fig in detected_figs:
        candidates = [g for g in grobid_figs if g.page == fig.page]
        if candidates:
            nearest = min(candidates,
                          key=lambda g: abs(g.y - fig.y))
            pairs.append({"image": fig.path, "caption": nearest.caption})
    return pairs

配对必然有误差(多栏排版、跨页图),抽样检查配对准确率并记录——平台的”按图注搜图”功能质量上限就是这条配对的准确率。

图表粗分类:让检索可以按类型过滤

抽出来的图表做一个轻量分类:架构图 / 曲线图 / 表格 / 公式 / 其他。用深度学习课程 05的迁移学习范式,标注几百张图微调一个 ResNet18 就能做到可用水平。

这个分类的产品价值直接可见:用户搜”attention 架构图”时只返回架构图类;统计”某领域论文的表格密度”时表格类单独计数。分类器的训练数据从已配对的图注引导——图注含”architecture”的图大概率是架构图,这种弱监督标注省掉大量人工。

公式:识别是深水区,先做好边界

公式的完整识别(PDF → LaTeX)是独立的研究方向(pix2tex 等模型)。平台的务实策略:定位与裁剪交给版面检测,LaTeX 识别作为可选增强。默认只存公式区域的图片和位置,识别层后续按需接入。这个”先划清边界”的决定本身值得写进技术文档——明确不做什么和做什么同样重要。

数据落地:图表成为平台的一等公民

图表抽取结果按平台惯例落盘:

{
  "figure_id": "fig:1706.03762:p2:f0",
  "paper_id": "arxiv:1706.03762",
  "page": 2, "type": "architecture",
  "caption": "Figure 1: The Transformer - model architecture.",
  "image_path": "figures/1706.03762_p2_f0.png",
  "extractor": "layoutparser+embed",
  "extracted_at": "2026-08-29T00:30:00"
}

保留 extractor 和坐标信息:解析方案升级后可以只重跑旧方案产出的记录,增量演进。

踩坑排查

症状原因处理
抽出的图里没有曲线图矢量图不是嵌入位图走版面检测路线
检测结果大量误检置信度阈值太低score > 0.7 起步,抽样标定
图注配对错位多栏布局垂直距离失效加栏位置约束;人工抽验
表格被当成图检测器类别混淆后处理:区域文本密度高的改判 Table
扫描版 PDF 全失败无文本层,渲染分辨率低标记走 OCR 支线
图片数量爆炸占盘装饰图没滤掉尺寸 + 长宽比过滤

作品集证据

本课产出:图表检测-抽取-配对-分类的完整流水线 + 配对准确率的抽验报告。平台的论文卡片从此有了”图”的维度。

练习

  1. 用 PyMuPDF 提取 10 篇论文的嵌入图,统计被尺寸过滤掉的占比。
  2. 用 LayoutParser 对 20 个渲染页面做版面检测,人工核对 Figure/Table 的检测准确率。
  3. 实现图注配对并抽验 30 对,报告准确率与主要错误模式。
  4. 用图注关键词做弱监督标注,训练一个图表粗分类器并报告混淆矩阵。

面试常问

Q:科研 PDF 的图表抽取为什么难? 实现异构:位图可直接提取,矢量图和表格需版面分析;语义分离:图的意义在图注里,要跨元素配对;格式多样:模板、单双栏、扫描版各有坑。所以是”检测+配对+分类”的流水线而非单一模型。

Q:弱监督标注在本课怎么体现的? 用图注文本的启发式规则(含 architecture → 架构图)自动生成带噪声的标签,省去全人工标注;后续可用人工小样本做验证集,量化弱标签的噪声率。

Q:版面检测和 OCR 的区别? 版面检测回答”页面哪块区域是什么类型”(检测框+类别),OCR 回答”图像区域里写了什么文字”。扫描版 PDF 两者都要:先版面检测找结构,再 OCR 各区域。原生数字 PDF 文字层直接可读,不需要 OCR。


下一课:多模态科研内容理解 05:多模态融合——统一表示一篇论文。

💬 评论

这套方案在哪一步卡住了?也欢迎补充你的实现方式或踩坑经验。

正在连接评论服务,首次访问可能需要几秒…