猫の手ツール

Algorithm & UI/UX

AI手形風スタンプ:21点の座標から輪郭を描く技法

手の21点のランドマークを使い、手のひらの多角形と太い指の線を描いてスタンプ風の形にします。写真の輪郭や指紋を直接切り抜く処理ではなく、推定された関節の位置から形を組み立てます。

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

現行コードの確認日:

入力
手のひらが見える画像と線色・太さ・関節表示・元画像の濃さを指定します。
処理
HandLandmarkerの手の点を結び、手形に見える輪郭と関節をCanvasへ描きます。
出力
背景が透明ならPNG、色付きならJPEG品質0.95で保存します。

まず確認する点:写真から輪郭を精密に測量する処理ではありません。見えない指や重なった指で点がずれ、実寸の手形や生体認証には使えません。

仕上がりの例

手の写真から、ピンク色の手形画像を作った例です。

加工前・加工後
左は布の上に置かれた小さな手の写真。右はピンク色の手形として切り出した画像。

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

加工前・加工後

左は布の上に置かれた小さな手の写真。右はピンク色の手形として切り出した画像。

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

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

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

記録の入力画像
1254×1254px (JPEG)
記録の出力画像
1254×1254px (PNG)
保存済み記録の主な操作・出力条件
画面の項目記録の値現行コードの初期値・範囲
線の色#a855f7初期値 #a855f7
手形のふっくら感40初期値 40 / 範囲 10〜100
インクのかすれ具合0初期値 0 / 範囲 0〜80
元の写真を表示(透かし)0初期値 0 / 範囲 0〜100

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

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

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

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

1. ランドマーク補間による「ふっくら」シルエット生成

MediaPipe Hand Landmarkerが返す21点の座標はあくまで「点」です。これをそのまま繋いでも線画にしかなりません。本ツールでは、手首と各指の付け根を結ぶ特定のインデックスを用いて「手のひら」のポリゴンを動的に生成しています。

さらに、Canvasの lineCap="round" と lineWidth を組み合わせた「ストローク・フィル」手法を適用。座標間の距離に基づいた独自の太さ設定を行うことで、指の線や手のひらの縁を丸く描きます。赤ちゃんの指の太さを実測して再現する処理ではありません。

かすれは、描画済みのImageDataの透明度を確率で0にする処理です。amountは0〜80の設定値を渡します。元の写真ではなく、手形専用Canvasの画素に適用します。

function addInkGaps(imageData, amount) {
  const data = imageData.data;
  for (let i = 3; i < data.length; i += 4) {
    if (data[i] > 0 && Math.random() < amount / 100) data[i] = 0;
  }
}

2. 画素の透明度を使ったインクのかすれ

スタンプらしい「インクのかすれ」を表現する場合、通常はSVGフィルタやCanvasの filter プロパティを使用します。しかし、高解像度画像に対してこれらの処理を行うと、モバイル環境では画像サイズやブラウザの実装によって負荷が大きくなる場合があります。

この問題を解決するため、本ツールでは getImageData で取得した生ピクセルデータに対し、直接アルファチャンネルを操作する軽量なノイズアルゴリズムを実装しました。ランダムな透過処理を全ピクセルに適用することで、インクが抜けたような質感を付けます。乱数を使うので再描画ごとに抜ける位置は変わり、画素の走査にも処理時間がかかります。

3. ブラウザ完結型 HEIC / WebAssembly 処理系

iPhoneで撮影された写真の多くは HEIC 形式です。HEICの直接読込に対応しない環境にも対応するため、本ツールでは heic2any を動的インポートし、クライアントサイドで JPEG へ変換しています。

手の位置はAIで推定し、スタンプの描画はCanvasで行います。選んだ写真の処理は端末内で行いますが、ページやライブラリ、AIモデルを読み込む通信は必要です。

出力の仕様と確認する点

太さは10〜100の描画幅を指定します。手のひらの丸みはランドマーク間の距離から曲線を作りますが、指の外形を測定した値ではないため、実際の手形の保存や実寸記録とは区別してください。

最大4本の手を検出し、入力は長辺1500px以下に縮小します。指が重なる、握っている、写真がぼけている場合は推定が崩れることがあります。開いた手がはっきり写った写真で線の位置を確認します。

背景が透明ならPNG、色付きならJPEG品質0.95で保存します。元写真の表示を0より上げると写真も合成されるため、手形だけの透明素材が必要な場合は元写真の表示を0にします。

制作時に確かめたこと