做过通用 OCR 的人都知道,传统的 CRNN (CNN + RNN + CTC) 架构有一个致命假设:文字是水平排列的,从左到右读取。

但数学公式打破了这个假设。

  • 二维嵌套:$\sum$ 的上面有上限,下面有下限,右边才是主体;分数线把分子分母隔开;根号包裹着内部内容。
  • 符号歧义:一个简单的横线 -,可能是减号,可能是负号,也可能是分数线的一部分。

对于这种结构,传统的“检测框+文本识别”思路完全失效。Mathpix 的出现,把 OCR 问题变成了一个 机器翻译(Machine Translation) 问题。

1. 核心原理:Encoder-Decoder 架构

Mathpix(以及后来的开源项目 LaTeX-OCR)不把图片看作“一行字”,而是看作“一张图”。它的任务不是提取字符,而是生成描述这张图的代码(LaTeX)

这通常基于 Transformer 架构:

  1. Vision Encoder (视觉编码器):通常是一个 ResNet 或 ViT (Vision Transformer),把输入的公式图片变成一个高维的特征向量(Feature Map)。它负责“看懂”图片里的空间关系(比如谁在谁的上面)。
  2. Text Decoder (文本解码器):这是一个语言模型。它接收视觉特征,然后一个 Token 一个 Token 地吐出 LaTeX 代码。

比如,看到 $\frac{a}{b}$ 的图片:

  • 模型不是先认出 a 再认出 b
  • 模型生成序列是:\frac -> { -> a -> } -> { -> b -> }

这种 Sequence Generation(序列生成) 的思路,彻底解决了二维结构的识别难题。

2. API 实战:从图片到 LaTeX

Mathpix 主要是通过 API 卖服务(虽然贵,但真的强)。对于开发者来说,它的输入是图片,输出是 LaTeX、MathML 或 Markdown。

下面是一个标准的 Python 调用示例,展示如何将一张手写的数学公式图片转换为 LaTeX 代码:

Python

import requests
import json
import base64

# 需要去 mathpix.com 注册申请
APP_ID = 'your_app_id'
APP_KEY = 'your_app_key'

def image_to_latex(image_path):
    # 1. 图片转 Base64
    with open(image_path, "rb") as image_file:
        image_uri = "data:image/jpeg;base64," + base64.b64encode(image_file.read()).decode()

    # 2. 构造请求
    # v3/text 接口是目前的主力接口
    url = "https://api.mathpix.com/v3/text"
    
    headers = {
        "app_id": APP_ID,
        "app_key": APP_KEY,
        "Content-type": "application/json"
    }
    
    payload = {
        "src": image_uri,
        # 指定我们需要的格式
        # "latex_styled": 带样式的 latex
        # "math_ml": 用于网页渲染
        "formats": ["text", "data", "html"], 
        "data_options": {
            "include_latex": True,
            "include_mathml": True
        }
    }

    print("正在发送 Mathpix 请求...")
    response = requests.post(url, data=json.dumps(payload), headers=headers)
    
    if response.status_code == 200:
        result = response.json()
        
        # 3. 解析结果
        # Mathpix 非常贴心,它会把识别置信度 (confidence) 也返回
        if 'text' in result:
            print("\n=== 识别成功 ===")
            # 这里的 text 字段通常包含 LaTeX 源码,如 \( x^2 \)
            print(f"LaTeX 输出: {result['text']}") 
            
            # 如果需要纯净的 LaTeX (无 markdown 包装)
            latex_clean = result.get('data', [])[0].get('value', '')
            print(f"Clean LaTeX: {latex_clean}")
            
            # 置信度检查,低于一定阈值建议人工审核
            confidence = result.get('confidence', 0)
            print(f"置信度: {confidence:.4f}")
    else:
        print(f"请求失败: {response.text}")

if __name__ == "__main__":
    # 找一张稍微复杂点的手写积分公式
    img = "handwritten_formula.jpg"
    image_to_latex(img)

返回结果示例:

JSON

{
  "text": "\\( f(x) = \\int_{-\\infty}^{\\infty} \\hat{f}(\\xi)\\,e^{2 \\pi i \\xi x} \\,d\\xi \\)",
  "confidence": 0.985
}

你看,它直接给你生成了可以在论文里渲染的 LaTeX 代码。

3. 开源平替:LaTeX-OCR (pix2tex)

Mathpix 是商业闭源的,而且价格不菲(按次收费)。如果你的业务预算有限,或者数据不能出内网,怎么办?

开源界有一个非常有名的项目叫 LaTeX-OCR (pix2tex)

它基本上复现了 Mathpix 的早期架构(ViT + Transformer Decoder)。

  • Github: lukas-blecher/LaTeX-OCR
  • 部署成本:你需要一张显卡。它不能像 CRNN 那样在 CPU 上飞快地跑,因为 Transformer 的推理还是有开销的。

对比 Mathpix vs. 开源版:

  1. 手写体差距:Mathpix 的护城河在于它拥有海量的手写数学公式数据。开源模型在印刷体上表现不错,但遇到潦草的学生作业,识别率会下降很多。
  2. 混合排版:Mathpix 现在能处理“中文文本 + 公式”的混合图片。开源的 LaTeX-OCR 只能处理纯公式切片,如果你给它一张整页试卷,它会懵。

4. 什么时候该用 Mathpix?

技术选型建议:

  • 场景 A:搜题/作业批改 App
    • 必须选 Mathpix。学生的手写体千奇百怪,只有 Mathpix 的泛化能力能扛得住。自己训练模型达到这个精度的成本远高于 API 费用。
  • 场景 B:论文/教材数字化
    • 可以用 Mathpix,也可以尝试开源。如果是标准的印刷体公式,开源的 pix2tex 经过微调后完全可用。
  • 场景 C:大模型 RAG 预处理
    • 强烈推荐 Mathpix。如果你要把一篇 arXiv 论文喂给 GPT-4,你需要把 PDF 转成 Markdown。Mathpix 的 PDF 解析引擎(v3/pdf)能把双栏 PDF 里的公式完美还原成 LaTeX 嵌入 Markdown,这对 LLM 理解数学推理至关重要。

总结

在公式识别这个垂直赛道,Mathpix 是当之无愧的“神”。

它证明了一件事:当通用 OCR 还在纠结“这个字是 A 还是 B”的时候,垂直领域的 OCR 已经通过 生成式模型 开始“理解”内容的逻辑结构了。对于技术人员来说,理解 Image-to-Sequence 这种范式,比单纯会调 API 更重要。