Algorithm & UI/UX
モザイク処理を劇的に軽くする
「オフスクリーン・キャッシュ」の戦略
ブラウザ上でのリアルタイムなモザイク加工は、高解像度画像になるほど計算コストが跳ね上がります。AIによる座標検知と、Canvas描画の最適化をどのように両立させたのか。その技術的工夫を解説します。
1. 描画負荷を最小化する「モザイク・キャッシュ」
ユーザーが顔の枠を追加・削除するたびに、巨大な元の画像からピクセルデータを計算してモザイクを作るのは非常に非効率です。
本ツールでは、「全画面をモザイク化した状態の隠しCanvas」を一度だけ生成してメモリに保持する戦略をとっています。描画時には、このキャッシュされたモザイク画像から「必要な部分だけを型抜き(Clip)」して転送するため、枠の数が増えてもレンダリング負荷がほぼ一定に保たれます。
// モザイクパターンの生成とキャッシュ管理
function updateMosaicCache() {
if (mosaicCacheCanvas && cachedStrength === state.strength) return;
mosaicCacheCanvas = document.createElement('canvas');
const mCtx = mosaicCacheCanvas.getContext('2d');
// 縮小描画 -> 拡大描画による高速ピクセル化
const tempCanvas = document.createElement('canvas');
// ここに独自のアルゴリズムに基づいたリサイズ計算が入ります
// アンチエイリアスを無効化してモザイクのエッジを立たせる
mCtx.imageSmoothingEnabled = false;
mCtx.drawImage(tempCanvas, 0, 0, /* ...以下、キャッシュへの書き込み処理 */);
cachedStrength = state.strength;
}
2. 楕円アルゴリズムによる「自然な」当たり判定
AIが検出する座標は矩形(四角形)ですが、人間の顔は楕円形に近いため、四角い判定のままでは「枠の角をタップした時に意図せず消えてしまう」といったUXの低下を招きます。
これを解決するため、座標の当たり判定に楕円の方程式を応用しています。中心からの距離を軸ごとの半径で正規化して計算することで、ユーザーが「顔そのもの」を触った時だけ反応する、直感的なインターフェースを実現しました。
// 楕円範囲内かどうかの数学的判定
function isInsideFace(clickX, clickY, box) {
const dx = clickX - box.xCenter;
const dy = clickY - box.yCenter;
// 判定範囲を微調整するための独自のチューニング値
const rx = (box.width * ADJUST_FACTOR) / 2;
const ry = (box.height * ADJUST_FACTOR) / 2;
// 楕円の方程式: (x^2 / a^2) + (y^2 / b^2) <= 1
return (dx * dx) / (rx * rx) + (dy * dy) / (ry * ry) <= 1;
}
3. ベクトル座標管理によるレスポンシブ対応
検知された顔の座標を「ピクセル」ではなく「0.0〜1.0の割合(正規化座標)」で管理しています。
これにより、内部処理用の高解像度データと、画面表示用のプレビューCanvasのサイズが異なっていても、座標の再計算が不要になります。スマホの縦横回転などでCanvasの物理サイズが変わっても、常に同じ位置にモザイクを維持できるメリットがあります。
// 座標の正規化(ベクトル化)
const faceResult = {
// ピクセル座標を画像サイズに対する割合へ変換
xCenter: (rawBbox.originX + rawBbox.width / 2) / imageWidth,
yCenter: (rawBbox.originY + rawBbox.height / 2) / imageHeight,
// ...
};
// 描画時の復元
const drawX = faceResult.xCenter * currentCanvasWidth;
Developer's Note
「AIツール」は便利な反面、プライバシーの懸念が常に付きまといます。 技術者として、MediaPipeのWASMモデルを完全にクライアントサイドで動かすことにこだわったのは、その不安を技術で払拭したかったからです。
また、AIが万能ではないことを前提に、「人間が楽に直せる」仕組みを追求しました。150回以上のポーリングによるAI起動待ちロジックや、iOS特有の保存仕様へのパッチなど、地味ながら「現場で本当に使える」ための泥臭い実装を詰め込んでいます。