猫の手ツール

AI & Image Processing

瞳の魔法を支える数学とAI。
精密な虹彩レタッチの裏側

AIが瞳の位置を特定するだけでは、リアルな「デカ目」や「カラコン」は作れません。まぶたと瞳の重なりを数学的に制御し、光の屈折をCanvasで再現する実装テクニックを深掘りします。

1. 「まぶたを突き抜けない」オクルージョン・マスク制御

瞳を大きくしたり色を塗ったりする際、単純に円を描画すると、まぶた(上下のアイライン)の上に色が乗ってしまい、非常に不自然な仕上がりになります。これを防ぐため、本ツールではMediaPipeから取得した**「眼球の輪郭(Contour)」をクリッピングパスとして使用**しています。

AIが検知した478点の頂点から特定のアイライン座標を抽出し、ctx.clip()を実行することで、どんなに瞳を大きくしても「まぶたの内側」だけに描画を制限する**オクルージョン(隠蔽)処理**を実現しています。

// まぶたの境界線座標を使用してパスを作成
ctx.save();
ctx.beginPath();

// 独自の輪郭インデックス配列を用いてパスを構築
eyeContourIndices.forEach(idx => {
    const point = landmarks[idx];
    ctx.lineTo(point.x * canvasWidth, point.y * canvasHeight);
});

ctx.closePath();
ctx.clip(); // これにより描画範囲を「眼球内」に限定

// ここに瞳の拡大や着色処理が入ります

ctx.restore();

2. 複層ブレンドモードによる「虹彩の奥行き」再現

カラコンの着色において、単純な半透明塗り(globalAlphaのみ)では、瞳の質感が失われて「のっぺり」してしまいます。本ツールでは、Canvasの**globalCompositeOperationを切り替えながら、2段階の合成**を行っています。

  • Overlay(オーバーレイ): 瞳が持つ元々のハイライト(反射光)やテクスチャを維持したまま、色だけを乗せます。
  • Multiply(乗算): 瞳の縁(フチ)や暗部を強調し、カラコン特有の奥行きと力強さを加えます。

この2つの層を、中心から外側へ広がる「放射状グラデーション(Radial Gradient)」と組み合わせることで、人間の虹彩に近い質感をシミュレートしています。

// 放射状グラデーションによる虹彩表現
const grad = ctx.createRadialGradient(cx, cy, innerRadius, cx, cy, outerRadius);
// 独自のカラーチューニング
grad.addColorStop(0, "transparent"); // 瞳孔部分は抜く
grad.addColorStop(0.5, currentColor);
grad.addColorStop(1, "rgba(0,0,0, // 独自の透明度値 )");

// 複層合成によるリアリティの追求
ctx.globalCompositeOperation = 'overlay'; 
ctx.fillStyle = grad;
ctx.fill();

ctx.globalCompositeOperation = 'multiply';
ctx.globalAlpha = // 独自の重み付け係数;
ctx.fill();

Developer's Note

「デカ目加工」と聞くと派手な印象がありますが、技術的なこだわりは「いかにバレないか」という地味な調整に集約されています。

特に苦労したのは、瞳を大きくする際の再サンプリング(drawImageの計算)です。単に円を大きくするだけだと、周囲の皮膚まで引き伸ばされてしまいます。そこで、AIが検知した瞳の中心点から「元の瞳の半径」だけを精密に抜き出し、それを「ターゲットの半径」へ拡大して描画する計算を行っています。

「WebAssemblyで爆速推論」+「Canvasで職人芸的な合成」という、現代フロントエンドの総力戦のような構成ですが、すべてはお客様の大切な写真を安全に、美しく仕上げるために採用した形です。