ドキュメント&知識ベース · daymade/claude-code-skills

photo-to-scanned-pdf

スキャナー風PDFを出力する2つのパイプライン。(1) 紙文書のスマホ写真(契約書、押印済み証明書、領収書、帳票、手書きメモ)→ 鮮明なスキャナー品質PDF:透視投影補正 + noteshrinkによる白地化 + A4統合 + 必須の全ページ確認。トリガー:「把照片 做成扫描件」「photos to scanned PDF」「make this look scanned」「手机拍的 文档转 PDF」「盖章文件扫描」、既存スキャンPDFのページ差し替え、CamScannerに類する各種依頼。(2) 未署名の電子文書(レンダリング済みdocx/PDF、確認票、契約書草案)→ 手書き署名・スキャン済み風に加工:手書き風署名を合成し、署名欄に合成後、同様のスキャン風後処理を適用。トリガー:「帮我做个手写签名」「生成签名盖到这份文件上」「做成签过字的扫描件」「synthesize a signature」、撮影した実物署名なしで署名済み風に見せる必要がある全般依頼。スキャン風を出すために手動でレベル補正やコントラスト調整を行わないこと(2度試して却下された経緯あり、本スキルのパイプラインが実証済みのアプローチ)。

L4 高権限 · 段階的認可と監査V1 コミット固定コマンド実行データ外部送信ネットワーク通信ファイル書き込みDual-pass Audit
Author daymadeGitHub daymade/claude-code-skills ↗Stars 1385License MIT(仓库根 LICENSE;Copyright (c) 2025 daymade;GitHub API spdx MIT)Commit d5c4678cb5
管理レベルは Skill の能力と推奨統制措置を示すものであり、品質や安全性の認証、利用可否の判定ではありません。使用の可否はユーザーおよび管理者が決定します。Agent 環境によって制約が異なるため、自動保護を仮定しないでください。第三者製 Skill の著作権は原著作者に帰属し、利用リスクは利用者が負います。

1仕組みと動作原理

2つのパイプラインは同一の仕上がり外観と設計哲学を共有:スクリプトは機械的実行に専念し、自動化不能な2つの判断(内容に基づくページ順序整列、全ドキュメント検証)はエージェントが担う。

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 → コンタクトシートによる全ドキュメント検証。

透視投影補正とホワイトバランスには内製OpenCVスクリプトを使用:photo_to_scan.py が最大輝度領域の四角形を検出して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生成をスキップして本スキル側で結合を実施。

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 ...
本スキルはレベル補正やトーンカーブの手動調整を厳禁としている(実ユーザーに2度却下された教訓をルール化)。zsh が変数をワード分割しない問題や、明示的なファイル名渡しが必要といったシェルの落とし穴も記載。

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* の作業セットを保持したまま該当ページを再実行し、ファイル名ではなく内容の一致により挿入位置を特定して全ドキュメントを再検証する。

検証規律としての「全ドキュメントコンタクトシートの確認必須」:make_contact_sheet.py で一覧画像を生成し、エージェントがページ順・色被り・印章や署名を全ページ確認した上で、1〜2ページを原寸大でサンプリングして鮮鋭度を点検する。

daymade-docs/photo-to-scanned-pdf/SKILL.md
**"I verified the pages I changed" is not verification.**
過去にリリースしてしまった2つの実バグ(ページ差し替え時の off-by-one による隣接ページ上書き、未編集ページへのパレット汚染)の反省から生まれたルールであり、変更ページのみの点検では見落とすリスクがある。

デジタル署名ブランチ(digital-signature-synthesis.md)は synthesize_signature.py の5つのサブコマンド(fonts/candidates/generate/locate/composite/scanify)で完結。フォントは candidates 比較シートからユーザーが選定(エージェントによる独断選択は禁止)、--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 等の候補群)を検出し、1文字ずつ独立したランダム回転(-6°〜3°)と字間詰め(0.70〜0.78倍)を適用。scanify で±0.3°の微小回転・ノイズ・輝度グラデーション・JPEG q86 劣化を付与。

