全部技能 / 文档与知识 / photo-to-scanned-pdf
文档与知识 · daymade/claude-code-skills

photo-to-scanned-pdf

Two pipelines ending at a scanner-look PDF. (1) Phone photos of paper documents (contracts, stamped certificates, receipts, forms, handwritten notes) → clean scanner-quality PDF: perspective rectification + noteshrink whitening + A4 assembly + mandatory whole-document check. Trigger: "把照片 做成扫描件", "photos to scanned PDF", "make this look scanned", "手机拍的 文档转 PDF", "盖章文件扫描", replacing pages in an existing scanned PDF, any CamScanner-like request. (2) A digital document with no signature yet (rendered docx/PDF, confirmation form, contract draft) → make it look hand-signed and scanned: synthesize a handwriting-style signature, composite it onto the signature line, apply the same scan-look post-processing. Trigger: "帮我做个手写签名", "生成签名盖到这份文件上", "做成签过字的扫描件", "synthesize a signature", any request for a document that needs to look signed without a real photographed signature. Do NOT hand-roll levels/contrast enhancement for scan-look — tried and rejected twice; this skill's pipeline is the proven one.

风险提醒:黄色 · 留意使用AI 侦查报告
作者 daymadeGitHub daymade/claude-code-skills ↗Stars 1385许可 MIT(仓库根 LICENSE;Copyright (c) 2025 daymade;GitHub API spdx MIT)commit d5c4678cb5
agent 宿主通常会约束 skill 执行权限;风险提醒为 AI 侦查观点,不构成质量或安全保证。第三方 skill 仅作拆解与展示,安装使用风险自负,版权归原作者。

1实现原理 · 为什么它能做到

两条流水线共享同一终点外观与同一哲学:脚本只干执行,agent 保留两个不可自动化的判断——按内容排序页面、整档验证。

daymade-docs/photo-to-scanned-pdf/SKILL.md
**Division of labor**: scripts carry execution; you (the agent) carry the two judgment steps — content-based page ordering, and whole-document verification. Neither can be automated away: filenames lie about order, and per-page spot checks miss wrong-slot bugs.
注:主流水线:rectify(photo_to_scan.py --raw) → 按内容排序+判纸色(agent) → noteshrink 增强 → assemble_pdf.py → contact sheet 全档验证。

透视矫正与白平衡用自研 OpenCV 脚本:photo_to_scan.py 找最大亮斑四边形 warp 到 A4(200dpi),--raw 模式只矫正;默认模式多做『除以纸色背景』白平衡给彩纸页预洗。EXIF 旋转由 PIL exif_transpose 先修(cv2.imread 忽略 EXIF)。

daymade-docs/photo-to-scanned-pdf/SKILL.md
The script handles EXIF rotation internally (`cv2.imread` ignores EXIF; phone photos come rotated — this silently produces sideways pages if you rectify with raw OpenCV).
注:脚本为 PEP 723 uv run 单文件(opencv-python-headless/numpy/pillow 自动解析);彩色纸必须先白平衡再 noteshrink,否则黑墨变蓝紫、红章变绛红。

『扫描感』由 noteshrink(uvx 外部工具)量化调色板实现:白纸批量一次 -w -g -K 全局调色板统一墨/章色,-c "true" 跳过其内部 PDF 步骤由本 skill 自组装。

daymade-docs/photo-to-scanned-pdf/SKILL.md
uvx noteshrink -w -g -K -q -b ns -c "true" page_03.jpg page_01.jpg page_07.jpg ...
注:SKILL 反复强调不要手搓 levels/曲线——两度被真实用户否掉的教训写成规则;zsh 不 word-split 变量、要显式传文件名等 shell 坑也记录在案。

A4 组装带边缘裁剪:assemble_pdf.py 每页先裁 24px 顶/12px 侧(200dpi)去除矫正拖入的桌面边条,img2pdf 直接嵌调色板 PNG 不重编码,输出 ~0.05MB/页。

daymade-docs/photo-to-scanned-pdf/SKILL.md
Edge crop (default 24px top / 12px sides at 200 dpi) removes the sliver of desk surface that rectification drags in along page borders; document margins dwarf it.
注:既有扫描 PDF 换页=保留 ns*/nc* 工作集、重跑该页、按内容身份定位槽位再全档验证。

