Intern

Pythonでカメラ映像を取得し骨格推定してみた

Pythonde仮想環境を作り、取得したカメラ映像で骨格推定していきたいと思います。

Pythonのインストールの準備

今回は、「Visual Studio Code」を使ってPythonを動かしていきたいと思います。

PCに入っていない方は、下記URLからダウンロードしてください。

https://code.visualstudio.com

まず、エクスプローラ―からOS内にフォルダーを作ります。

Visual Studio Codeを開き、先ほど作ったフォルダーを開きます。

もしかしたら、信頼しますか?などが出てくるかもしれませんが、こちらは信頼する、にしてください。
次に左のフォルダー名カーソルを合わせると、アイコンが出てきますので、ここからファイルを作成します。

ファイル名は何でもいいですが、拡張子は「.py」にしてください。

右上の分割マークから、下の分割を選択します。

ここからPythonのインストールをします。

Pythonのインストール

下のターミナルから、仮想環境を作成します。

python -m venv venv
./venv/Scripts/Activate

こちらで仮想環境が作成されます。
次に、この仮想環境内にモデルをインストールします。

pip install opencv-python numpy
pip install torch torchvision yolov5

ここまでインストールできましたら、まずはカメラ映像が取得できるか確認します。

import cv2
 
cap = cv2.VideoCapture(0)  # USBカメラを選択
while True:
    ret, frame = cap.read()
    if not ret:
        break
    cv2.imshow('Camera', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):  # 'q'で終了
        break
cap.release()
cv2.destroyAllWindows()Code language: PHP (php)

こちらのコードを作成したファイルに書き、保存します。
下のターミナルから
python ./ファイル名.py
でカメラを起動できます。

骨格推定のインストール

カメラの起動が確認出来たら、骨格を判定するためのライブラリーをインストールします。

pip install opencv-python mediapipe numpy matplotlib

こちらをインストールし、RTSPでカメラ映像を読み取ります。
新しいファイルに下記を挿入します。

import cv2
import mediapipe as mp
 
# MediaPipe Poseのセットアップ
mp_pose = mp.solutions.pose
pose = mp_pose.Pose()
mp_draw = mp.solutions.drawing_utils
 
# RTSPストリームのURL
rtsp_url = "rtsp://username:password@ip_address:port/stream1"
# WIDTH = 640
# HEIGHT = 480

# RTSPストリームのキャプチャ
cap = cv2.VideoCapture(rtsp_url)
 
if not cap.isOpened():
    print("Error: Could not open RTSP stream.")
    exit()

    # cap.set(cv2.CAP_PROP_FRAME_WIDTH, WIDTH)
    # cap.set(cv2.CAP_PROP_FRAME_HEIGHT, HEIGHT)
 
while True:
    ret, frame = cap.read()
    if not ret:
        print("Error: Failed to read frame from RTSP stream.")
        break

    # frame = cv2.resize(frame, (WIDTH, HEIGHT))
 
    # OpenCVはBGR、MediaPipeはRGBのため変換
    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
     
    # 骨格推定
    result = pose.process(rgb_frame)
 
    # 結果の描画
    if result.pose_landmarks:
        mp_draw.draw_landmarks(frame, result.pose_landmarks, mp_pose.POSE_CONNECTIONS)
 
        # 右手首の座標を取得(MediaPipeのランドマークインデックス 16)
        right_wrist = result.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_WRIST]
        nose = result.pose_landmarks.landmark[mp_pose.PoseLandmark.NOSE]  # 顔の位置を取得
        h, w, _ = frame.shape  # フレームのサイズ取得
        x, y = int(right_wrist.x * w), int(right_wrist.y * h)  # 画像座標に変換
        nose_x, nose_y = int(nose.x * w), int(nose.y * h)  # 顔の上に表示するための座標取得
 
        # 座標を顔の上に表示
        cv2.putText(frame, f'Right Wrist: ({x}, {y})', (nose_x, max(nose_y - 30, 30)),
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)
 
    cv2.imshow('Pose Estimation', frame)
 
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
 
cap.release()
cv2.destroyAllWindows()Code language: PHP (php)

こちらを挿入したら、RTSPの部分を自身の読み込みたいカメラに設定します。
PCカメラで行う場合は下記を挿入してください。

import cv2
import mediapipe as mp
 
# MediaPipe Poseのセットアップ
mp_pose = mp.solutions.pose
pose = mp_pose.Pose()
mp_draw = mp.solutions.drawing_utils
 
# RTSPストリームのURL
rtsp_url = "rtsp://admin:SmartLight197@192.168.1.102:554/stream1"
# WIDTH = 640
# HEIGHT = 480

# RTSPストリームのキャプチャ
cap = cv2.VideoCapture(rtsp_url)
 
if not cap.isOpened():
    print("Error: Could not open RTSP stream.")
    exit()

    # cap.set(cv2.CAP_PROP_FRAME_WIDTH, WIDTH)
    # cap.set(cv2.CAP_PROP_FRAME_HEIGHT, HEIGHT)
 
while True:
    ret, frame = cap.read()
    if not ret:
        print("Error: Failed to read frame from RTSP stream.")
        break

    # frame = cv2.resize(frame, (WIDTH, HEIGHT))
 
    # OpenCVはBGR、MediaPipeはRGBのため変換
    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
     
    # 骨格推定
    result = pose.process(rgb_frame)
 
    # 結果の描画
    if result.pose_landmarks:
        mp_draw.draw_landmarks(frame, result.pose_landmarks, mp_pose.POSE_CONNECTIONS)
 
        # 右手首の座標を取得(MediaPipeのランドマークインデックス 16)
        right_wrist = result.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_WRIST]
        nose = result.pose_landmarks.landmark[mp_pose.PoseLandmark.NOSE]  # 顔の位置を取得
        h, w, _ = frame.shape  # フレームのサイズ取得
        x, y = int(right_wrist.x * w), int(right_wrist.y * h)  # 画像座標に変換
        nose_x, nose_y = int(nose.x * w), int(nose.y * h)  # 顔の上に表示するための座標取得
 
        # 座標を顔の上に表示
        cv2.putText(frame, f'Right Wrist: ({x}, {y})', (nose_x, max(nose_y - 30, 30)),
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)
 
    cv2.imshow('Pose Estimation', frame)
 
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
 
cap.release()
cv2.destroyAllWindows()Code language: PHP (php)

そうしましたら、下のターミナルから

python ./ファイル名.py
を実行すると映像が映り、骨格の判定が表示されます。