はじめに

2026年現在、画像生成AIの急速な普及に伴い、生成された画像に「AIによって作られた」という来歴情報を記録する動きが世界的に活発化しています。具体的には、GoogleのGeminiで生成した画像に表示される「星マーク(可視ロゴ)」、人間には知覚できない周波数信号を埋め込む「SynthID」、改ざん不可能な署名を施す来歴メタデータのオープン規格「C2PA(Content Credentials)」などが挙げられます。

しかし、これら「可視透かし」「不可視透かし」「メタデータ」は技術的に全く異なる仕組みであり、混同されがちです。また、自作のAI生成イラストをSNS等で公開する際に識別IDの付随を避けたいというプライバシー上の動機や、誤って「Made with AI」判定された写真の修正、透かし技術の頑健性(ロバスト性)を検証するセキュリティ研究といった文脈において、これらの一括除去ツールが求められています。

本稿では、これらの各種透かしを一括で検知・除去できる実力派オープンソースツール「Remove-AI-Watermarks」をピックアップします。Windows環境においてパッケージマネージャー「uv」を用いてクリーンに導入する手順から、直感的でプレミアムな操作感をもたらすGradioベースのWeb GUIの構築方法、さらにブラシで塗った領域をピンポイントでインペイント消去する「自由消しゴム」の実装コードまで、詳しく解説します。

1. AI透かしの技術分類とツールの対抗アプローチ

まず前提として、このツールが処理する3つの異なるターゲットと、その処理アプローチについて整理しておきましょう。

ターゲットの種類 代表例 技術的特徴 ツールのアプローチ
可視透かし (Visible Logo) Geminiのキラキラマーク、Doubao/Jimengのテキストマーク 画像の一部に視覚的なロゴやテキストが合成されたもの。 既知のロゴデザインのアルファチャンネル(透過情報)を反転させて差し引く「逆アルファブレンディング」+インペイント処理。
不可視透かし (Invisible) Google DeepMindの「SynthID」、StableSignature、TreeRing 人間の目には見えない微細な周波数変化として、画像データ自体に信号を埋め込む。切り抜きや圧縮にも強い。 ControlNetなどの画像生成AI(SDXL)を用いて、構造を維持したまま画像を再生成(インペイント/img2img)し、埋め込まれた信号を破壊・撹乱する。
来歴メタデータ (Metadata) C2PA規格、EXIF/XMP "Made with AI"タグ、中国TC260 AIGCラベル 画像ファイルのヘッダー領域等に埋め込まれたJSONや証明書等の作成データ。 画像ピクセルには手を加えず、ファイルバイナリから不要なメタデータセグメント(C2PAマニフェスト、EXIFタグなど)を直接ストリップ(削ぎ落とし)する。

2. Windows環境へのスマートな導入手順 (uvを活用)

Pythonプロジェクトの環境構築において、ライブラリの肥大化やパッケージ競合は日常茶飯事です。特に画像処理やGPU推論を含むプロジェクトでは顕著です。今回は、高速かつ軽量なパッケージ管理ツールである「uv」を用いて、極めてクリーンな環境を作成します。

Step 1. プロジェクトの初期化

まず、適当な空の作業用フォルダを用意し、uv init でPythonプロジェクトを初期化します。

mkdir Remove-AI-Watermarks-App
cd Remove-AI-Watermarks-App
uv init

Step 2. プロジェクト名競合の回避 (注意ポイント)

デフォルトでは、フォルダ名に基づいてプロジェクト名が remove-ai-watermarks に設定されます。しかし、この状態のままライブラリの remove-ai-watermarks をインストールしようとすると、「自己参照依存」となりエラーが発生してしまいます。そのため、事前に pyproject.toml を開き、以下のようにプロジェクト名を別名(例: remove-ai-watermarks-app)に変更しておきます。

[project]
name = "remove-ai-watermarks-app" # 重複を防ぐために書き換える
version = "0.1.0"
...

Step 3. 依存ライブラリの追加

以下のコマンドを実行して、透かし除去ライブラリと、今回のGUI構築に用いる Gradio を追加します。uvが自動的にローカルの仮想環境(.venv)を作成し、パッケージをインストールしてくれます。

uv add remove-ai-watermarks gradio

※不可視透かしの拡散モデルによる除去(GPU推論)もフルで活用したい場合は、uv pip install "remove-ai-watermarks[gpu]" も併せて実行しておきます。

3. 操作しやすいGradio WebUI の構築

CLI単体でも十分に強力ですが、結果をビジュアルに確認したり、手動で消去領域を指定したりするためには、直感的なWebインターフェースが不可欠です。以下に示すのは、今回の導入に合わせて開発した webui.py の実装コードです。このコードを実行すると、自動的に空きポートをスキャンしてローカルでWebUIを起動します。

# webui.py からの抜粋:自動ポート検索と起動
import socket
import gradio as gr

