猫の手ツール

Algorithm & UI/UX

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

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

このツールの入力から出力まで

現行コードの確認日:

入力
人物を残して周囲だけ粗くしたい写真を入力し、ドットの大きさを変えます。
処理
ImageSegmenterの人物・背景マスクを処理寸法へ合わせ、縮小して再拡大した画像と元画像を画素ごとに切り替えます。
出力
長辺1500px以下へ縮小し、JPEG品質0.95で保存します。

まず確認する点:髪の間や人物の持ち物の境界を拡大します。背景の位置や文字が読めるかどうかは、ドットの大きさによっても変わります。

仕上がりの例

人物を残し、背景だけをドット絵風に加工した例です。

加工前・加工後
左は屋外で集まった人物の写真。右は人物の周囲の背景を粗いドット状にした写真。

サンプルにはAIで生成した架空の人物画像を使用しています。人物と背景の境界は写真によって変わります。

加工前・加工後

左は屋外で集まった人物の写真。右は人物の周囲の背景を粗いドット状にした写真。

掲載画像はサイトにある既存の公開作例です。保存済みの資料ではAIで作成した架空の人物・手の画像を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。

保存済み検証記録の条件を見る

資料の種類は「既存の公開作例」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。

写真に写る人物を残し、周囲の風景やテーブルなどをドット絵風に加工した例です。人物とピクセル化した背景の違いを比較できます。

記録の入力画像
1024×559px (JPEG)
記録の出力画像
1024×559px (JPEG)

この作例には操作値の記録がないため、同じ設定で再現できるとは断定しません。本文の数値は現行の実装仕様です。

資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。

実装の確認箇所:src/pages/ai/ima-seg/bg-pixelate/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。

仕組みを読み進めるときは、MediaPipeの画像セグメンテーション(人物マスクの寸法、カテゴリと資源解放)、Canvas APIと画像処理(画像寸法、drawImage、画素と透明度の扱い)が参考になります。

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

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

具体的には、一度画像を数十分の一の極小サイズに縮小描画し、それを元のサイズへ拡大して描画し直します。この際、ブラウザ標準の補間機能をオフ(imageSmoothingEnabled = false)にすることで、縮小した画素の四角い境界を残します。

背景用の縮小寸法を求める部分です。pixelSizeは4〜120の設定値で、大きくするほど粗い四角になります。

function pixelCanvasSize(width, height, pixelSize) {
  const scale = 1 / Math.max(1, pixelSize);
  return {width: Math.max(1, Math.floor(width * scale)),
    height: Math.max(1, Math.floor(height * scale))};
}

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

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

  • Layer 1 (底): 全体をドット化した元画像(背景用)
  • Layer 2 (中): AIによって背景部分を「透明」に加工した人物画像
  • 画面上のUI: 設定操作に使う部分で、保存画像のレイヤーには含まれません。

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

出力の仕様と確認する点

マスクの大きさは返却されたwidth・heightを参照します。readMaskDataで処理Canvasの寸法へ合わせ、カテゴリは最近傍補間で所有配列へコピーします。コピー後にImageSegmenterResult.close()で元のマスク資源を解放し、編集と描画にはコピーを使います。

全体を縮小・再拡大した画像の上へ、人物として残した画素を重ねます。背景の色数を固定パレットへ減らす処理ではないので、昔のゲームと同じ色数になるわけではありません。

現行のMediaPipe Tasks Vision 0.10.34とselfie_segmenter.tfliteのカテゴリマスクは、人物が0、背景が255です。背景のカテゴリ255だけへモザイクを適用します。髪の間や手に持った物は、モデルの推定によって人物から欠けることがあります。

長辺1500px以下へ縮小し、JPEG品質0.95で保存します。細かいドットでは文字や場所の特徴が読み取れることがあります。背景を公開したくない用途では、保存結果を拡大して残る情報を確認してください。