猫の手ツール

Algorithm & UI/UX

AIセグメンテーションによる
背景限定ピクセル化のロジック

本ツールは、Googleが提供する「MediaPipe」による機械学習を用いた人物切り抜きと、Canvasの低解像度再サンプリングを組み合わせることで、ブラウザ内のみでリアルタイムな背景加工を実現しています。その中核となる描画パイプラインを解説します。

1. 低コストな「ドット絵」生成アルゴリズム

背景をドット絵(ピクセル化)にするために、複雑なフィルタ演算は使用していません。Canvasの描画特性を利用した「ダウンサンプリング(解像度低下)処理」を採用しています。

具体的には、一度画像を数十分の一の極小サイズに縮小描画し、それを元のサイズへ拡大して描画し直します。この際、ブラウザ標準の補間機能をオフ(imageSmoothingEnabled = false)にすることで、数学的に「正しい」ギザギザのドット感を演出しています。

// 背景をドット化するための描画フロー(概念)
const pixelScale = // 独自のチューニング係数を用いた縮尺率

// 1. 小さなテンポラリCanvasに元画像をギュッと縮小して描画
tempCtx.drawImage(originalImg, 0, 0, w * pixelScale, h * pixelScale);

// 2. メインのCanvasで「補間」を無効化する
ctx.imageSmoothingEnabled = false;

// 3. 小さい画像を元のサイズまで引き伸ばして描画(これでドット絵化が完了)
ctx.drawImage(tempCanvas, 0, 0, smallW, smallH, 0, 0, originalW, originalH);

2. AIマスクを用いた動的なレイヤー合成

本ツールの最大の特徴は「人物はそのままに背景だけを変える」という点です。これを実現するために、以下の3つのレイヤー構造をとっています。

  • Layer 1 (底): 全体をドット化した元画像(背景用)
  • Layer 2 (中): AIによって背景部分を「透明」に加工した人物画像
  • Layer 3 (上): UIや補助ガイドライン

AI(MediaPipe)が生成するセグメンテーションマスクは、「どのピクセルが人物か」をビットマップ形式で提供します。この情報を走査し、背景に該当するピクセルのAlphaチャネルを強制的にゼロ(透明)に書き換えることで、合成用の人物レイヤーを作成しています。

// AIのセグメンテーション結果から人物のみを抽出するハック
const maskArray = segmentationResults.categoryMask.getAsUint8Array();
const imgData = personCtx.getImageData(0, 0, w, h);

// ピクセルデータを走査し、背景判定箇所を透過させる
for (let i = 0; i < maskArray.length; i++) {
    if (maskArray[i] === // 独自の背景識別アルゴリズムによる判定) {
        // 背景とみなされたピクセルのアルファ値を0にする
        imgData.data[i * 4 + 3] = 0; 
    }
}
personCtx.putImageData(imgData, 0, 0);

// 最後に、ドット絵化した背景レイヤーの上にこの人物レイヤーを重ねる
ctx.drawImage(personCanvas, 0, 0);

Developer's Note

このツールを開発する上で最もこだわったのは、「プライバシー」と「体験のスピード」の両立です。

通常、AIによる高精度な画像切り抜きはサーバーサイドで行うのが一般的ですが、それではユーザーの大切な写真を外部へ送信しなければなりません。本ツールではMediaPipeのWASMランタイムを採用し、ブラウザのリソースだけでAIを動かすことで、オフライン環境に近い安全性と、スライダー操作に追従するリアルタイム性を確保しました。

また、実装上の小さな工夫として「画像の左上隅(座標 0, 0)は通常、被写体ではなく背景である」という確率的性質を利用して、AIの出力するセグメンテーションカテゴリから動的に背景IDを特定するロジックを組み込んでいます。これにより、AIモデルの出力仕様に依存しすぎない、堅牢な描画ロジックを実現できました。

☕ 開発ノート

このツールの裏側・仕組み

技術的な仕組みや、安全に処理を行うための工夫などを解説しています。