ブラウザで人物背景を透過する処理は、写真をサーバーへ送らなくても実現できます。選択した画像をブラウザが読み込み、人物セグメンテーションモデルが人物らしさのマスクを作り、そのマスクを Canvas で透明度に変換します。最後に透過 PNG を生成するところまで、同じタブの中で完結します。

この方式はプロフィール写真、登壇資料、サムネイルなど、人物を主題にした画像に向いています。バックエンドの画像処理 API も API Key も不要です。一方で、商品や動物を含むあらゆる画像を正確に切り抜ける方式ではありません。ページが対象を「人物」に限定しているのは、モデルの学習目的と実際の精度を一致させるためです。

先に知っておきたい適用範囲

自動処理に向くのは、人物が画面の中で十分に大きく、輪郭が見え、背景との色や明るさに差がある写真です。正面の顔写真だけに限りませんが、人物が遠い集合写真、暗い室内、強い逆光、細かな葉と髪が重なる構図では誤差が増えます。

Wisly で採用した MediaPipe Selfie Segmentation は、人物と背景を分けるためのモデルです。Google のモデルカードでは、細い指が欠ける場合、ノイズや速い動きで品質が落ちる場合、大きな遮蔽物が苦手な場合が説明されています。複数人の大きさが大きく異なる画像や、カメラからかなり離れた人物も想定外です。

したがって、境界調整のスライダーがあっても、認識されなかった腕や手を後から完全に復元できるわけではありません。調整できるのは、モデルが人物か背景かを迷った境界部分です。モデルが背景と断定した広い領域を、単純な閾値変更だけで正しく戻すことはできません。

ローカル処理のデータ経路

画像を選んでからダウンロードするまでの経路は次のようになります。

  1. ファイル入力から、利用者が選んだ画像をブラウザ内でデコードします。
  2. JavaScript が元画像を Canvas に描画します。
  3. WebAssembly 上の Image Segmenter が人物の信頼度マスクを計算します。
  4. マスクを元画像の大きさに合わせ、人物の透明度として適用します。
  5. 透明、白、または指定色の背景と合成し、PNG Blob を作ります。

画像データを推論サーバーへ送る工程はありません。モデルと実行環境は wisly.dev からダウンロードされ、選択した写真は端末のメモリ内で扱われます。ファイル名や画像内容を API のリクエスト本文に入れる必要もありません。

ただし「ローカル」と「常にオフライン」は別の性質です。初回表示ではページ本体、JavaScript、WebAssembly、モデルを取得するネットワーク接続が必要です。ブラウザがキャッシュを再利用する場合はありますが、確実なオフライン動作には Service Worker とキャッシュ更新設計が必要です。実装していない機能まで含めて「完全オフライン」と表現するのは正確ではありません。

256 × 256 のマスクをどう使うか

MediaPipe の方形 Selfie Segmenter は float16 の 256 × 256 入力を使い、背景をインデックス 0、人物をインデックス 1 とする二つのカテゴリを出力します。モデルカードに記載されたモデルファイルの大きさは約 249 KBです。ブラウザで必要になる実行環境全体はモデル単体より大きいため、「モデルが小さい」ことと「ページで追加取得する全資産が同じ大きさ」であることを混同しない注意が必要です。

出力される信頼度マスクでは、各画素に 0 から 1 に近い値が入ります。値が高いほど人物である可能性が高く、低いほど背景である可能性が高いという意味です。髪、肩、半透明の布、ぼけた輪郭では中間値が多くなります。

実装では、この値をそのまま白黒の二択にせず、一定の幅で滑らかに透明度へ変換します。

低い信頼度   透明
境界付近     半透明で滑らかに接続
高い信頼度   不透明

境界を硬くすると輪郭は明快になりますが、毛先や細い部分が切れやすくなります。柔らかくすると髪を残しやすい反面、元の背景色が縁に残ることがあります。写真ごとに背景と髪の条件が違うため、一つの固定値より小さな調整機能が実用的です。この調整は保存済みのマスクを再合成するだけなので、モデル推論を繰り返す必要はありません。

透過 PNG を作る Canvas 合成

人物マスクが得られたら、元画像用、マスク用、人物用、出力用の Canvas を使って合成します。人物用 Canvas に元画像を描き、destination-in に相当する合成でマスク部分だけを残します。透明背景なら、その人物を空の出力 Canvas に描きます。白や任意色を選んだ場合は、先に背景色を塗ってから人物を重ねます。

PNG を採用する理由は Alpha チャンネルを保持できるからです。JPEG は透明を保存できません。WebP にも透過機能はありますが、資料作成ソフトや一般的な画像編集で扱いやすい出力として PNG は理解しやすい選択です。

大きな写真ではメモリにも注意が必要です。圧縮された JPEG が 10 MBでも、デコード後は幅、高さ、4 色チャンネル分のメモリを使います。さらに複数の Canvas が同時に存在します。Wisly のツールは入力ファイルを 15 MBまでとし、長辺が 4096 pxを超える場合は縮小して処理します。縮小したときは画面にその事実を表示します。

初回だけ待ち時間が長くなる理由

体感時間には推論以外の処理も含まれます。初回は WebAssembly の取得とコンパイル、モデルの読み込み、画像のデコードが必要です。その後に前処理、推論、マスク変換、Canvas 合成、PNG エンコードが続きます。同じページで二枚目を処理するときは初期化済みの Segmenter を再利用できるため、通常は初回より短くなります。

公式資料には参考端末のベンチマークがありますが、あらゆるブラウザで同じ時間になる保証ではありません。端末の性能、空きメモリ、省電力設定、画像寸法によって変わります。そのため、固定の秒数を宣伝するよりも、モデル読み込み中と画像処理中を別の状態として示すほうが誠実です。

Google の Web ガイドは、segment() が同期処理で UI スレッドを一時的に止めることも説明しています。一枚ずつ静止画を処理する用途では短い処理状態を表示する設計が可能です。動画や大量の画像を連続処理するなら、Web Worker へ分離して操作性を守る必要があります。

プライバシーとライセンス

画像を送信しない設計でも、外部スクリプト、ログ、解析イベントに不用意な情報を渡せばプライバシー上の利点は薄れます。モデルとランタイムの版を固定して同一ドメインから配信し、Content Security Policy で通信先を制限し、ファイル名や画像内容をログに記録しないことが重要です。もちろん、ブラウザに秘密の API Key を埋め込む設計も避けます。

依存ライブラリのライセンスも公開前に確認すべき項目です。無料で試せることと、閉じたソースのサイトへ条件なく組み込めることは同じではありません。Wisly は Apache License 2.0 の MediaPipe Tasks Vision と Selfie Segmentation モデルを使い、配信物にライセンスと出典情報を含めています。

実際に人物背景を透過する

無料の人物背景透過ツールでは、JPEG、PNG、WebP の人物写真を選び、端末内で背景を透過できます。境界の柔らかさを調整し、透明背景、白背景、任意色から選んで PNG を保存できます。

精度を上げる最も簡単な方法は、人物が大きく写り、照明が安定し、背景との区別が明確な写真を使うことです。ブラウザ機械学習は、万能さを装うより、対象、データ経路、失敗条件を明確にした小さな機能として提供すると価値が伝わりやすくなります。