Algorithm & UI/UX
人物マスクと背景の色加工:セグメンテーションとポスタリゼーション
人物と背景のマスクをAIで推定し、背景に分類した画素の彩度・明るさ・階調を変えてイラスト風に見せます。新しい風景を生成するAIではなく、元写真の背景の色を加工するツールです。
このツールの入力から出力まで
現行コードの確認日:
- 入力
- 人物写真を選び、背景加工の強さを指定します。
- 処理
- 背景側の彩度と青みを変えて色を段階化し、人物マスクで元の人物を重ね直します。
- 出力
- 入力は長辺1500px以下、出力はJPEG品質0.95です。
まず確認する点:テキストから新しい風景を生成する処理ではありません。元背景の輪郭がどう変わるかと、人物の境界の欠けを見ます。
仕上がりの例
人物を残し、背景をアニメ風に加工した例です。
サンプルにはAIで生成した架空の人物画像を使用しています。
掲載画像はサイトにある既存の公開作例です。保存済みの資料ではAIで作成した架空の人物・手の画像を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。
保存済み検証記録の条件を見る
資料の種類は「ツールの出力画像を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。
- 記録の入力画像
- 1788×2400px (JPEG)
- 記録の出力画像
- 1117×1500px (JPEG)
| 画面の項目 | 記録の値 | 現行コードの初期値・範囲 |
|---|---|---|
| アニメ化の強さ | 50 | 初期値 50 / 範囲 1〜100 |
記録では「この画像で保存へ進む」から完成表示へ進んでいます。初期値と記録値を比べてから、効果を1項目ずつ変えると作用を確認しやすくなります。
資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。
実装の確認箇所:src/pages/ai/ima-seg/anime-bg/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。
仕組みを読み進めるときは、MediaPipeの画像セグメンテーション(人物マスクの寸法、カテゴリと資源解放)、Canvas APIと画像処理(画像寸法、drawImage、画素と透明度の扱い)が参考になります。
1. MediaPipeによる人物セグメンテーション
このツールの最大の特徴は、人物と推定された領域を残し、背景と判断した領域を加工する点にあります。これを可能にしているのが、Googleの「MediaPipe Image Segmenter」を用いたリアルタイムセグメンテーションです。
WASM(WebAssembly)とGPUを活用することで、ブラウザ上でピクセル単位の「カテゴリマスク」を生成。これにより、髪や持ち物の境界を含めて領域を推定し、マスクを使って背景を操作する「レイヤー分離」と同等の処理を単一の画像に対して実行しています。
背景色の階調数と彩度を決める式です。strengthは1〜100で、大きいほど階調が粗く、色が強くなります。
function animeParameters(strength) {
const levels = Math.max(3, 20 - Math.floor(strength / 6));
return {step: 255 / levels, saturation: 1 + strength / 100 * 0.6,
redGreenOffset: 10 + strength / 10, blueOffset: 20 + strength / 5};
} 2. ImageDataを使った背景の階調・彩度調整
アニメ風の「ベタ塗り感」は、背景の色を少ない階調へまとめることで作ります。本ツールではCanvasの filter に加工を任せず、読み出した各画素へ計算を行います。
getImageData で取得した画素配列へ、ポスタリゼーション(階調化)と青み・彩度の計算を1ピクセルずつ適用します。JavaScriptで画素を走査する負荷は残り、特定の端末での速度や安定動作を保証する方式ではありません。
3. requestAnimationFrame による動的プレビュー最適化
「アニメ化の強さ」スライダーを動かす際、膨大なピクセル計算が走ります。UIの反応を損なわないよう、描画処理は requestAnimationFrame (RAF) を用いてブラウザの更新サイクルと同期させています。
実行前の描画予約を取り消して最新の値で予約し直すことで、連続入力による描画の重複を抑えます。実行を開始した画素計算を途中で中止したり、別スレッドへ移したりする仕組みではありません。
出力の仕様と確認する点
マスクの大きさは返却されたwidth・heightを参照します。readMaskDataで処理Canvasの寸法へ合わせ、カテゴリは最近傍補間で所有配列へコピーします。コピー後にImageSegmenterResult.close()で元のマスク資源を解放し、編集と描画にはコピーを使います。
現行のMediaPipe Tasks Vision 0.10.34とselfie_segmenter.tfliteのカテゴリマスクは、人物が0、背景が255です。人物のカテゴリ0を残し、背景のカテゴリ255へ効果を掛けます。人物向けモデルのため、物やペットを必ず残せるわけではありません。
強さを上げると彩度を高め、青成分を赤・緑より多く足し、色を段階化します。線画を新しく描いたり、背景の物を消す処理はないため、元の部屋や看板などの形は残ります。
入力は長辺1500px以下、出力はJPEG品質0.95です。加工後も背景の情報が読めることがあるので、この効果だけで住所や場所を隠せるとは考えず、公開範囲を確認してください。
