Algorithm & UI/UX
服の明暗を使って色を重ねるブレンドの仕組み
衣服と推定した画素の明るさを取り出し、選択色へ掛け合わせて元画像と混ぜます。柄や陰影を手掛かりに色を変える方法と、黒い服や境界の推定が持つ限界を説明します。
このツールの入力から出力まで
現行コードの確認日:
- 入力
- 服が写った人物写真と色・濃さを指定します。
- 処理
- 複数カテゴリのImageSegmenterで衣服に対応する領域を取り、元の明暗に色を重ねます。
- 出力
- 入力の長辺は最大1500px、出力はJPEG品質0.95です。
まず確認する点:人物全体のマスクをそのまま服のマスクにしない点が要点です。柄、髪、肌との境界に色が漏れていないか見ます。
仕上がりの例
人物の服だけを、青色から紫色に変えた例です。
サンプルにはAIで生成した架空の人物画像を使用しています。
掲載画像はサイトにある既存の公開作例です。保存済みの資料ではAIで作成した架空の人物・手の画像を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。
保存済み検証記録の条件を見る
資料の種類は「ツールの出力画像を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。
- 記録の入力画像
- 1788×2400px (JPEG)
- 記録の出力画像
- 1117×1500px (JPEG)
| 画面の項目 | 記録の値 | 現行コードの初期値・範囲 |
|---|---|---|
| 変更するカラー | #a855f7 | 初期値 #a855f7 |
| 染める濃さ(ブレンド強度) | 100 | 初期値 100 / 範囲 0〜100 |
資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。
実装の確認箇所:src/pages/ai/ima-seg/cloth-recolor/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。
仕組みを読み進めるときは、髪と服のセグメンテーション(目的に合うモデルとカテゴリの選び方)、Canvas APIと画像処理(画像寸法、drawImage、画素と透明度の扱い)が参考になります。
1. テクスチャを維持する「輝度抽出(Luminance)ブレンド」
服の色を変更する際、最も大きな課題は「影やシワをいかに残すか」です。単純に特定の色を重ねる(Overlay)だけでは、立体感が消えてベタ塗りのような不自然な仕上がりになります。
このツールでは、まず元の画像の各ピクセルから輝度(Luminance)を計算します。輝度とは、その点の「明るさの度合い」です。この値を抽出した上で、新しく指定されたカラーと乗算合成を行うことで、元の服の明暗を新しい色の濃淡へ反映します。ただし、選んだ色の明るさによって出力の輝度は変わり、元と完全に同じ明るさを保存する計算ではありません。
衣服の確信度を使って1画素を着色する式です。rgbとtargetはRGBの配列、strengthとconfidenceは0〜1です。実装では衣類の確信度マスク(インデックス4)をコピーした透明度からconfidenceに相当する値を使います。
function recolorCloth(rgb, target, strength, confidence) {
const light = rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114;
const mix = strength * confidence;
return rgb.map((value, channel) =>
value * (1 - mix) + target[channel] * light / 255 * mix);
} 2. MediaPipe Wasmによるマルチクラス・セグメンテーション
「服だけ」を自動で選ぶためには、画像の中から衣服の領域を特定するAI(セグメンテーション)が必要です。本ツールでは、MediaPipeのSelfie Multiclassモデルを採用しています。
この実装のポイントは、サーバーを介さないブラウザ完結型であることです。WebAssembly(Wasm)を活用することで、1枚の画像をピクセル単位で解析し、「背景」「肌」「髪」「衣類」といったカテゴリに分類したマスク配列を高速に生成します。このマスク情報をCanvasのImageData操作に直接結びつけることで、低遅延なプレビューを可能にしています。
3. requestAnimationFrameによるレンダリングの最適化
カラーピッカーやスライダーを動かした際、Canvasの全ピクセル(数百万個)をループ処理して再描画すると、ブラウザのメインスレッドを占有し、UIがカクつく原因になります。
これを防ぐため、本ツールでは requestAnimationFrame を用いた間引き描画(Throttling)を実装しています。変更イベントが連続して発生しても、次の画面更新前に重なった描画要求をまとめます。画素の走査はメインスレッドで行うため、画像の大きさによっては操作が待たされる場合があります。
出力の仕様と確認する点
マスクの大きさは返却されたwidth・heightを参照します。readMaskDataで処理Canvasの寸法へ合わせ、カテゴリは最近傍、確信度は双線形補間で所有配列へコピーします。コピー後にImageSegmenterResult.close()で元のマスク資源を解放し、編集と描画にはコピーを使います。
Selfie Multiclassモデルは6クラスで、衣類のカテゴリと確信度のインデックスは4です。衣類確信度を着色強度へ掛け、境界を連続的に混ぜます。背景や肌を手動で塗り分ける機能はありません。複数の服を別々の色へ指定することもできません。
強さ0では元画像を使い、100でも衣類確信度が1の画素でのみ計算した色へ完全に置き換えます。中間の確信度では元画像と混ぜます。黒い部分は輝度が低いため明るい色を指定しても暗く残ります。白い服・柄物・透ける素材で実物の染色結果を予測する機能ではありません。
入力の長辺は最大1500px、出力はJPEG品質0.95です。袖や襟、髪との境界を確認し、見た目の比較用として使用します。
