猫の手ツール

Algorithm & UI/UX

AIが描く理想の曲線。
小顔補正を支えるグリッドワープの数学

AIが顔を検知するだけでは不自然な「加工感」が出てしまいます。本ツールがどのようにして、顔付近の移動量を徐々に変えながら写真を変形するのか、その裏側の数学的アルゴリズムを公開します。

このツールの入力から出力まで

現行コードの確認日:

入力
人物写真を選び、補正の強さを0から少しずつ上げます。
処理
顔周囲を30×30のセルへ分け、ランドマークを基準に顔の中心方向へ各セルの描画位置をずらします。
出力
出力はJPEG品質0.9です。

まず確認する点:セルの画素を動かすため背景も歪む場合があります。輪郭の変化と背景の不連続を別々に確認すると、自然に見える範囲を判断できます。

仕上がりの例

顔の輪郭を、少しシャープに見せた例です。

加工前・加工後
左は屋外で自撮りした人物の写真。右は顔の輪郭を調整した同じ人物の写真。

サンプルにはAIで生成した架空の人物画像を使用しています。

加工前・加工後

左は屋外で自撮りした人物の写真。右は顔の輪郭を調整した同じ人物の写真。

掲載画像はサイトにある既存の公開作例です。保存済みの資料ではAIで作成した架空の人物・手の画像を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。

保存済み検証記録の条件を見る

資料の種類は「ツールの出力画像を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。

記録の入力画像
1788×2400px (JPEG)
記録の出力画像
1117×1500px (JPEG)
保存済み記録の主な操作・出力条件
画面の項目記録の値現行コードの初期値・範囲
小顔・シャープ強度50初期値 50 / 範囲 0〜100

記録では「この画像で保存へ進む」から完成表示へ進んでいます。初期値と記録値を比べてから、効果を1項目ずつ変えると作用を確認しやすくなります。

資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。

実装の確認箇所:src/pages/ai/face-lan/face-slim/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。

仕組みを読み進めるときは、MediaPipeの顔ランドマーク(顔の点を使う描画と変形)、Canvas APIと画像処理(画像寸法、drawImage、画素と透明度の扱い)が参考になります。

1. サイン関数(正弦波)を用いた非線形ワープアルゴリズム

小顔補正において、画像を単に内側へ押し込むだけでは、アゴのラインが尖りすぎたり、頬が不自然に凹んだりします。本ツールでは、垂直方向の変形強度を制御するためにサイン関数(Math.sin)を採用しています。

アゴの下から耳の付け根までの範囲を 0 から π と定義し、その中央部で最も変形が強く、端にいくほど滑らかに減衰する「非線形な重み付け」を行うことで、変形の境界で移動量が急に変わりにくいようにしています。

縦方向の重みを計算する部分です。y・top・bottomは0〜1の正規化座標で、範囲の中央で強く、上下端で0になる値を返します。

function verticalWeight(y, top, bottom) {
  if (bottom <= top || y <= top || y >= bottom) return 0;
  return Math.sin(Math.PI * (y - top) / (bottom - top));
}

2. 30x30グリッドメッシュによる局所歪み制御

画像全体を一度に変形させると、計算コストが高くなるだけでなく、関係のない背景まで大きく歪んでしまいます。本ツールでは、顔周辺の領域を30x30の細かいグリッド(メッシュ)に分割して処理しています。

Canvasの drawImage を活用し、各グリッドセルごとに計算された「移動後の座標」へ断片的に転送することで、変形が必要な「顔の周辺」を小さな矩形単位で移動しています。顔と背景を別々に分離しているわけではありません。輪郭に近い背景の線や髪も一緒に動くことがあり、強い補正ではグリッドの境界が見える場合があります。

3. 必要になった時点で行うAIの初期化

AIモデルの読み込みには追加の通信と初期化が必要です。本ツールでは、「ユーザーが画像をアップロードした瞬間」に初めてエンジンのダウンロードと初期化を開始する戦略をとっています。

初期表示とAI読込のタイミングを分ける構成です。ただし画像選択後にはモデルの読込を待つ必要があり、表示速度の改善量はこの解説では測定していません。

出力の仕様と確認する点

顔周囲の矩形を30×30に区切り、顔の中心へ向かって各セルの描画位置をずらします。強さ0では補正せず、100では移動量の係数が0.13になります。これを顔幅や上下位置に応じた重みと掛け合わせます。

最大5人の検出設定で、入力は長辺1500px以下に縮小します。出力はJPEG品質0.9です。横顔や重なった顔では期待と異なる領域が動くため、低い強さから変化を確認してください。

元写真の顔の輪郭を画素の移動で変える加工です。立体形状の計測や、実際の体形・美容施術の結果を予測する機能ではありません。

制作時に確かめたこと