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で保存します。細かいドットでは文字や場所の特徴が読み取れることがあります。背景を公開したくない用途では、保存結果を拡大して残る情報を確認してください。
