์ง๋ ๋ธ๋ก๊ทธ ํฌ์คํ ์์๋ 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 ํ์ผ๋ก ์ ์ฅํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ค์๊ฐ ๋ชจ์ ์ธ์์ ๊ตฌํํ ์ ์์ต๋๋ค