Open6

ブラウザだけで指数えを検出

おのおの

ブラウザで簡単機械学習できるml5js

ml5jsはProcessing出身の自分からしてみると、光ですね
もっと皆に知ってほしいライブラリです!
tensorflow.jsも触ったけど、やっぱり記述が多い

ただ、やはり新しいものなので機能がなかったり、記述のルールが機能によって違ったりするので、そこらへん注意ですね。

handposeで手の骨格を取得

Image from Gyazo

handpose(https://learn.ml5js.org/#/reference/handpose)って前あったっけ?
すごくよくできてるので使ってみる
単眼で、しかもブラウザだけで3Dデータとして取得できるのは少し前から考えるとすごいですね

おのおの

取得結果のjsonデータの中身を見てみる

[
    {
      handInViewConfidence: 1, // The probability of a hand being present.
      boundingBox: { // The bounding box surrounding the hand.
        topLeft: [162.91, -17.42],
        bottomRight: [548.56, 368.23],
      },
      landmarks: [ // The 3D coordinates of each hand landmark.
        [472.52, 298.59, 0.00],
        [412.80, 315.64, -6.18],
        ...
      ],
      annotations: { // Semantic groupings of the `landmarks` coordinates.
        thumb: [
          [412.80, 315.64, -6.18]
          [350.02, 298.38, -7.14],
          ...
        ],
        ...
      }
    }
  ]

landmarks内に3Dデータが入ってますね
多分、x軸、y軸、z軸という順で2次配列ができていると予想できますね

ただ、第一階層目のどこの指のどの関節なのかがわからないので、確認するコードを作ってみます

おのおの

指数えを取得してみる

指で表す数字のことですね。

Image from Gyazo

結果、右手限定にしてみることで正確にとれているように見えます。
アルゴリズムは各指の付け根から先端までの角度を…とか考えたけど…簡略化したらもっと正確のように見えるとれかたしました
以下コードの一部

function getFingerNumber(hand) {
  const annotations = hand.annotations;

  let number = 0;
  // 右手限定
  // 親指が立っているかどうか
  if (annotations.thumb[3][0] > annotations.thumb[2][0]) {
    number++;
  }

  if (annotations.indexFinger[3][1] < annotations.indexFinger[2][1]) {
    number++;
  }
  if (annotations.middleFinger[3][1] < annotations.middleFinger[2][1]) {
    number++;
  }
  if (annotations.ringFinger[3][1] < annotations.ringFinger[2][1]) {
    number++;
  }
  if (annotations.pinky[3][1] < annotations.pinky[2][1]) {
    number++;
  }

  return number;
}

先端が、第一関節よりY座標が低かったら曲げてるということにしてます。
右手限定というのは、親指だけX座標で考えているだけです。(手のひらに近い、とかでもいいですけども…)

角度計算のものが、小指だけなんか正確じゃなくて…とくにZ座標が。
なので2DでY座標しか見ないようになってます。
なので、手のひらを逆さまにしたり、角度によって全然正確じゃないです。が、まぁいったんいいでしょう!

おのおの

アルゴリズムをわかりやすくしたような解説図

Image from Gyazo

Image from Gyazo