0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

似顔絵ポートレートの制作メモを自動検査する小さなPythonスクリプト

0
Posted at

はじめに

AIで似顔絵やカリカチュアを作ると、一度のセッションで複数の案を比較できます。一方で、どの写真を使ったのか、誰が承認したのか、無料枠と有料オプションのどちらを前提にしたのか、といった判断は会話の中に散らばりがちです。あとから「この画像は共有してよいのか」を確認するには、制作メモそのものが読み返せる形になっている必要があります。

この記事では、制作メモを検査する小さなPythonスクリプトを紹介します。画像を生成するAPIは呼びません。標準ライブラリだけで、Markdownのメモに必要な項目がそろっているかを確認します。似顔絵の出来栄えを採点するものではなく、共有前に確認すべき記録を可視化するための道具です。

何を検査するか

メモは「キー: 値」の1行形式にします。検査する項目は次の8つです。

項目 ルール 目的
consent yes のみ許可 生成前に対象者の同意を記録する
source photo または description 入力の種類を明確にする
ownership 空でないこと 写真や文章の権利元を残す
style 8つのスタイル枠のいずれか 仕上がりの方向性を固定する
exaggeration 1〜10の整数 誇張の強さを数値で残す
review pending / approved / rejected 公開前の状態を管理する
disclosure free / paid / not_needed 無料枠か有料オプションかを記録する
caption_privacy checked のみ許可 キャプションの個人情報を確認する

スクリプト

以下が本体です。ファイルを読み、問題があれば箇条書きで表示し、終了コード1を返します。

"""Audit a portrait-session notes file before an image is generated or shared."""
from __future__ import annotations

import sys
from pathlib import Path

REQUIRED = {
    "consent": "yes",
    "source": {"photo", "description"},
    "ownership": None,
    "style": {"classic", "sketch", "watercolor", "manga", "cartoon", "retro", "pencil", "vector"},
    "exaggeration": (1, 10),
    "review": {"pending", "approved", "rejected"},
    "disclosure": {"free", "paid", "not_needed"},
    "caption_privacy": "checked",
}


def parse_notes(text: str) -> dict[str, str]:
    notes: dict[str, str] = {}
    for raw in text.splitlines():
        line = raw.strip()
        if not line or line.startswith("#") or ":" not in line:
            continue
        key, value = line.split(":", 1)
        notes[key.strip().lower()] = value.strip()
    return notes


def audit(notes: dict[str, str]) -> list[str]:
    problems: list[str] = []
    if notes.get("consent") != "yes":
        problems.append("consent must be recorded as yes before generation")
    if notes.get("source") not in REQUIRED["source"]:
        problems.append("source must be photo or description")
    if not notes.get("ownership"):
        problems.append("ownership of the source photo or brief is missing")
    if notes.get("style") not in REQUIRED["style"]:
        problems.append("style must match one of the eight configured style slots")
    try:
        level = int(notes.get("exaggeration", ""))
        if not 1 <= level <= 10:
            problems.append("exaggeration must be an integer from 1 to 10")
    except ValueError:
        problems.append("exaggeration must be an integer from 1 to 10")
    review = notes.get("review")
    if review not in REQUIRED["review"]:
        problems.append("review must be pending, approved, or rejected")
    if review == "approved" and not notes.get("reviewer"):
        problems.append("an approved result needs a named reviewer")
    if notes.get("disclosure") not in REQUIRED["disclosure"]:
        problems.append("disclosure must record free, paid, or not_needed")
    if notes.get("caption_privacy") != "checked":
        problems.append("caption_privacy must be checked before sharing")
    return problems


def main(path: str) -> int:
    notes = parse_notes(Path(path).read_text(encoding="utf-8"))
    problems = audit(notes)
    if not problems:
        print("notes look complete")
        return 0
    for problem in problems:
        print(f"- {problem}")
    return 1


if __name__ == "__main__":
    sys.exit(main(sys.argv[1]))

