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
カメラ映像からリアルタイムに体の姿勢を検出します。
| 引数名 | 内容 | 備考 | オプション | デフォルト値 |
|---|---|---|---|---|
| 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: {
...
}
},
]