ロード中

トップへ(mam-mam.net/)

WEBサイトでカメラ(WebCam)画像から姿勢のランドマークを検出して表示する ~Google MediaPipe/pose

WEBサイトでカメラ(WebCam)画像から「Google MediaPipe/pose.js」を使用して姿勢のランドマークを検出して表示します

カメラ使用を許可してしばらくすると、カメラ映像が表示されます

カメラに全身を映してください。ランドマークを推定表示します。

ソースコード



<!DOCTYPE html>
<html lang="ja">
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=0.5, maximum-scale=2.0,user-scalable=yes">
  <script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@mediapipe/control_utils/control_utils.js" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@mediapipe/drawing_utils/drawing_utils.js" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@mediapipe/pose@0.2/pose.js" crossorigin="anonymous"></script>

  <script type="module">
    let video,can,ctx;
    window.addEventListener('load', async function(event){
      video = document.querySelector('.video');
      can = document.querySelector('.can');
      ctx = can.getContext('2d');

      const pose = new Pose({locateFile: function(file){
        return `https://cdn.jsdelivr.net/npm/@mediapipe/pose@0.2/${file}`;
      }});
      pose.setOptions({
        upperBodyOnly: false,
        smoothLandmarks: true,
        minDetectionConfidence: 0.5,
        minTrackingConfidence: 0.5
      });
      pose.onResults(onResults);

      const camera = new Camera(video, {
        onFrame: async function(){
          await pose.send({image: video});
        },
        width: 640,
        height: 480
      });
      camera.start();
    });

    function onResults(results) {
      ctx.save();
      ctx.clearRect(0, 0, can.width, can.height);
      ctx.drawImage(results.image, 0, 0, can.width, can.height);
      //線を描く
      drawConnectors(ctx, results.poseLandmarks, POSE_CONNECTIONS, {color:'#00F', lineWidth:2});
      //ランドマークを描く
      drawLandmarks(ctx, results.poseLandmarks, {color:'#F00', lineWidth:0, fillColor:'#800', radius:3});
      ctx.restore();
    }
  </script>
</head>
<body>
  <div class="container">
    <video class="video" style="display:none;"></video>
    <canvas class="can" width="640" height="480" style="transform:scale(-1,1);width:90%;max-width:640px;height:auto;"></canvas>
  </div>
</body>
</html>

ランドマークの戻り値について

onResults関数での引数「results.poseLandmarks」配列は以下の値が入っているようです。

poseLandmarks[0~32].x画像の幅に対するランドマークのX座標(0.0から1.0の範囲)
poseLandmarks[0~32].y画像の高さに対するランドマークのY座標(0.0から1.0の範囲)
poseLandmarks[0~32].z深度情報。腰の中点を原点として、値が小さいほどカメラに近くなります(全身モードでのみ予測)
poseLandmarks[0~32].visibilityランドマークが画像内でどれだけ見えているかの確率(0.0から1.0の範囲)

poseLandmarks[0]NOSE (鼻)
poseLandmarks[1]LEFT_EYE_INNER (左目の内側)
poseLandmarks[2]LEFT_EYE (左目)
poseLandmarks[3]LEFT_EYE_OUTER (左目の外側)
poseLandmarks[4]RIGHT_EYE_INNER (右目の内側)
poseLandmarks[5]RIGHT_EYE (右目)
poseLandmarks[6]RIGHT_EYE_OUTER (右目の外側)
poseLandmarks[7]LEFT_EAR (左耳)
poseLandmarks[8]RIGHT_EAR (右耳)
poseLandmarks[9]MOUTH_LEFT (口の左側)
poseLandmarks[10]MOUTH_RIGHT (口の右側)
poseLandmarks[11]LEFT_SHOULDER (左肩)
poseLandmarks[12]RIGHT_SHOULDER (右肩)
poseLandmarks[13]LEFT_ELBOW (左肘)
poseLandmarks[14]RIGHT_ELBOW (右肘)
poseLandmarks[15]LEFT_WRIST (左手首)
poseLandmarks[16]RIGHT_WRIST (右手首)
poseLandmarks[17]LEFT_PINKY (左小指)
poseLandmarks[18]RIGHT_PINKY (右小指)
poseLandmarks[19]LEFT_INDEX (左人差し指)
poseLandmarks[20]RIGHT_INDEX (右人差し指)
poseLandmarks[21]LEFT_THUMB (左親指)
poseLandmarks[22]RIGHT_THUMB (右親指)
poseLandmarks[23]LEFT_HIP (左腰)
poseLandmarks[24]RIGHT_HIP (右腰)
poseLandmarks[25]LEFT_KNEE (左膝)
poseLandmarks[26]RIGHT_KNEE (右膝)
poseLandmarks[27]LEFT_ANKLE (左足首)
poseLandmarks[28]RIGHT_ANKLE (右足首)
poseLandmarks[29]LEFT_HEEL (左かかと)
poseLandmarks[30]RIGHT_HEEL (右かかと)
poseLandmarks[31]LEFT_FOOT_INDEX (左足の人差し指)
poseLandmarks[32]RIGHT_FOOT_INDEX (右足の人差し指)