consent と caption_privacy は yes/checked 以外を受け付けません。review が approved のときは reviewer も必須にしています。承認者を書かずに承認済みへ進む運用を防ぐためです。

8つのテストケース

検査関数は副作用がないので、合成したメモでテストできます。完全なメモ1件と、7種類の壊れたメモを用意しました。

from portrait_notes_audit import audit

BASE = {
    "consent": "yes",
    "source": "photo",
    "ownership": "provided by the person in the portrait",
    "style": "sketch",
    "exaggeration": "4",
    "review": "approved",
    "reviewer": "the person in the portrait",
    "disclosure": "free",
    "caption_privacy": "checked",
}

CASES = [
    ("complete notes", {}, 0),
    ("missing consent", {"consent": "no"}, 1),
    ("unknown source", {"source": "guessed"}, 1),
    ("empty ownership", {"ownership": ""}, 1),
    ("unknown style", {"style": "unknown"}, 1),
    ("exaggeration out of range", {"exaggeration": "12"}, 1),
    ("approved without reviewer", {"reviewer": ""}, 1),
    ("caption privacy unchecked", {"caption_privacy": "todo"}, 1),
]

passed = 0
for name, patch, expected in CASES:
    notes = {**BASE, **patch}
    problems = audit(notes)
    ok = (len(problems) > 0) == (expected > 0)
    passed += int(ok)
    print(f"{'PASS' if ok else 'FAIL'} {name}: {len(problems)} problem(s)")

print(f"{passed} passed, {len(CASES) - passed} failed")
raise SystemExit(0 if passed == len(CASES) else 1)

実行結果です。

PASS complete notes: 0 problem(s)
PASS missing consent: 1 problem(s)
PASS unknown source: 1 problem(s)
PASS empty ownership: 1 problem(s)
PASS unknown style: 1 problem(s)
PASS exaggeration out of range: 1 problem(s)
PASS approved without reviewer: 1 problem(s)
PASS caption privacy unchecked: 1 problem(s)
8 passed, 0 failed

テストは8件すべて通りました。ここで確認しているのは記録の完全性だけで、似顔絵の品質や本人らしさを保証するものではありません。

運用のコツ

最初の生成前に1回、共有前にもう1回実行します。生成後はメモに実際のスタイルと誇張の値、承認状態を追記します。公開するリポジトリにメモを置く場合は、実名や連絡先などの個人情報を入れず、必要な項目だけを残します。

レビューでは、大きな画面と実際の表示サイズの両方で確認します。サムネイルでは見えない崩れがあり、逆に大きな画面では目立たない違いもあります。1回の修正で止めるのも大切です。修正を繰り返すほど、ブリーフ自体が曖昧だったのか、レビュー担当者の好みが割れているのかが分からなくなります。

無料枠の扱いもメモに残します。今回の確認では one free 1K generation が用意されており、より大きなサイズや追加の実行は任意の有料アップグレードでした。スクリプトは支払いを前提にせず、レビューの手順にも費用はかかりません。セッションを始める前に、無料の範囲で何回試すのかを決めておくと、レビューが予定外の購入に流れにくくなります。

参考: 実際のツールで試す

レビューの対象を確認するために、ai caricature generator の公開ページを見ました。写真または短い文章から似顔絵を作り、8種類のスタイル、誇張の調整、画像編集を備えています。ブラウザだけで完結し、インストールは不要です。無料枠は one free 1K generation で、より大きなサイズや追加実行は任意の有料アップグレードです。本記事のスクリプトとレビュー手順に支払いは不要で、本記事はツール運営者とは関係ありません。

af-homepage.png

まとめ

制作メモの検査は、創作の質を上げる作業ではありません。しかし、同意の有無、入力の権利元、承認者、無料枠の範囲を一度立ち止まって確認するだけで、共有後のトラブルは減らせます。60行ほどのスクリプトでも、チームの判断を残す土台としては十分役立ちます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?