Raspberry Piでカメラ映像の骨格検出をする方法 Part 1

  • URLをコピーしました!

今回から2回に分けて、Raspberry Piで撮影した映像に映った人物の骨格検出を行う方法を解説していきます。
Part 1ではOpenPoseを使って静止画に対して骨格検出を行うプログラムを作成していきます。

また、、OpenCVの活用事例についても以下の記事で解説していますので、あわせてご覧ください。

目次

openposeを入手する

今回、骨格検出するアプリケーションにはgithubで公開されているspmallick氏の「learnopencv」のプロジェクトを利用させて頂きました。以下のリポジトリをダウンロードします。

「Code」のプルダウンメニューの「Download ZIP」をクリックしてプロジェクトファイルをダウンロードしてください。

「(ダウンロードしたファイルのディレクトリパス)\learnopencv-master\OpenPose」にある「OpenPose_Notebook.ipynb」が骨格検出のプログラムになります。

モデルを入手する

骨格検出のための学習済みモデルをダウンロードします。

モデルのダウンロード

「(ダウンロードしたファイルのディレクトリパス)\learnopencv-master\OpenPose\getModels.sh」のファイルにモデルのダウンロード先が書かれています。「COCO」と「MPI」の2つのモデルファイルをダウンロードしてください。

# ------------------------- POSE MODELS -------------------------


# Downloading the pose-model trained on COCO
COCO_POSE_URL="https://www.dropbox.com/s/2h2bv29a130sgrk/pose_iter_440000.caffemodel"
COCO_FOLDER="pose/coco/"
wget -c ${COCO_POSE_URL} -P ${COCO_FOLDER}

# Downloading the pose-model trained on MPI
MPI_POSE_URL="https://www.dropbox.com/s/drumc6dzllfed16/pose_iter_160000.caffemodel"
MPI_FOLDER="pose/mpi/"
wget -c ${MPI_POSE_URL} -P ${MPI_FOLDER}

モデルを配置する

ダウンロードしたモデルファイルを配置します。
2つのモデルファイルをそれぞれ以下のディレクトリに配置してください。

pose_iter_440000.caffemodel

「(ダウンロードしたファイルのディレクトリパス)\learnopencv-master\learnopencv-master\OpenPose\pose\coco」

pose_iter_160000.caffemodel

「(ダウンロードしたファイルのディレクトリパス)\learnopencv-master\learnopencv-master\OpenPose\pose\mpi」

作成したソースコード

実際に骨格検出を行うプログラムを作成していきます。ダウンロードした「learnopencv」のソースコードはjupyter notebookファイルですので、Raspberry Piで実行するために必要な処理だけを実装します。

モデルの選択

ダウンロードした「COCO」と「MPI」のどちらのモデルを使用するかは、実際に読み込む画像によって使い分けてみてください。「MODE」という変数に使いたいモデルを指定することで切り替えることができます。
今回は「MPI」を使うことにしました。

#読み込むモデルを選択
MODE = "MPI"

if MODE is "COCO":
    protoFile = "(ダウンロードしたファイルのディレクトリパス)/learnopencv-master/OpenPose/pose/coco/pose_deploy_linevec.prototxt"
    weightsFile = "(ダウンロードしたファイルのディレクトリパス)/learnopencv-master/OpenPose/pose/coco/pose_iter_440000.caffemodel"
    nPoints = 18
    POSE_PAIRS = [ [1,0],[1,2],[1,5],[2,3],[3,4],[5,6],[6,7],[1,8],[8,9],[9,10],[1,11],[11,12],[12,13],[0,14],[0,15],[14,16],[15,17]]

elif MODE is "MPI" :
    protoFile = "(ダウンロードしたファイルのディレクトリパス)/learnopencv-master/OpenPose/pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt"
    weightsFile = "(ダウンロードしたファイルのディレクトリパス)/learnopencv-master/OpenPose/pose/mpi/pose_iter_160000.caffemodel"
    nPoints = 15
    POSE_PAIRS = [[0,1], [1,2], [2,3], [3,4], [1,5], [5,6], [6,7], [1,14], [14,8], [8,9], [9,10], [14,11], [11,12], [12,13] ]

全体のソースコード

以下が作成したコードの全体です。今回はRaspberry Piに実装する前に、PCで静止画で骨格検出ができるかテストするためのコードとなります。
画像はOpenPoseのディレクトリに最初から用意されている「single.jpeg」をそのまま使用します。
ディレクトリを指定している箇所は、環境に合わせてパスを変更して使ってください。

