์ธ๊ณต์ง€๋Šฅ(AI) ๐Ÿ“š

MediaPipe Holistic์„ ํ™œ์šฉํ•œ ์‹ค์‹œ๊ฐ„ ์›น์บ  ๋ชจ์…˜ ์ธ์‹

leejaejae 2024. 6. 19. 15:06

2024.06.19 - [์ธ๊ณต์ง€๋Šฅ(AI)] - MediaPipe Holistic์„ ํ™œ์šฉํ•œ ๋ชจ์…˜ ์ธ์‹ ๋ฐ JSON ํŒŒ์ผ ์ถ”์ถœ

์ง€๋‚œ ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŒ…์—์„œ๋Š” MediaPipe Holistic์„ ํ™œ์šฉํ•ด ์ด๋ฏธ์ง€์—์„œ ๋ชจ์…˜์„ ์ธ์‹ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋‹ค๋ค˜์Šต๋‹ˆ๋‹ค. MediaPipe Holistic์€ Google์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๋กœ, ์ด๋ฏธ์ง€์—์„œ ์‹ ์ฒด, ์–ผ๊ตด, ์†์˜ ๋žœ๋“œ๋งˆํฌ๋ฅผ ์‰ฝ๊ฒŒ ์บก์ฒ˜ํ•˜๊ณ  ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ์ด๋ฅผ ํ•œ ๋‹จ๊ณ„ ๋” ๋‚˜์•„๊ฐ€ ์‹ค์‹œ๊ฐ„ ์›น์บ  ๋ชจ์…˜ ์ธ์‹์— ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

<๋ชฉ์ฐจ>

0. ์‚ฌ์ „ ์ค€๋น„
1. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ ์„ค์ •
2. ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ ์ถ”์ถœ ํ•จ์ˆ˜
3. ๋””๋ ‰ํ† ๋ฆฌ ์„ค์ •
4. ์›น์บ ์—์„œ ํ”„๋ ˆ์ž„ ์บก์ฒ˜ ๋ฐ ์ฒ˜๋ฆฌ
5. ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐ ์ €์žฅ
6. ์ด๋ฏธ์ง€์— ๋žœ๋“œ๋งˆํฌ ๊ทธ๋ฆฌ๊ธฐ ๋ฐ ์ €์žฅ
7. ์ข…๋ฃŒ ์ฒ˜๋ฆฌ
8. ๊ฒฐ๊ณผ


0. ์‚ฌ์ „ ์ค€๋น„

์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. OpenCV์™€ MediaPipe ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

pip install opencv-python mediapipe

 

1. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ ์„ค์ •

์šฐ์„  ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , MediaPipe์˜ ๊ทธ๋ฆฌ๊ธฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ์™€ ์Šคํƒ€์ผ, ๊ทธ๋ฆฌ๊ณ  Holistic ์†”๋ฃจ์…˜์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

import cv2
import mediapipe as mp
import json
import os

mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_holistic = mp.solutions.holistic

# ๋ฐฐ๊ฒฝ์ƒ‰ ์„ค์ •
BG_COLOR = (192, 192, 192)

 

2. ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ ์ถ”์ถœ ํ•จ์ˆ˜

๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•˜์—ฌ JSON ํ˜•์‹์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

def extract_landmark_data(landmarks, landmark_enum=None):
    if landmark_enum is not None:
        return [{'name': landmark_enum(lm_idx).name, 'x': lm.x, 'y': lm.y, 'z': lm.z, 'visibility': lm.visibility if hasattr(lm, 'visibility') else None}
                for lm_idx, lm in enumerate(landmarks.landmark)]
    else:
        return [{'index': lm_idx, 'x': lm.x, 'y': lm.y, 'z': lm.z, 'visibility': lm.visibility if hasattr(lm, 'visibility') else None}
                for lm_idx, lm in enumerate(landmarks.landmark)]

 

3. ๋””๋ ‰ํ† ๋ฆฌ ์„ค์ •

๋žœ๋“œ๋งˆํฌ๊ฐ€ ๊ทธ๋ ค์ง„ ์ด๋ฏธ์ง€์™€ JSON ํŒŒ์ผ์„ ์ €์žฅํ•  ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

output_image_dir = 'cam_output_images'
output_json_dir = 'cam_output_json'

if not os.path.exists(output_image_dir):
    os.makedirs(output_image_dir)
if not os.path.exists(output_json_dir):
    os.makedirs(output_json_dir)

 

4. ์›น์บ ์—์„œ ํ”„๋ ˆ์ž„ ์บก์ฒ˜ ๋ฐ ์ฒ˜๋ฆฌ

