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

MediaPipe Holistic์„ ํ™œ์šฉํ•œ ๋ชจ์…˜ ์ธ์‹ ๋ฐ JSON ํŒŒ์ผ ์ถ”์ถœ

leejaejae 2024. 6. 19. 14:53

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

<๋ชฉ์ฐจ>

1. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž„ํฌํŠธ ๋ฐ MediaPipe ์ดˆ๊ธฐํ™”
2. ์ด๋ฏธ์ง€ ํŒŒ์ผ ๋ชฉ๋ก ๋ฐ ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ ๋ฆฌ์ŠคํŠธ ์„ค์ •
3. ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ ์ถ”์ถœ ํ•จ์ˆ˜ ์ •์˜
4. MediaPipe Holistic์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ
5. ๊ฐ์ง€๋œ ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ ์ถ”์ถœ ๋ฐ ์ €์žฅ
6. ์ด๋ฏธ์ง€์— ๋žœ๋“œ๋งˆํฌ ์ฃผ์„ ์ถ”๊ฐ€
7. ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ๋ฅผ JSON ํŒŒ์ผ๋กœ ์ €์žฅ
8. ๊ฒฐ๊ณผ
9. ์ฐธ๊ณ 


1. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž„ํฌํŠธ ๋ฐ MediaPipe ์ดˆ๊ธฐํ™”

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

import cv2
import mediapipe as mp
import json
import matplotlib.pyplot as plt

# MediaPipe Holistic ๋ฐ ๊ทธ๋ฆฌ๊ธฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ ์ดˆ๊ธฐํ™”
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_holistic = mp.solutions.holistic

 

2. ์ด๋ฏธ์ง€ ํŒŒ์ผ ๋ชฉ๋ก ๋ฐ ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ ๋ฆฌ์ŠคํŠธ ์„ค์ •

์ฒ˜๋ฆฌํ•  ์ด๋ฏธ์ง€ ํŒŒ์ผ ๋ชฉ๋ก์„ ์„ค์ •ํ•˜๊ณ , ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ๋ฆฌ์ŠคํŠธ๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค.

# ์ฒ˜๋ฆฌํ•  ์ด๋ฏธ์ง€ ํŒŒ์ผ ๋ชฉ๋ก
IMAGE_FILES = ["../singlePerson_image/yoo/balance.jpeg"]
BG_COLOR = (192, 192, 192)

# ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ๋ฆฌ์ŠคํŠธ
landmarks_data = []

 

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

๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ๊ฐ ๋žœ๋“œ๋งˆํฌ์˜ ์ด๋ฆ„๊ณผ ์ขŒํ‘œ(x, y, z)๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

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)]

 

4. MediaPipe Holistic์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ

์ด๋ฏธ์ง€๋ฅผ ์ฝ๊ณ , MediaPipe Holistic์„ ์‚ฌ์šฉํ•˜์—ฌ ํฌ์ฆˆ, ์–ผ๊ตด, ์†์˜ ๋žœ๋“œ๋งˆํฌ๋ฅผ ๊ฐ์ง€ํ•ฉ๋‹ˆ๋‹ค.

with mp_holistic.Holistic(
    static_image_mode=True,
    model_complexity=2,
    enable_segmentation=True,
    refine_face_landmarks=True) as holistic:
    for idx, file in enumerate(IMAGE_FILES):
        # ์ด๋ฏธ์ง€ ์ฝ๊ธฐ
        image = cv2.imread(file)
        image_height, image_width, _ = image.shape
        results = holistic.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))

 

5. ๊ฐ์ง€๋œ ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ ์ถ”์ถœ ๋ฐ ์ €์žฅ

๊ฐ์ง€๋œ ๋žœ๋“œ๋งˆํฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค

        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)

        landmarks_data.append({
            'file': file,
            'landmarks': landmarks
        })

 

6. ์ด๋ฏธ์ง€์— ๋žœ๋“œ๋งˆํฌ ์ฃผ์„ ์ถ”๊ฐ€

๊ฐ์ง€๋œ ๋žœ๋“œ๋งˆํฌ๋ฅผ ์ด๋ฏธ์ง€์— ๊ทธ๋ ค์„œ ์ฃผ์„์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

        # ์ด๋ฏธ์ง€์— ๋žœ๋“œ๋งˆํฌ ๊ทธ๋ฆฌ๊ธฐ
        annotated_image = image.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 * image_width)
                y = int(landmark.y * image_height)
                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()
        )

        # ์ฃผ์„ ์ฒ˜๋ฆฌ๋œ ์ด๋ฏธ์ง€ ํ‘œ์‹œ
        fig = plt.figure(figsize=[10, 10])
        plt.title("Output")
        plt.axis('off')
        plt.imshow(annotated_image[:, :, ::-1])
        plt.show()

 

7. ๊ฒฐ๊ณผ

 

8. ์ฐธ๊ณ 

https://github.com/google-ai-edge/mediapipe/blob/master/docs/solutions/holistic.md

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