import cv2
import time
import numpy as np
import matplotlib.pyplot as plt


frame = cv2.imread(r"(ダウンロードしたファイルのディレクトリパス)/learnopencv-master/OpenPose/single.jpeg")
frameCopy = np.copy(frame)
frameWidth = frame.shape[1]
frameHeight = frame.shape[0]
threshold = 0.1

#読み込むモデルを選択
MODE = "MPI"

if MODE is "COCO":
    protoFile = "(ダウンロードしたファイルのディレクトリパス)/learnopencv-master/OpenPose/pose/coco/pose_deploy_linevec.prototxt"
    weightsFile = "(ダウンロードしたファイルのディレクトリパス)/learnopencv-master/OpenPose/pose/coco/pose_iter_440000.caffemodel"
    nPoints = 18
    POSE_PAIRS = [ [1,0],[1,2],[1,5],[2,3],[3,4],[5,6],[6,7],[1,8],[8,9],[9,10],[1,11],[11,12],[12,13],[0,14],[0,15],[14,16],[15,17]]

elif MODE is "MPI" :
    protoFile = "(ダウンロードしたファイルのディレクトリパス)/learnopencv-master/OpenPose/pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt"
    weightsFile = "(ダウンロードしたファイルのディレクトリパス)/learnopencv-master/OpenPose/pose/mpi/pose_iter_160000.caffemodel"
    nPoints = 15
    POSE_PAIRS = [[0,1], [1,2], [2,3], [3,4], [1,5], [5,6], [6,7], [1,14], [14,8], [8,9], [9,10], [14,11], [11,12], [12,13] ]


print("protoFile = ", protoFile)
print("weightsFile = ", weightsFile)
net = cv2.dnn.readNetFromCaffe(protoFile, weightsFile)

inWidth = 368
inHeight = 368

inpBlob = cv2.dnn.blobFromImage(frame, 1.0 / 255, (inWidth, inHeight),
                          (0, 0, 0), swapRB=False, crop=False)

net.setInput(inpBlob)

output = net.forward()
H = output.shape[2]
W = output.shape[3]

points = []

for i in range(nPoints):
    # confidence map of corresponding body's part.
    probMap = output[0, i, :, :]

    # Find global maxima of the probMap.
    minVal, prob, minLoc, point = cv2.minMaxLoc(probMap)
    
    # Scale the point to fit on the original image
    x = (frameWidth * point[0]) / W
    y = (frameHeight * point[1]) / H

    if prob > threshold : 
        cv2.circle(frameCopy, (int(x), int(y)), 8, (0, 255, 255), thickness=-1, lineType=cv2.FILLED)
        cv2.putText(frameCopy, "{}".format(i), (int(x), int(y)), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, lineType=cv2.LINE_AA)
        cv2.circle(frame, (int(x), int(y)), 8, (0, 0, 255), thickness=-1, lineType=cv2.FILLED)

        # Add the point to the list if the probability is greater than the threshold
        points.append((int(x), int(y)))
    else :
        points.append(None)

# Draw Skeleton
for pair in POSE_PAIRS:
    partA = pair[0]
    partB = pair[1]

    if points[partA] and points[partB]:
        cv2.line(frame, points[partA], points[partB], (0, 255, 255), 3)

print("画像出力")

plt.figure(figsize=[10,10])
plt.imshow(cv2.cvtColor(frameCopy, cv2.COLOR_BGR2RGB))
plt.show()
plt.figure(figsize=[10,10])
plt.imshow(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
plt.show()

実行結果

実行結果は以下の通りです。うまく骨格検出することができました。モデルを変更すると結果も変わりますので試してみてください。

まとめ

今回はOpenCVで骨格検出を行う方法を解説しました。次回はRaspberry Piに実装するためのコードを作成して、カメラで撮影した映像に対してリアルタイムに骨格検出します。

また、ラズベリーパイの画像認識についてさらに深く学びたい方にはUdemyの以下の講座がおすすめです。

【初心者向けAI・IoT講座】 ラズベリーパイ(Raspberry Pi)とOpenCVで作る簡単画像認識システム icon



それでは、また次の記事でお会いしましょう。

参考

よかったらシェアしてね!
  • URLをコピーしました!
目次