์›น์บ ์—์„œ ํ”„๋ ˆ์ž„์„ ์บก์ฒ˜ํ•˜๊ณ , MediaPipe Holistic์„ ์‚ฌ์šฉํ•˜์—ฌ ๋žœ๋“œ๋งˆํฌ๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.

cap = cv2.VideoCapture(0)
frame_count = 0

with mp_holistic.Holistic(
    static_image_mode=False,
    model_complexity=2,
    enable_segmentation=True,
    refine_face_landmarks=True) as holistic:
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break

        image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        image.flags.writeable = False
        results = holistic.process(image)
        image.flags.writeable = True
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

 

5. ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐ ์ €์žฅ

์ถ”์ถœ๋œ ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ๋ฅผ JSON ํŒŒ์ผ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

        landmarks = {}
        if results.pose_landmarks:
            landmarks['pose_landmarks'] = extract_landmark_data(results.pose_landmarks, mp_holistic.PoseLandmark)
        if results.face_landmarks:
            landmarks['face_landmarks'] = extract_landmark_data(results.face_landmarks)
        if results.left_hand_landmarks:
            landmarks['left_hand_landmarks'] = extract_landmark_data(results.left_hand_landmarks, mp_holistic.HandLandmark)
        if results.right_hand_landmarks:
            landmarks['right_hand_landmarks'] = extract_landmark_data(results.right_hand_landmarks, mp_holistic.HandLandmark)

        pose_data = {
            'frame_index': frame_count,
            'landmarks': landmarks
        }

        # JSON ํŒŒ์ผ ์ €์žฅ
        json_file_path = os.path.join(output_json_dir, f'pose_data_{frame_count}.json')
        with open(json_file_path, 'w') as json_file:
            json.dump(pose_data, json_file, indent=2)

 

6. ์ด๋ฏธ์ง€์— ๋žœ๋“œ๋งˆํฌ ๊ทธ๋ฆฌ๊ธฐ ๋ฐ ์ €์žฅ

์บก์ฒ˜๋œ ์ด๋ฏธ์ง€์— ๋žœ๋“œ๋งˆํฌ๋ฅผ ๊ทธ๋ฆฐ ํ›„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

        # ์ด๋ฏธ์ง€์— ๋žœ๋“œ๋งˆํฌ ๊ทธ๋ฆฌ๊ธฐ
        annotated_image = frame.copy()
        mp_drawing.draw_landmarks(annotated_image, results.left_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
        mp_drawing.draw_landmarks(annotated_image, results.right_hand_landmarks, mp_holistic.HAND_CONNECTIONS)

        if results.face_landmarks:
            for landmark in results.face_landmarks.landmark:
                x = int(landmark.x * annotated_image.shape[1])
                y = int(landmark.y * annotated_image.shape[0])
                cv2.circle(annotated_image, (x, y), 1, (0, 255, 0), -1)

        mp_drawing.draw_landmarks(
            annotated_image,
            results.pose_landmarks,
            mp_holistic.POSE_CONNECTIONS,
            landmark_drawing_spec=mp_drawing_styles.get_default_pose_landmarks_style()
        )

        # ๋žœ๋“œ๋งˆํฌ๊ฐ€ ํ‘œ์‹œ๋œ ์ด๋ฏธ์ง€ ์ €์žฅ
        image_file_path = os.path.join(output_image_dir, f'annotated_image_{frame_count}.png')
        cv2.imwrite(image_file_path, annotated_image)

        frame_count += 1

        cv2.imshow('MediaPipe Holistic', annotated_image)
        if cv2.waitKey(5) & 0xFF == 27:
            break

 

7. ์ข…๋ฃŒ ์ฒ˜๋ฆฌ

์›น์บ ๊ณผ ๋ชจ๋“  ์ฐฝ์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

cap.release()
cv2.destroyAllWindows()

print(f"Total number of frames processed: {frame_count}")

 

8. ๊ฒฐ๊ณผ

 

์ด ์ฝ”๋“œ๋Š” ์‹ค์‹œ๊ฐ„์œผ๋กœ ์›น์บ ์—์„œ ํ”„๋ ˆ์ž„์„ ์ฝ์–ด MediaPipe Holistic์„ ํ†ตํ•ด ์‹ ์ฒด, ์–ผ๊ตด, ์†์˜ ๋žœ๋“œ๋งˆํฌ๋ฅผ ์ถ”์ถœํ•˜๊ณ , ์ด๋ฅผ ์ด๋ฏธ์ง€์™€ JSON ํŒŒ์ผ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์‹ค์‹œ๊ฐ„ ๋ชจ์…˜ ์ธ์‹์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค