---
name: scan-to-docx
display_name: 扫描资料转精准Word
display_name_en: Scan to Docx
description: 把扫描件（图片或 PDF）转成精准可编辑的 Word，并保留原图「下划线 = 需填写的空」的语义。内置 PaddleOCR 文字识别与下划线检测，文档专属配置外移到 profile，换一份资料只改 profile、不动管线。
description_zh: 扫描件（图片/PDF）转精准可编辑 Word，保留原图下划线填空语义，内置 PaddleOCR 与下划线检测，文档配置外移到 profile。
description_en: Convert scanned pages (images or PDF) to precise editable Word, preserving underline-as-blank semantics, with built-in PaddleOCR and underline detection; per-document config lives in a profile.
version: 1.0.3
slug: scan-to-docx
displayName: 扫描资料转精准Word
summary: 把扫描件（图片/PDF）转成可编辑 Word，保留原图下划线填空语义
license: MIT
author: kaiw800
category: office-efficiency
read_when:
  - 用户要把扫描件/照片/PDF 转成 Word
  - 原图有下划线填空，转后要保留成空位
  - 同类扫描件要批量处理、反复用同一套配置
---

# scan-to-docx · 扫描资料转精准 Word

通用型扫描资料 → Word 转换 skill。核心价值：**通用 OCR→docx 工具会丢掉原图下划线的「填空」语义，本 skill 把它还原成 Word 里可编辑的下划线空位**。

## 何时用

- 扫描件（图片 / PDF）想转成可编辑 Word。
- 原图有下划线填空，要求转后仍是下划线（不是纯文本）。
- 批量处理同类资料：写一个 profile，反复用。

## 架构（通用管线与文档配置解耦）

```
扫描图/PDF
  └─[ocr.py]   PaddleOCR 文字识别 + 下划线检测
        ├─ ocr_result.json  每页文字框 {x0,y0,x1,y1,text}
        └─ lines.json       每页下划线线段 segs [[x0,x1,y], ...]
  └─[pipeline.py]  行合并 → 块分类(标题/单元/课/条目/填空) → 下划线坐标重建 → 修正表应用
  └─[docx_writer.py]  版式/字体/页眉页脚/每页后缀，写出精准 .docx
```

所有「这份资料专属」的东西都在 **profile JSON** 里：纠错表、标题正则、版式常量、页眉页脚文案、段落后缀。换一份资料只改 profile，管线代码不动。

## 安装与联网边界

解压后将整个 scan-to-docx 文件夹安装到 skills 目录，保留 scripts/、profiles/、requirements.txt 和 LICENSE。推荐 Python 3.10–3.12，创建虚拟环境后运行 pip install -r requirements.txt。首次安装 Python 依赖和下载 PaddleOCR 模型需要联网；模型缓存完整后本机处理，不上传输入文件。只使用已有 OCR 中间结果时可仅安装 python-docx。不同 OCR/Paddle 版本的兼容性需按实际平台验证。

## 依赖

```
paddlepaddle  paddleocr  python-docx  opencv-python(paddleocr 自带)  pypdfium2(paddleocr 自带)
```
PaddleOCR / opencv / pypdfium2 在 `ocr.py` 内懒加载；只用「吃已有 OCR 结果」模式时不需 paddle。

## 用法

**1) 直接吃已有 OCR 中间结果（调试/回归）：**
```bash
python scripts/run.py \
  --ocr-result ocr_result.json --lines lines.json \
  --profile profiles/_base.json \
  --out out.docx
```

**2) 内部跑 PaddleOCR（标准用法）：**
```bash
python scripts/run.py \
  --input scan.pdf            # 或图片目录 / 单张图
  --profile profiles/_base.json \
  --out out.docx
```
`--input` 模式会把 OCR 中间结果写到 `--work-dir`（默认输出目录下的 `.ocr_tmp`）。

## Profile 字段

| 字段 | 说明 |
|---|---|
| `block_rules` | 块分类正则：`title/unit/lesson/item/sub2/sub`，每项 `{regex, max_len?, first_page_only?}`。匹配不到则归为 `cont`。 |
| `corrections.global` / `corrections.once` | `[[错字,正字], ...]`。匹配不上只警告不崩溃。 |
| `skip` | 跳过行正则（页脚页码、水印等）。 |
| `motto_filter` | 含此串且较短的行整体丢弃。 |
| `title_text` / `lesson_suffix` | 标题固定文案、每课末尾后缀（如「班级：＿ 姓名：＿」）。 |
| `fonts` / `page` / `header` / `footer` | 字体、页边距、页眉页脚（footer="page" 生成「第X页 共Y页」）。 |
| `ul_y_minus` / `ul_y_plus` / `ul_overlap` | 下划线映射窗口与重叠阈值。 |
| `ul_detect_threshold` / `ul_band_ratio` / `ul_min_width_ratio` | `ocr.py` 下划线检测的暗度阈值、条带比例、最小宽度比。 |

模板：`profiles/_base.json` —— 字段齐全但取中性默认值的空骨架，照着它复制改名即可，无需附带任何具体资料的配置。

## 扩展新资料类型

1. 复制 `_base.json` 改名，按新资料填 `block_rules`、`corrections`、`page`、`header` 等。
2. 先用「吃已有 OCR 结果」模式跑通，核对下划线段落数与预期。
3. 再切到 `--input` 模式整链验证；下划线偏少就调低 `ul_detect_threshold` 或 `ul_min_width_ratio`。

## 已知边界

- 表格、插图目前按「整页文本 + 填空」处理；结构化表格恢复是后续模块（PaddleOCR layout 已具备基础能力，按需接入）。
- 不同 OCR 引擎识别结果不同，换引擎后 `corrections` 需按新错字重校。
- 下划线检测对扫描质量敏感：阴影、双下划线、手写体可能漏检，靠 profile 阈值调。

