猫の手ツール

Algorithm & UI/UX

多重レイヤー合成による「物理的」ブラーの実装

カメラのシャッター速度を遅くして被写体を追う「流し撮り」。この物理現象をWebブラウザ上で再現するため、高度な被写体分離AIとCanvas 2D APIを組み合わせた軽量な描画パイプラインを構築しました。

1. 反復合成によるモーションブラー・アルゴリズム

通常の「ぼかし(Blur)」フィルタは全方向に平均化されますが、流し撮りの質感を出すには「水平方向のみ」に光を流す必要があります。

本ツールでは、背景レイヤーに対して画像を水平方向に少しずつずらしながら複数回重ね描きする「多重レイヤー合成」を採用しています。各レイヤーの不透明度(globalAlpha)を反復回数に応じて最適化することで、GPU負荷を抑えつつ、カメラの露光時間をシミュレートした滑らかな引きボケを実現しました。

// 背景レイヤーに対する水平方向の多重合成
function applyMotionEffect(bgCtx, sourceImg, strength) {
    const steps = // チューニングされた反復回数;
    const totalShift = strength * // 画面解像度に応じた係数;
    
    bgCtx.globalCompositeOperation = 'source-over';
    for (let i = 0; i < steps; i++) {
        // ここに水平方向のオフセット計算ロジックが入ります
        const offset = (i - steps / 2) * (totalShift / steps);
        
        bgCtx.globalAlpha = 1 / steps; 
        bgCtx.drawImage(sourceImg, offset, 0);
    }
    bgCtx.globalAlpha = 1.0;
}

2. Edge AIを活用したピクセル単位の領域分離

背景だけにブラーをかけ、被写体をクッキリ残すためには「どこが人間か」を瞬時に判断する必要があります。本ツールでは Googleの MediaPipe を採用し、WebAssembly (Wasm) 上で推論を実行しています。

サーバーに画像を送らず、ユーザーの手元のデバイス(Edge)でピクセルごとに「人間か背景か」のマスクを生成します。このマスク情報を Canvas の destination-in 合成モードと組み合わせることで、複雑な境界線を持つ人物も高速かつ非破壊的に切り出すことが可能になっています。

// AIによるセグメンテーションマスクの抽出(擬似コード)
async function processSegment(offscreenCanvas) {
    const results = imageSegmenter.segment(offscreenCanvas);
    const maskArray = results.categoryMask.getAsUint8Array();
    
    // カテゴリIDに基づいて前景/背景を分離
    for (let i = 0; i < maskArray.length; i++) {
        // ここにピクセルデータの透明度書き換え処理が入ります
        // 人物領域のみを不透明にするマスクを生成
    }
    maskCtx.putImageData(maskImgData, 0, 0);
}

3. requestAnimationFrame によるUIスレッドの保護

スライダーを動かした際にリアルタイムでブラーを更新すると、計算負荷によって画面がフリーズするリスクがあります。

これを防ぐため、描画要求をキューイングし、ブラウザの描画更新タイミング(通常60fps)に合わせて実行する requestAnimationFrame (RAF) 制御を導入しました。連続したイベントが発生しても「次のフレーム」で一度だけ描画を行うため、モバイル端末でもカクつきのないスムーズな操作体験を提供しています。

Developer's Note

「いかにしてWebサイト上のツールで、プロのレタッチのような質感を出せるか」にこだわりました。単に背景を横に引き伸ばすだけでは、端の部分に隙間ができてしまいます。内部的には、指定されたブラー強度よりもわずかに広い領域をサンプリングし、中央に収束させることで、写真の端まで自然にブラーが繋がるよう調整しています。

また、プライバシーへの配慮として、MediaPipeのモデル自体も自ドメイン内の /models/ から直接配信し、外部サーバーへのリクエストを極限まで排除した点も、技術的なこだわりの一つです。