Algorithm & UI/UX
イラスト資料を加速させる:21点のランドマークから線画を紡ぐアルゴリズム
複雑な「手の形」を、トレース可能な純粋な骨格情報へ。本ツールではAIが検知した3D座標を、クリエイターが最も扱いやすい2Dワイヤーフレームへと変換・再構成しています。その背後にあるCanvas制御とリアルタイム処理の工夫を紐解きます。
1. 接続マトリックスによるワイヤーフレームの再構築
AI(MediaPipe Hand Landmarker)が返すデータは、手の各関節にあたる21個の「点」の集合です。これだけではイラストの資料としては不十分なため、本ツールでは手首から指先までの「骨格の流れ」を定義した独自の接続リスト(HAND_CONNECTIONS)を用いて、Canvas上に一気に線を引いています。
この実装により、単なる点の羅列を「構造体」として可視化することが可能になります。また、描画時には lineCap="round" と lineJoin="round" を指定することで、デジタル特有の硬さを抑えた、ペン入れしやすい滑らかな線画を実現しています。
// 手の構造を定義する接続定義(一部抜粋)
const CONNECTIONS = [
[0, 1], [1, 2], [2, 3], [3, 4], // 親指のライン
[0, 5], [5, 6], [6, 7], [7, 8], // 人差し指のライン
// ここに中指、薬指、小指、手のひらの接続データが入ります
];
function drawSkeleton(ctx, landmarks, color, thickness) {
ctx.strokeStyle = color;
ctx.lineWidth = thickness;
// 構造体を一筆書きのようにレンダリング
CONNECTIONS.forEach(([start, end]) => {
const p1 = landmarks[start];
const p2 = landmarks[end];
// 座標のスケーリングと描画
// ここにCanvasのmoveTo/lineToを用いた計算処理が入ります
});
ctx.stroke();
} 2. requestAnimationFrame による低遅延なプレビュー同期
ユーザーがスライダーで線の太さや透過度を変更した際、一瞬の遅延も感じさせない操作性が求められます。本ツールでは、値を変更するたびに即時描画を行うのではなく、requestAnimationFrame を介した描画リクエスト方式を採用しています。
これにより、ブラウザの更新タイミングに合わせて描画が最適化され、高解像度の画像であってもUIスレッドをブロックすることなく、ヌルヌルとした滑らかなプレビュー更新を可能にしています。
let renderTimer = null;
function requestRender() {
// 既にリクエストがある場合はキャンセルして最新の状態に上書き
if (renderTimer) cancelAnimationFrame(renderTimer);
// 次の描画フレームで実行
renderTimer = requestAnimationFrame(() => {
// ここにCanvasのクリアと全レイヤーの再描画処理が入ります
renderCanvas();
});
}
// 各スライダーの変更イベントでリクエストを投げる
slider.oninput = () => requestRender(); 3. WASMによる完全ローカル処理とプライバシー設計
自撮りした「自分の手」という非常にプライベートな情報を守るため、AIエンジン(Hand Landmarker)はWebAssembly(WASM)技術を用いてユーザーのブラウザ上で直接動作します。
画像データは一滴も外部サーバーへ流れません。この「完全ローカル完結型」の設計により、機密性の高い資料作成や、SNS用の自撮り写真からでも、セキュリティを気にせず一瞬で素材化できるのが最大のメリットです。
Developer's Note
イラストレーターにとって「手」は永遠の課題です。自分の手を撮影して鏡に映したり、デッサン人形をこねくり回したり……そんな苦労を少しでも減らしたいという思いからこのツールを作りました。
こだわったのは、線画だけでなく「関節点」を表示できるオプションです。骨格の重なりやパースが理解しやすくなるよう、スライダーで点の大きさを微調整できるようにしました。また、保存時に「透過PNG」を選択できるようにしたことで、そのままイラストソフトのレイヤーに放り込めるワークフローを重視しています。あなたの創作活動の、良き「猫の手」になれば幸いです。