8_3_1 姿勢検出(1人)

手順としては、前のcoco-ssdと同様、[ファイルを選択]ボタンのクリックで画像ファイルを選択し、それをJavaScriptのイメージデータに変換します。そしてそれをposenetに渡します。

// PoseNetを読み込み、イメージの姿勢検出を実行
posenet.load().then((net) => {
    return net.estimateSinglePose(imageData);
}).then((pose) => {
    // 各部位を描画する
    drawParts(context, pose);
});

posenetのestimateSinglePose()は1人の姿勢検出に使用します。このメソッドは配列を含むオブジェクトを返すので、ここではそれ(pose)を、キャンバスのコンテキストとともに、drawParts()関数に渡しています。

poseオブジェクトはkeypointsプロパティを持っています。keypointsは配列で、要素として、部位名(part)とその部位のx位置(x)、y位置(y)をプロパティに持つオブジェクトを含んでいます。

pose.keypoints[{
    position.x // x位置
    position.y // y位置
    part // 部位名
}, ...]

drawParts()関数では、渡されたコンテキストとpose.keypointsを使って、キャンバス画像の上に丸と線を描きます。

// 頭部と上半身、下半身の部位を色別に丸で描き、左右別に線で結ぶ
const drawParts = (ctx, pose) => {
    const points = pose.keypoints;
    // 円の半径
    const radius = 7;

    // pose.keypoints配列にあるオブジェクトの情報を元に部位を円で描く
    for (let i = 0; i < points.length; i++) {
        // x位置
        const xpos = points[i].position.x;
        // y位置
        const ypos = points[i].position.y;
        // 部位の名前
        const part = points[i].part;
        // 頭部と上半身、下半身で色を分ける
        if (part === 'nose' || part === 'leftEye' || part === 'rightEye' || part === 'leftEar' || part === 'rightEar') {
            ctx.fillStyle = "lightgreen";
        }
        else if (part === 'leftShoulder' || part === 'rightShoulder' || part === 'leftElbow' || part === 'rightElbow' || part === 'leftWrist' || part === 'rightWrist') {
            ctx.fillStyle = "red";
        }
        else {
            ctx.fillStyle = "blue";
        }
        // 円で塗る
        ctx.beginPath();
        ctx.arc(xpos, ypos, radius, 0, Math.PI * 2);
        ctx.fill();
    }

    // 上半身、左右別に部位を線で結ぶ
    ctx.beginPath();
    ctx.strokeStyle = 'red';
    ctx.lineWidth = 4;
    // leftSholder5 - leftElbow7 - leftWrist9
    ctx.moveTo(points[5].position.x, points[5].position.y);
    ctx.lineTo(points[7].position.x, points[7].position.y);
    ctx.lineTo(points[9].position.x, points[9].position.y);
    // rightSholder6 - rightElbow8 - rightWrist10
    ctx.moveTo(points[6].position.x, points[6].position.y);
    ctx.lineTo(points[8].position.x, points[8].position.y);
    ctx.lineTo(points[10].position.x, points[10].position.y);
    // 線を描く
    ctx.stroke();

    // 下半身、左右別に部位を線で結ぶ
    ctx.beginPath();
    ctx.strokeStyle = 'blue';
    // leftHip11 - leftKnee13 - leftAnkle15
    ctx.moveTo(points[11].position.x, points[11].position.y);
    ctx.lineTo(points[13].position.x, points[13].position.y);
    ctx.lineTo(points[15].position.x, points[15].position.y);
    // rightHip12 - rightKnee14 - rightAnkle16
    ctx.moveTo(points[12].position.x, points[12].position.y);
    ctx.lineTo(points[14].position.x, points[14].position.y);
    ctx.lineTo(points[16].position.x, points[16].position.y);
    ctx.stroke();
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA