PDF 设计稿版本差异对比(pdf-design-diff)
用途
对同一份设计稿/图纸的两个 PDF 版本做多层交叉验证,定位并标注差异。一条命令按序完成:
- 文件级 sha256 检查(相同即短路);
--all逐页粗筛跳过完全相同页 - 像素 diff 定位差异块(主扫 + 灵敏度补扫)
- 文本层行级集合差 + 矢量路径 bbox 签名多重集差 → 增/删元素数
- OCR 读出内容(6x);关键行(许可证/电话/日期/公司/地址)先用已在算的整页 3x 读数免费交叉验证,不足才升 10x,且只重扫关键行邻域窗口
- 条码/QR/UDI 解码对比:按 payload 集合差对比,不对比图像
- 差异块内小簇聚类 + 位移模式 + 高清裁图 + 结论草稿 + 合并报告
- 属性级自动核验(默认开):矢量逐点差 + 8 字段属性差 + 框外核验一次进程跑完,并标出未被任何像素簇覆盖的属性变化(漏检守卫)
何时使用
- 用户给出同一图纸的两个版本 PDF(文件名常带 V03/V04、Rev A/B、日期后缀)要求对比差异
- 图纸为全矢量(包装设计稿、版面工艺图),文字已转曲线,肉眼或文本提取无法对比
- 需忽略标题栏/修改记录只看中间设计稿,或需标注差异位置并输出证据
- 版面含条码/二维码/UDI(GS1 DataMatrix、批号、效期)要按解码数据核对
- 多页说明书/版面逐页对比
不适用:纯文本 PDF 的合同/文档对比(文本 diff 更快);位图扫描件大幅面比对(先做图像配准)。
使用方法
运行打包脚本(不要逐段重写分析代码):
python scripts/compare_design_drafts.py OLD.pdf NEW.pdf --out diff_output \
--auto-align --forensics --barcode --details auto:6 --draft-report --pack
一条命令产出全部交付物。随后只剩一步 LLM 工作:把 report_md.draft.md 改写为 report_md.md(补语义结论与风险),需要时重跑 --pack。
最常用参数(完整参数、子脚本 CLI、产物清单见 references/parameters.md):
| 参数 | 默认 | 说明 |
|---|---|---|
--auto-align |
关 | 含自动量外框;两版外框尺寸一致即裁剪归一(_aligned/),页眉表格/修改记录随之排除。外框 = 面积最大的单个闭合矩形,多面板版面它只是一个面板 |
--ignore-rect x0,y0,x1,y1 |
无 | 忽略区(PDF pt),可重复。标题栏/修改记录必须由此排除;不归一化时才用 |
--all / --page N |
0 | 逐页对比(自动跳过完全相同页)/ 只对比第 N 页 |
--barcode |
关 | 条码/QR/UDI 按 payload 集合差对比;解码固定跑原始页 |
--details auto:6 / --detail-combo N |
关 / 3 | 按簇出 detail_*.png + index.tsv / 多簇拼一张 combo_overview.png |
--draft-report / --pack |
关 | 出 report_md.draft.md / 结束时合成合并报告 PDF |
--no-ocr |
关 | 无 OCR 环境时降级为「区域定位 + 路径增删计数」,不臆测内容 |
--verify-scope-max-px / --ocr-threads |
8e6 / 自动 | 关键行 10x 复核的整块面积上限(超限只重扫关键行窗口,0 = 旧行为)/ onnxruntime 推理线程数(0 = 不干预 = 旧行为) |
环境依赖:pymupdf、numpy、pillow、rapidocr-onnxruntime(或 easyocr)。缺 rapidocr 时先试 easyocr;中文模型 zip 损坏(BadZipFile)是 easyocr 常见坑,直接换 rapidocr。
★ 硬性规则 1:报告的 md 一律用结论式摘要,禁止直接指向 diff_summary.md(后者是机器证据:逐行 OCR 清单、像素坐标、路径增删计数,进正文会淹没细节,实测被退回)。报告只有三节:① 结论——共 N 处差异的语义结论与风险;条码与关键行复核在此以单行条目出现;② 差异汇总表(编号 / 位置 / 旧版 → 新版 / 性质,一行一条、语义级);③ 说明——只写范围不写内容(忽略区坐标/名称、弱差异性质、原始明细留档位置)。「位置」列必须保留「p0 块 #N / p0 簇 N.M」前缀,否则合并报告脚注会映射错块或丢行。结构只以 report_md.draft.md 或 references/report_md.template.md 为准,禁止拿历史报告/上一份报告当模板。合成前 check_report_md.py 机械校验:忽略区内容入正文即 block(退出码 4)。
★ 硬性规则 2:已删除的「对比方法」与「重点复核项」两节不得 re-add。 前者是过程信息(旧/新版标注、链路段、坐标基准、忽略区行),后者是机器证据表格(条码 payload、关键行复核状态)——其风险内容已在「结论」段以单行条目保留,信息不丢但不占章节位。旧报告里若还有这两节,那是历史产物,不要照抄。
执行提速(默认路径)
分工原则:能代码做的都在脚本里。 外框测量、归一化裁剪、位移量化、证据裁图、报告配置与合成全部由脚本一次完成——不要临时写 Python/JSON 片段补这几步(实测那样一轮要 20+ 次工具往返)。
- 一条命令出全部产物,把输出一次看全,不要一步一探。
- 解释器固定:用已装全依赖的 Python,勿逐环境探测;脚本启动即打印
[OK] interpreter:与[OK] pymupdf ...,读这两行即可。 - 读图预算:默认 0 张,最多 2 张(硬闸门)。内容结论以
diff_summary.md的「差异块内部小簇」段为准(与放大图红框同源);只有判视觉形态(Logo 重绘风格、图标形状、底纹)时才读图,且每读一张必须先登记(read_budget.py)。超预算未授权、或自报张数与台账不符,--pack直接失败(退出码 5)。 - LLM 只做两件事:定范围(是否/如何排除页眉与修改记录)与写结论(性质归类、风险标注)。位置、量值、条码 payload、复核状态一律取脚本输出,不靠目测。
- 补充取证 / 差异定性 / 矢量·属性·框外核验各有专责脚本,都走一个进程:
probe_regions.py(批量探针,spec 驱动)、diag_reexport.py(栅格差 / 缩放 / 位移 / 内容增删)、forensics_kit.py(逐点差 / 属性差 / 框外核验)。不要一个疑点起一个python -c。 - 批量合并跑:多对文件一次跑完再统一写报告;不需要内容结论时加
--no-ocr。 - 性能:
--timing打函数级incl/self表并写timing.json。OCR 是唯一主要算力成本,要提速只能从「次数 × 倍率」入手;耗时结构与已证伪的提速手段见references/methodology.md「性能」节。
解读与汇报规则
- 三层证据齐全才下结论:像素块位置 + 路径增删数 + OCR 内容互相印证;只有像素证据时只报位置与大小,不猜内容。
- 关键数据复核状态必须为 OK;RECHECK 时换更高倍率或换引擎再验,并在「结论」段以单行风险条目如实标注(不单列复核章节)。
- 汇报按差异块逐条:位置 → 旧内容 → 新内容 → 性质(删除 / 新增 / 改写 / 位移 / 格式修正)。
- 忽略区内容(标题栏版本号、修订日期、修改记录新增行)不得出现在报告任何位置(含汇总表与说明段);说明段只引用脚本的「忽略区命中 N 处」计数与坐标并声明已按要求忽略。反例(禁止):「版本号 V03→V04、修订日期 …」——转述内容 ≠ 写范围。
- OCR 是矢量小字的最后手段:7–8pt 转曲线字 6x 渲染是下限,关键行 10x。
详细方法学、排错与实测案例见 references/methodology.md。
注意事项
- 控制台与脚本输出只用 ASCII 符号(
[OK]/[WARN]/[NG]),禁用 emoji(GBK 控制台会崩)。坐标一律用 PDF pt 思考与传参;渲染像素 = pt × scale,换算错误是定位偏差首要来源。 - 条码能力边界:zxing-cpp 解 QR/DataMatrix/EAN/UPC/Code128,cv2 解 QR + EAN/UPC。UDI 场景先确认 zxing-cpp 可用;全缺时必须注明「DataMatrix 未解码」,不得只看 QR 就下「条码无变化」结论。
- 两版页尺寸不一致:优先加
--auto-align(外框尺寸一致即归一,不一致则[WARN]并保持不归一化)。降级分支与三分支判定见 methodology「页尺寸不一致」。 - 多面板版面(纸盒展开图)先看守门告警:
--auto-align的外框只是其中一个面板,其余面板会被静默排除(实测覆盖率低至 16%)。覆盖率 <60% 时脚本[WARN]并打印可直接粘贴的--frame-rect,仍须对照annotated_*_p<N>.png确认覆盖;或去掉--auto-align按面板分别比对。 - 重新导出型 PDF(同内容不同导出批次:白边零差异 + 正文散布 2–5% 像素差 + ±3px 平移最优偏移 0)属字形栅格差,不是内容变化;三步诊断见 methodology「重新导出型」。
- 页级聚合成单一大块时以「差异块内部小簇」为准(簇矩形 + 带内单侧差异行 + 位移模式):通常无需读图即可定结论;窄条簇(宽/高 <3pt)为边界/线条位移,量值看
--forensics。 - 细条小差异块(高 <30pt 且宽 <200pt)的放大图与 OCR 自动外扩到整行;整页标注红框仍标原始小块。
- PDF 报告生成坑(pymupdf):
insert_text(fontname="china-s")对长中英混排静默截断(rc 仍返 1)→ 带 CJK 报告一律TextWriter+Font("china-s"),保存后逐块回读校验(build_merged_report.py已内置,退出码 2)。 - 黄底条标的是内容层面新增/删除/改写的字词,不是「这行动过」:行内只改几个字就只圈那几个字,只改字号/换行而文字未变不标黄,纯插入行只在插入侧标黄。判定细则(双路 OCR 交叉验证、密度守门)见 methodology「黄底条」节。
版本历史
| 版本 | 变更摘要 |
|---|---|
| 1.6.0 | OCR 算力回收(结论零变化):关键行 10x 复核收缩到关键行邻域窗口(原为整块外接矩形重扫)+ 无关键行侧直接跳过;onnxruntime 推理线程固定(默认自动,--ocr-threads)。实测否决并回退「细条块外扩改吃整页 3x 词源」 |
| 1.5.0 | 属性级自动核验内置主链路(run_post_verify,默认开);多簇证据总览图 combo_overview.png;框外核验外框口径与裁剪统一 |
| 1.4.2 | MIN_CLUSTER_ROWS 10→8 修掉 6pt 小字差异块被静默丢弃;新增 forensics_kit.py 取证三件套;实测否决整页 3x OCR 并集化提速 |
| 1.4.1 | 报告精简:删去「对比方法」「重点复核项」两节,只留结论 / 差异汇总 / 说明 |
| 1.4.0 | diag_reexport.py 一键判差异性质;报告红字脚注自适应;读图登记可批量 |
| 1.3.9 | --timing 函数级耗时表(incl/self)+ probe_regions.py 单进程批量探针 |
| 1.3.7–1.3.8 | 忽略区内容闸门(退出码 4);读图预算硬闸门(退出码 5)、报告模板唯一格式源 |
| 1.3.0–1.3.6 | 黄条只标差异词 / 过密不清空 / 多面板守门 / 条码改跑原始页;合并报告去重裁图;提交合规整改(提速 25%) |
| 1.0.0–1.2.0 | 一站式自动化(auto-align/forensics/details/pack);免读图小簇证据;平台合规首版 |
完整逐版明细见 CHANGELOG.md。