ML5.pose

def setup
  createCanvas(320, 240)
  @video = createCapture(VIDEO)
  @results = []
  @video.elt.onloadeddata = proc {
    # キャンバスに対する縮小率を計算
    # (ロードが完了するまで videoサイズは不定)
    @sx = width / @video.width
    @sy = height / @video.height
    # p @sx, @sy
    ML5.pose(@video, @results)
    @video.hide
  }
end

def draw
  background(220)
  image(@video, 0, 0, width, height)

  scale(@sx, @sy) if @sx and @sy   # 検出座標をキャンバスサイズに一致させる
  @results.each do |bodies|
    bodies.each do |body|
      v = body.pose

      # 顔
      fill(255, 255, 255)
      ellipse(v.leftEye.x,  v.leftEye.y,  15, 15)
      ellipse(v.rightEye.x, v.rightEye.y, 15, 15)
      fill(0, 0, 0)
      ellipse(v.leftEye.x,  v.leftEye.y,  10, 10)
      ellipse(v.rightEye.x, v.rightEye.y, 10, 10)
      noStroke
      fill(255, 0, 0)
      ellipse(v.nose.x,     v.nose.y,     15, 15)
      ellipse(v.leftEar.x,  v.leftEar.y,  10, 10)
      ellipse(v.rightEar.x, v.rightEar.y, 10, 10)

      fill(0, 255, 0)
      # 左
      ellipse(v.leftShoulder.x,  v.leftShoulder.y,  10, 10)
      ellipse(v.leftElbow.x,     v.leftElbow.y,     10, 10)
      ellipse(v.leftWrist.x,     v.leftWrist.y,     10, 10)
      ellipse(v.leftHip.x,       v.leftHip.y,       10, 10)
      ellipse(v.leftKnee.x,      v.leftKnee.y,      10, 10)
      ellipse(v.leftAnkle.x,     v.leftAnkle.y,     10, 10)
      # 右
      ellipse(v.rightShoulder.x, v.rightShoulder.y, 10, 10)
      ellipse(v.rightElbow.x,    v.rightElbow.y,    10, 10)
      ellipse(v.rightWrist.x,    v.rightWrist.y,    10, 10)
      ellipse(v.rightHip.x,      v.rightHip.y,      10, 10)
      ellipse(v.rightKnee.x,     v.rightKnee.y,     10, 10)
      ellipse(v.rightAnkle.x,    v.rightAnkle.y,    10, 10)

      stroke(255, 255, 255)
      strokeWeight(4)
      # 肩~肱~手首(左)
      line(v.leftShoulder.x,   v.leftShoulder.y,  v.leftElbow.x,   v.leftElbow.y)
      line(v.leftElbow.x,      v.leftElbow.y,     v.leftWrist.x,   v.leftWrist.y)
      # 肩~肱~手首(右)
      line(v.rightShoulder.x,  v.rightShoulder.y, v.rightElbow.x,  v.rightElbow.y)
      line(v.rightElbow.x,     v.rightElbow.y,    v.rightWrist.x,  v.rightWrist.y)
      # 尻~膝~足首(左)
      line(v.leftHip.x,        v.leftHip.y,       v.leftKnee.x,    v.leftKnee.y)
      line(v.leftKnee.x,       v.leftKnee.y,      v.leftAnkle.x,   v.leftAnkle.y)
      # 尻~膝~足首(右)
      line(v.rightHip.x,       v.rightHip.y,      v.rightKnee.x,   v.rightKnee.y)
      line(v.rightKnee.x,      v.rightKnee.y,     v.rightAnkle.x,  v.rightAnkle.y)
      # 胴体(両肩~両尻)
      quad(v.leftShoulder.x,   v.leftShoulder.y,
           v.rightShoulder.x,  v.rightShoulder.y,
           v.leftHip.x,        v.leftHip.y,
           v.rightHip.x,       v.rightHip.y)
    end
  end
end

ml5.jsリファレンス(参考情報)

[ml5.js] PoseNet

概要

カメラ映像からリアルタイムに体の姿勢を検出します。

書式

ML5.pose(video, results)

引数

引数名内容備考オプションデフォルト値
videoカメラ映像p5.Element
results検出結果をセットする配列後述の備考の記載を参照

戻値

なし

備考

・ML5.poseメソッドは setupメソッドで使用してください。
 その後、カメラ画像に対象が検出されるたびに
 配列「results」にデータがセットされるので、その内容を drawメソッドで処理してください。

・配列「results」には下記のようなデータ構造の検出結果がセットされます。

  [                                            # 検出された人数分の要素(ハッシュ)を持つ配列
    {                                          # 1人目
      pose: {
        keypoints: [                           # ポイント(17ヶ所)
          {
            position: { x: x0, y: y0 },        # ポイント 0
            score: r,                          # 信頼度
            part: name                         # 部位名
          },
          {
            position: { x: x1, y: y1 },        # ポイント 1
            score: r,                          # 信頼度
            part: name                         # 部位名
          },
          ...
          ...
          ...
          {
            position: { x: x16, y: y16 },      # ポイント16
            score: r,                          # 信頼度
            part: name                         # 部位名
          },
        ],
        nose:          { x: x , y: y, confidence: r },   # ポイント(鼻)
        leftEye:       { x: x , y: y, confidence: r },   # ポイント(左目)
        rightEye:      { x: x , y: y, confidence: r },   # ポイント(右目)
        leftEar:       { x: x , y: y, confidence: r },   # ポイント(左耳)
        rightEar:      { x: x , y: y, confidence: r },   # ポイント(右耳)
        leftShoulder:  { x: x , y: y, confidence: r },   # ポイント(左肩)
        rightShoulder: { x: x , y: y, confidence: r },   # ポイント(右肩)
        leftElbow:     { x: x , y: y, confidence: r },   # ポイント(左肘)
        rightElbow:    { x: x , y: y, confidence: r },   # ポイント(右肘)
        leftWrist:     { x: x , y: y, confidence: r },   # ポイント(左手首)
        rightWrist:    { x: x , y: y, confidence: r },   # ポイント(右手首)
        leftHip:       { x: x , y: y, confidence: r },   # ポイント(左尻)
        rightHip:      { x: x , y: y, confidence: r },   # ポイント(右尻)
        leftKnee:      { x: x , y: y, confidence: r },   # ポイント(左膝)
        rightKnee:     { x: x , y: y, confidence: r },   # ポイント(右膝)
        leftAnkle:     { x: x , y: y, confidence: r },   # ポイント(左足首)
        rightAnkle:    { x: x , y: y, confidence: r }    # ポイント(右足首)
      }
    },
    {                                          # 2人目
      pose: {
        ...
      }
    },
    ...
    ...
    ...
    {                                          # N人目
      pose: {
        ...
      }
    },
  ]

関連