아이디어 : Pose Detection을 활용한 ㅁㅁㅁㅁㅁ
Pose Detection으로 사람의 포즈를 포착한다.
Pose Estimation에 대해서는 2d, 3d 등의 여러 기술들이 있다.
[Pose Estimation]
포즈를 포착하는 것에 있어서 스켈레톤 구성(점 좌표 연결), 덩어리 구성(사람의 몸 구성에 대해서 팔, 다리, 몸통을 도형으로 어림잡아서 잡기-마치 그림 그릴 때 뭉탱이 그리기처럼), 볼륨을 전체로 구성하기.(인체와 비슷한 볼륨으로 구성-3D로 구성).
Pose estimation의 적용 중 흔하게 사용할 수 있는 것은 OpenCV 라이브러리의 OpenPose와 구글에서 제작한 MediaPipe가 있다. 이 두라이브러리는 사용이 정말 간단하다.
나는 먼저 스켈레톤을 보기 위해 MediaPipe를 주력으로 사용하였다. OpenPose는 Pose Estimation의 모델을 얻기가 어려웠기 대문이다. (깃허브의 설치 안내를 따라가다 batch 파일을 통해 모델을 다운받게 되는데, 서버가 고장났는지 다운로드에 실패한다. 물론 다른 곳에서 얻기는 하였다. 깃허브는 위대하다.)
그리하여 사용한 것이 MediaPipe이다.
해당 파이썬 코드는 이러하다. 노트북에 장착된 혹은 연결된 카메라를 통해서 포즈를 확인하는 코드는 아래와 같다.
import cv2
import mediapipe as mp
import math
import numpy as np
# MediaPipe 초기화
mp_pose = mp.solutions.pose
pose = mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5)
# 비디오 캡처
cap = cv2.VideoCapture(0)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 색 공간 변환 (BGR -> RGB)
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# 포즈 추적
results = pose.process(rgb_frame)
# 월드 랜드마크 추출
if results.pose_world_landmarks:
# 월드 랜드마크(3D 좌표) 출력
#for i, landmark in enumerate(results.pose_world_landmarks.landmark):
for i in range(11, 17): # 11번부터 16번까지
landmark = results.pose_landmarks.landmark[i]
#print(f"Landmark {i}: X={landmark.x:.4f}, Y={landmark.y:.4f}, Z={landmark.z:.4f}")
# 시각화
if results.pose_landmarks:
# MediaPipe가 제공하는 기본 랜드마크 그리기
mp.solutions.drawing_utils.draw_landmarks(
frame, results.pose_landmarks, mp_pose.POSE_CONNECTIONS
)
# 결과 출력
cv2.imshow('Pose Detection (3D)', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
이를 사용하면, 아래와 같이 뜨게 된다.
Pose Estimation에서는 각 관절의 점을 Keypoint(Landmark)로 잡는다. 미디어 파이프에서는 우측 사진처럼 키포인트를 잡게 된다. 눈,코,입, 귀와 몸통까지 잡게 된다. 이를 통해서 각 좌푤를 미터 단위로 환산해서 잡게 된다.
미디어파이프는 정말 효율이 좋다. 연산 또한 가볍기 때문에 작은 기기에서도 돌아가기 쉽다. 어렵게 구한 OpenPose 모델에서는 실시간 연산을 따라갈 때 버거웠지만 미디어파이프는 매우 부드러웠다.
이를 통해 우리는 프로젝트 목표(비공개했습니다.)를 하기 위해 각 좌표의 점을 추출. 추출한 점을 통해서 관절의 각도를 CSV파일로 옮기게 됐다.
좌표를 통해서 벡터 내적 및 삼각함수를 이용해서 구하고, 해당 데이터를 사진별로 CSV파일로 수치 데이터로 가공.
좌표에 따라 각도를 구하는 코드는 아래와 같다.
def calculate_angle(a, b, c):
# 각 landmark에서 x, y 좌표만 추출
a = np.array([a.x, a.y])
b = np.array([b.x, b.y])
c = np.array([c.x, c.y])
ba = a - b
bc = c - b
# 내적을 사용하여 두 벡터 간의 각도 계산
cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc))
angle = np.arccos(cosine_angle)
return np.degrees(angle)
z 좌표는 a.z, b.z c.z 를 각각 np.array에 넣어주면 그만이고, 다만, z 좌표가 추가된 것에 대한 계산 처리 알고리즘이 return 전에 더 들어갈 것 이다. 직접 해보기.
이런 전처리 후 CSV 파일로 만들었다.
'[개발]자국 > [그 외]' 카테고리의 다른 글
[해커톤] Big Data / AI 모델 해커톤 -2(완) (1) | 2024.12.02 |
---|---|
[코드트리] 서로 다른 구간의 수 (0) | 2023.08.27 |
[코드트리] 가장 많이 겹치는 구간 (0) | 2023.08.27 |
[코드트리] Intermediate Mid - Shorten Time Technique[LR Technique] (0) | 2023.08.25 |
[코드트리] Intermediate Mid - Shorten Time Technique[Grid Compression] (0) | 2023.08.25 |