合成署名の位置決めは pdftotext -bbox で署名欄ラベルを検出。フェイルセーフ機構として、ラベルと下線が1つの単語枠に結合された場合は 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 事象は「何もない空白領域に署名が浮いて配置される事態が静かに発生する」ことが実証されており、過去のインシデントを明示的なチェック項目に昇華させている。

2コア機能

01スマホ写真 → A4透視投影補正ページ変換(四角形検出 + EXIF修正 + FULLFRAMEフォールバックフラグ)
02noteshrink スキャン質感強調:白紙向けグローバルパレット / 色紙向けホワイトバランス前処理の分離実行
03A4 PDF結合(img2pdf による無再エンコード処理 + マージントリミング)
04全ドキュメント検証用コンタクトシート(順序・色被り・印影の全ページ点検)
05既存スキャンPDFの内容に基づくページ差し替え・挿入(ファイル名推測に依存しないスロット特定)
06手書き風署名の合成:フォント候補比較一覧の生成 → ユーザー選定 → 再現可能な生成(--seed)
07署名欄のピクセル位置特定 + 合成オーバーレイ + ページ全体の scanify 経年劣化加工(スキャン質感の一貫性保持)

3外部依存関係

KindDependency / Endpoint
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推奨統制措置と判定根拠

安全運用のための推奨統制措置
Agent 向け
段階的・都度認可、サンドボックス推奨
管理者向け
承認フロー、ロールバック可能、全履歴監査
判定根拠(ファイルパスと抜粋)
  • scripts/: ローカルスクリプトまたはコマンドの実行: python photo_to_scan.py / assemble_pdf.py / make_contact_sheet.py / synthes
  • 外部端点: ローカルコンテンツまたは会話のサードパーティクラウドストレージへの外部送信
  • 本地工作目录: ファイルの読み書きおよび成果物の出力: rectify/enhance の中間PNG、結合された scanned.pdf、contact.png の指定作業ディレクトリへの書き出し。署名ブランチにおける署名ファイルの出力
監査ノート: コードの接触面自体は青レベル(完全にローカルな画像処理ツール、ネットワーク外部送信なし、認証情報なし、削除処理なし)です。しかし、第2のパイプラインは「手書き署名された本物のスキャン文書に見えるファイル」を意図的に生成します。合成署名とスキャン風劣化処理による高忠実度な出力には欺瞞的な副作用があり、悪用リスク(契約書、確認票、委任状等の偽造)が実在するため、「迷った場合は上位基準を採用する」原則に基づき黄レベルと判定します。ドキュメント内には権限確認や用途制限のガードレールがないため、ホスト側でトリガー条件や受取人への周知状況を厳格に制御する必要があります。

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 を採用)。色紙と白紙の分離処理により色被り問題を解消。
  • 全ドキュメント検証の規律により、ページ上書きやパレット汚染といった実インシデント由来のバグを、コンタクトシート1枚の確認コストで確実に防止。
  • 署名合成の高いエンジニアリング品質:人手によるフォント選定ゲート、再現可能なシード値、バウンディングボックス結合時のWARNINGによる位置ズレ防止など、破綻しやすい箇所を網羅的にチェック機構化。
  • 「ファイル名を信用しない」設計(内容順ソート、明示的ファイル名指定、内容識別によるスロット配置)が双方のパイプラインで一貫して徹底されている。
  • 最適な用途: スマホで撮影した紙文書(契約書、押印済み証明書、領収書、手書きメモ)を整ったスキャンPDFに変換する日常業務に最適。署名ブランチは、正当な署名権限を持ち「電子的な手書き署名の外観」を必要とするユーザー、またはデモ・教育目的に適している。
    不向きな用途: 他者の署名の偽造や文書の真正性を改ざんするあらゆる用途(技術的制約ではなく用途上のリスク)。本物のスキャナー級のDPIや色精度が求められるアーカイブ用途。poppler や noteshrink が利用できない環境。
    Install Agent-Ready
    ① Verified Mirror 2026-09-09
    Option A · Direct DownloadDownload photo-to-scanned-pdf.tar.gz
    sha256: 0e8f936e0a123f3a…
    Option B · Copy Guide for Agent
    install.json
    Agent はこの JSON ガイドから自動的にダウンロードして検証します。
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit d5c4678cb5.