验证纪律是『全档 contact sheet 必读』:make_contact_sheet.py 出一张总览图,agent 逐页核对顺序/色偏/印章签名,再抽查 1-2 页全分辨率锐度。

daymade-docs/photo-to-scanned-pdf/SKILL.md
**"I verified the pages I changed" is not verification.**
注:两个真实 shipped-bug 故事支撑该规则:换页 off-by-one 覆盖邻页、调色板污染未编辑页——只查改动页都会漏。

数字签名分支(digital-signature-synthesis.md)用 synthesize_signature.py 五子命令完成:fonts/candidates/generate/locate/composite/scanify,字体必须经 candidates 页给用户挑(agent 不得自选),--seed 保证可复现。

daymade-docs/photo-to-scanned-pdf/references/digital-signature-synthesis.md
**Send the candidates sheet to the user and get a number back — do not pick one yourself.** Which style reads as a plausible signature is a taste call, not something derivable from the document or the font's technical properties.
注:生成器用 fc-list 发现手写体 CJK 字体(Hannotate/HanziPen/Xingkai/Kaiti/STKaiti 候选族),逐字独立随机旋转(-6°..3°)+收紧字距(0.70-0.78×);scanify 加 ±0.3° 旋转/噪声/亮度渐变/JPEG q86 做旧。

合成签名的定位靠 pdftotext -bbox 找签名行标签,并内建防错机制:标签与下划线被合并成一个 word 时会打 WARNING 并指导用像素扫描右缘,避免签名浮空。

daymade-docs/photo-to-scanned-pdf/references/digital-signature-synthesis.md
This means `pdftotext` tokenized your label together with whatever sits right after it on the same line — most commonly a signature blank authored as underscores immediately following the label with no space (`簽名:_____`, an entirely ordinary way to type this in Word).
注:该 WARNING 场景 'verified to place a signature floating in empty page space, silently'——文档把曾经的真事故写成检查项。

2核心能力

01手机照片→A4 透视矫正页(quad 检测 + EXIF 修正 + FULLFRAME 降级标记)
02noteshrink 扫描质感增强:白纸全局调色板 / 彩纸白平衡预洗分离处理
03A4 PDF 组装(img2pdf 免重编码 + 边缘裁剪)
04整档验证 contact sheet(顺序/色偏/章印逐页核查)
05既有扫描 PDF 按内容身份换页/插页(槽位不按文件名推)
06合成手写签名:字体候选对比页→用户挑选→可复现生成(--seed)
07签名行像素定位 + 合成叠加 + 全页 scanify 做旧(扫描一致性)

3外部依赖

类型依赖
cliuvx noteshrink(扫描感增强,PEP 723 首跑 ~30s 构建)
clipoppler pdftoppm / pdftotext(contact sheet / -bbox 定位)
packageopencv-python-headless / numpy / pillow / img2pdf(PEP 723 内联依赖)
cliLibreOffice soffice(签名分支把 docx 渲染成页图)
clifc-list(fontconfig,发现手写体字体)

4风险提醒 风险提醒:黄色 · 留意使用

风险提醒:黄色 · 留意使用
  • 合成签名+扫描做旧可被用于伪造文件外观(核心风险) — 产出物与真实签署扫描件难以区分,用于合同/确认单/授权书可误导接收方。skill 不设用途闸门,宿主/用户需自担授权与告知义务;仅应在确有签署权或明确演示用途时使用。
  • 判断步骤依赖 agent 眼力 — 内容排序、纸色判定、整档核查与合成效果目检都是人/模型判断;低质量模型可能跳过或走马观花,需宿主监督。
  • 环境依赖面 — 需要 poppler/soffice/noteshrink(uvx 联网首装)/fc-list 与手写体 CJK 字体(macOS 有、Linux 需自装)。
  • 无删除面但会覆盖输出 — 输出路径由用户给;assemble 的工作目录中间件 _pdfpage_*.png 会留在输入旁(--work-dir 可改)。
