猫の手ツール

Algorithm & UI/UX

AI背景透過と手動補正を
支える「マスクレイヤー」戦略

本ツールは、GoogleのMediaPipeを用いた最新のAIセグメンテーションと、Canvas APIによる伝統的な画像合成を組み合わせた「ハイブリッド型」の構成をとっています。AIの限界を人間がカバーするための、実装の工夫を紐解きます。

1. マスクキャンバスによる非破壊的な手動補正

AIが切り抜きに失敗した際、ユーザーが指でなぞって「消去」や「復元」を行えるようにするため、**「表示状態を管理する専用のマスク用Canvas」**を裏側に持っています。

元画像そのものを加工するのではなく、白黒のマスクデータ(白=見える、透明=見えない)を介して元画像をくり抜く(destination-in)手法を採用しました。これにより、一度消した部分も「復元ブラシ」で元のピクセルデータを完全に再表示させることが可能になります。

// 表示内容を決定するレンダリングロジックの核心
function renderCanvas() {
    // 1. 元画像を一時的なCanvasに描画
    tCtx.drawImage(originalImgObj, 0, 0, w, h);
    
    // 2. マスク情報を重ねて「重なっている部分だけ」を抽出
    tCtx.globalCompositeOperation = 'destination-in';
    tCtx.drawImage(maskCanvas, 0, 0, w, h);
    
    // 3. 最終的な表示用Canvasに合成結果を出力
    ctx.globalCompositeOperation = 'source-over';
    ctx.drawImage(tempCanvas, 0, 0, w, h);
}

2. 動的な背景カテゴリの自動特定アルゴリズム

MediaPipeのセグメンテーションモデルは、画像内の各ピクセルにカテゴリIDを割り当てます。しかし、どのIDが「背景」で、どのIDが「人物(前景)」なのかは画像によって変動する可能性があります。

本ツールでは、**「画像の端(左上隅)のピクセルは、高い確率で背景である」**という仮定に基づくサンプリング手法を用いています。AI処理の直後に(0, 0)座標のカテゴリIDを取得し、それを背景の基準値として全体を走査することで、事前のラベル定義に依存しない柔軟な透過処理を実現しています。

// マスクデータの生成と背景特定
const maskArray = results.categoryMask.getAsUint8Array();
const bgCategory = maskArray[// 独自のサンプリング位置による判定];

for (let i = 0; i < maskArray.length; i++) {
    const isForeground = maskArray[i] !== bgCategory;
    if (isForeground) {
        // ここに人物部分を白(不透明)としてマークする処理が入ります
    } else {
        // ここに背景部分を透明としてマークする処理が入ります
    }
}

3. ブラウザ内完結(Edge AI)によるプライバシーと速度の両立

一般的な背景透過サービスは画像をサーバーに送信して処理しますが、本ツールは**WebAssembly(WASM)を活用したエッジ処理**を行っています。

一度数メガバイトのAIモデルをロードしてしまえば、その後は1ピクセルも外部に送信することなく、クライアントサイドのGPUを活用して高速に推論を実行します。これはユーザーのプライバシー保護に加え、ネットワーク遅延をゼロにするというUX上の大きなメリットを生んでいます。

// AIエンジンの初期化(機密パスを除外した抽象コード)
const vision = await FilesetResolver.forVisionTasks("DUMMY_WASM_PATH");
imageSegmenter = await ImageSegmenter.createFromOptions(vision, {
    baseOptions: { 
        modelAssetPath: "DUMMY_MODEL_PATH", 
        delegate: "GPU" // ハードウェア加速を利用
    },
    runningMode: "IMAGE",
    // 独自のセグメンテーション設定
});

Developer's Note

開発において最も腐心したのは、**「AIの確からしさ」と「人間の意志」をどうスムーズに繋ぐか**という点です。

AIは驚くほど高性能ですが、どうしても髪の毛の一房や、持っている小道具の境界線を間違えることがあります。そこで、globalCompositeOperationdestination-out(消しゴム)とsource-over(復元)をブラシ操作に割り当て、ユーザーがストレスなく「直せる」UIを追求しました。

また、Canvasの座標変換において、Retinaディスプレイ等の高解像度環境でもブラシの軌跡がずれないよう、getBoundingClientRectとCanvasの解像度比率をリアルタイムに計算して補正する処理を入れています。地味な部分ですが、この「なぞった通りに消える」という直感的な手触りこそがツールの価値だと信じています。