def find_free_port(start_port=7860, max_port=7900):
    for port in range(start_port, max_port):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            try:
                s.bind(('127.0.0.1', port))
                return port
            except OSError:
                continue
    raise IOError("使用可能なポートが見つかりませんでした。")

# アプリの起動部
if __name__ == "__main__":
    port = find_free_port()
    print(f"Starting Gradio on port {port}...")
    demo.launch(server_name="127.0.0.1", server_port=port, share=False)

この仕組みにより、他の開発用サーバー(別のGradioやVite等)が稼働していても、ポート競合を起こすことなく快適に並行起動できます。

4. 技術解説:ブラシで塗って消す「自由消しゴム」の仕組み

本WebUIの主要な機能として、画像上の任意のロゴや不要オブジェクトをブラシで塗るだけでインペイント消去できる「自由消しゴム (Region Eraser)」を実装しました。

Remove-AI-Watermarksの region_eraser.erase 関数は、本来 (x, y, width, height) という矩形座標のリスト(boxes)を受け取る設計になっています。しかし、ユーザーが手動で座標を指定するのは極めて面倒です。そこで、Gradioの画像編集ツール(マスク描画)から得られるピクセルデータから、自動で輪郭を抽出し、矩形領域へ変換する仕組みを取り入れました。

マスク画像から消去矩形(Bounding Box)を切り出すコード解説

def run_erase(image_with_mask, backend, cv2_method, dilate):
    img = None
    mask = None
    
    # Gradio 4/5のマスク格納辞書からデータを取り出す
    if isinstance(image_with_mask, dict):
        if "background" in image_with_mask:
            img = image_with_mask["background"]
        if "layers" in image_with_mask and image_with_mask["layers"]:
            mask = image_with_mask["layers"][0] # ユーザーが描いた描画レイヤー
        elif "mask" in image_with_mask:
            mask = image_with_mask["mask"]
            
    if img is None or mask is None:
        return None, "画像またはマスクがありません。"

    # アルファチャンネルから塗られた領域を取得
    if mask.ndim == 3 and mask.shape[2] == 4:
        gray = mask[:, :, 3] # RGBAのA(不透明度)チャンネル
    else:
        gray = cv2.cvtColor(mask, cv2.COLOR_RGB2GRAY)

    # 閾値処理で二値化(塗られた部分を完全な白に)
    _, thresh = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY)
    
    # 輪郭(接続成分)を検出
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    boxes = []
    for cnt in contours:
        x, y, w, h = cv2.boundingRect(cnt)
        if w > 2 and h > 2: # 微小なノイズを除外
            boxes.append((x, y, w, h))
            
    if not boxes:
        return None, "消去領域が検出されませんでした。"

    # 抽出された矩形領域リストをインペイントエンジンに引き渡す
    from remove_ai_watermarks.region_eraser import erase
    bgr_img = cv2.cvtColor(img[:, :, :3], cv2.COLOR_RGB2BGR)
    result_bgr = erase(bgr_img, boxes=boxes, backend=backend, dilate=dilate, cv2_method=cv2_method)
    
    # RGBに戻して出力
    return cv2.cvtColor(result_bgr, cv2.COLOR_BGR2RGB), "消去完了"

このアプローチの強みは、「ユーザーが直感的に塗りつぶした複数の点」を個別の独立した矩形(Bounding Box)として一度に検出し、それぞれに適切なインペイント処理を適用できる点にあります。これにより、画像全体の解像度を維持しながら、ロゴが描かれた局所領域だけを自然に復元できます。

5. 法的・倫理的な位置づけについて

Remove-AI-WatermarksはMITライセンスのオープンソースであり、技術自体は完全に合法です。しかし、悪用の懸念(他人のAI生成物を人間が作ったと偽る行為、意図的に著作権表示を剥ぎ取って再配布する行為、ディープフェイクの来歴を消す行為など)から、海外コミュニティでも議論の対象となっています。

配布元のREADMEには、「自らが所有または生成したアセットのクリーンアップ」「誤検知された写真の修正」「セキュリティおよび透かし強度の研究」などの合法的な利用目的のみを想定していることが明記されています。私たちの導入・検証においても、これらの倫理規定に準拠し、決して他者を欺く目的や法令違反となる使い方は行わないよう厳守してください。

まとめ

「Remove-AI-Watermarks」は、これまでバラバラに行われていた「可視ロゴ補完」「SynthID周波数撹乱」「C2PAマニフェスト削除」という別々のプロセスを、美しく統合したツールです。Windows環境に uv を用いて導入することで、システムの安定性を損なうことなく、最小限の容量で強力な機能を使用できます。

今回構築した Gradio WebUI により、画像解析から一括フォルダ処理、ブラシによる手動修正まで、極めてスムーズに実行できるようになりました。クリエイター自身のプライバシー保護や、AI透かしの研究にぜひ役立ててみてください。