风险提醒:黄色,留意使用。代码接触面是蓝色档(纯本地图像工具、无网络外发、无凭证、无删除),但第二条流水线刻意产出『看起来是手写签署的真实扫描件』——合成签名+扫描做旧的高保真输出具有欺骗性副作用,误用面(伪造合同/确认单/授权书外观)真实存在,按『拿不准取高一档』定黄。文档内无授权/用途闸门,宿主应自行约束触发场景与接收方知情。

5第二遍独立确认

  • [ok] 主流水线 rectify→noteshrink→assemble→contact sheet — 四个环节命令与脚本均在;photo_to_scan.py --raw 与默认白平衡模式分支存在。
  • [ok] EXIF/quad/白平衡实现 — load_exif_corrected 用 ImageOps.exif_transpose;find_page_quad/warp_a4/flatten_whitebalance 函数在 photo_to_scan.py 源码可定位。
  • [ok] 边缘裁剪默认值 24/12px — assemble_pdf.py argparse default crop_top=24/crop_side=12 与 SKILL 一致。
  • [ok] noteshrink 参数 -w -g -K -c "true" — SKILL 命令与外部工具语义一致(noteshrink 为 uvx 外部包,未在本仓捆绑,命令调用方式可核)。
  • [ok] 『只查改动页不算验证』纪律 — SKILL 原文 + 两个 shipped-bug 叙事(错槽覆盖邻页、调色板污染)在 Step 5。
  • [ok] 签名分支六子命令 — synthesize_signature.py subparsers fonts/candidates/generate/locate/composite/scanify 均实现;candidates→用户挑选→generate 流程与 reference 一致。
  • [ok] 候选人选门禁(agent 不自选字体) — reference 原文 'do not pick one yourself';脚本 generate 需 --font/--face/--ink 显式参数。
  • [ok] 无网络/凭证/删除面 — 全脚本扫描零网络代码、零 env 密钥读取;无删除用户文件逻辑;子进程均列表参数。

6结论

  • 照片→扫描件的质量路线经过真实验证(noteshrink 而非手搓曲线),彩纸/白纸分离处理解决色偏难题。
  • 全档验证纪律防住了换页/调色板两类真实 shipped bug,验证成本仅一张 contact sheet。
  • 签名合成工程质量高:人挑字体门禁、可复现 seed、bbox 合并 WARNING 防浮空,把易翻车点都做成检查。
  • 对『文件名不可信』的系统性防御(内容排序、显式文件名、槽位按内容身份)在两条流水线一致执行。
  • 适合:适合把手机拍的纸质件(合同、盖章证书、收据、手写笔记)做成整洁扫描 PDF 的日常办公;签名分支适合确有签署权、需要『电子化手写签署外观』或演示/教学用途的用户。
    不适合:不适合用于伪造他人签署或篡改文件真实性的任何场景(用途风险,非技术不能);不适合要求真扫描仪级 DPI/色彩精度的归档需求;不适合无 poppler/noteshrink 的环境。
    安装 agent 直装可复制
    ① 本站镜像 更新 2026-09-09
    方式 A · 人下载镜像包下载 photo-to-scanned-pdf.tar.gz
    sha256: 0e8f936e0a123f3a…
    方式 B · JSON 格式安装指南,复制给 agent
    安装指南
    agent 读 JSON 指南后会自动从本站下载安装,无需更多说明。
    ② 上游 GitHub · 原始来源
    能访问 GitHub?直接去上游安装(实时版,可能已更新)GitHub 原始 ↗
    本页镜像锁定 commit d5c4678cb5;上游为实时仓库。
    来源信息 GitHub 原始
    作者 / 仓库daymade / daymade/claude-code-skills
    Stars1385
    最近推送2026-09-09
    本 skill commitd5c4678cb5
    许可MIT(仓库根 LICENSE;Copyright (c) 2025 daymade;GitHub API spdx MIT)
    本站信息
    收录日期2026-09-06
    分类文档与知识
    侦查报告2026-09-06 · 2 遍
    本站镜像与 GitHub 原始是不同来源:本站锁定 commit 快照经 /r2 分发;GitHub 为实时上游,内容可能已更新。