Deep Learning - mediapipe hand 사용하기 - Hand Landmark - 가위바위보

화이티 ·2024년 1월 19일
1

Deep Learning

목록 보기
19/24

설치:

(base) C:\Users\dd>activate yolov5
(yolov5) C:\Users\dd>pip install mediapipe
(yolov5) C:\Users\dd>jupyter notebook

https://developers.google.com/mediapipe/solutions/examples

import cv2
import mediapipe as mp
# 캠 연결하기
import cv2

# mediapipe 사용하기
# 손찾디 관련 기능 불러오기
mp_hands = mp.solutions.hands
#손 그려주는 기능 불러오기
mp_drawing = mp.solutions.drawing_utils
# 손 찾기 관연 세부 설정
hands = mp_hands.Hands(
    max_num_hands = 1,# 탐지할 최대 손의 객수
    min_detection_confidence = 0.5, # 표시할 손의 최소 정확도
    min_tracking_confidence = 0.5 # 표시할 관잘의 최소 정확도

)

video = cv2.VideoCapture(0)
while video.isOpened():
    ret, img = video.read()
    img = cv2.flip(img,1)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    result = hands.process(img) # 손 탐지하기
    
    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
    if not ret: 
        break
    # 찾은 손 표시하기
    if result.multi_hand_landmarks is not None:
       # print(result.multi_hand_landmarks)
        for res in result.multi_hand_landmarks:
            mp_drawing.draw_landmarks(img, res, mp_hands.HAND_CONNECTIONS)
   
    k = cv2.waitKey(30)
    if k==49:
        break
    cv2.imshow('hand', img)
video.release()
cv2.destroyAllWindows()

한손 동작 인식시키기🐱‍🚀

정의

  1. 손가락 관절 위치 (mediapipe에서 출력된 값)
  2. 관절끼리 연결한 뼈의 값 구하기(점을 연결한 선)
  3. 뼈 사이의 각도 구하기
  4. KNN모델에 예측시키기
  5. 이미지에 예측값 표현
    https://developers.google.com/mediapipe/solutions/vision/hand_landmarker#get_started
    landmark{
    x: 0.86945135
    y: 0.56984164
    z: 0.21968469}

Enumerate() in Python

The enumerate () method adds a counter to an iterable and returns it in the form of an enumerating object. This enumerated object can then be used directly for loops or converted into a list of tuples using the list() function.
Syntax: enumerate(iterable, start=0)
Parameters:
Iterable: any object that supports iteration
Start: the index value from which the counter is to be started, by default it is 0
Return: Returns an iterator with index and element pairs from the original iterable

# 캠 연결하기
import cv2
import mediapipe as mp
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
# 인식 가능한 11가지 동작
gesture = {
    0:'fist', 1:'one', 2:'two', 3:'three', 4:'four', 5:'five',
    6:'six', 7:'rock', 8:'spiderman', 9:'yeah', 10:'ok',
}
# 가위바위보 동작 만들기
rsp = {
    0: 'rock', 5: 'paper', 9:'scissors'
}
# 동작 인식 모델 만들기 (knn모델)
file = np.genfromtxt('./data/gesture_train.csv', delimiter = ',')
X = file[:,:-1].astype(np.float32)
y = file[:,-1].astype(np.float32)
knn = KNeighborsClassifier(n_neighbors = 3)
knn.fit(X,y)
# mediapipe 사용하기
# 손찾디 관련 기능 불러오기
mp_hands = mp.solutions.hands
#손 그려주는 기능 불러오기
mp_drawing = mp.solutions.drawing_utils
# 손 찾기 관연 세부 설정
hands = mp_hands.Hands(
    max_num_hands = 2,# 탐지할 최대 손의 객수
    min_detection_confidence = 0.5, # 표시할 손의 최소 정확도
    min_tracking_confidence = 0.5 # 표시할 관잘의 최소 정확도

)

video = cv2.VideoCapture(0)
while video.isOpened():
    ret, img = video.read()
    img = cv2.flip(img,1)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    result = hands.process(img) # 손 탐지하기
    
    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
    if not ret: 
        break
    # 찾은 손 표시하기
    if result.multi_hand_landmarks is not None:
        rsp_result = []
        #d이미지 손 표현하기
       # print(result.multi_hand_landmarks)
        for res in result.multi_hand_landmarks:
            joint = np.zeros((21,3)) # 21개 관절, xyz값 저장할 배열 생성
            # enumerate = for문의 순서 표현
            for j,lm in enumerate(res.landmark):
                joint[j] = [lm.x, lm.y,lm.z]
                # 연결할 관절 번호 가져오기
            v1 = joint[[0,1,2,3,0,5,6,7,0,9,10,11,0,13,14,15,0,17,18,19],:]
            v2 = joint[[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],:]
            v = v2-v1 # 뼈의 값 (x,y,z좌표값 > 백터값)
            # 유클리디안 길이로 변롼(피타고라스)
            # 뼈의 값(직선 값)
            v = v/np.linalg.norm(v, axis = 1)[:, np.newaxis]
            # 뼈의 값으로 뼈사이의 각도 구하기, 변화값이 큰 15개
            angle = np.arccos(np.einsum('nt,nt->n',
                v[[0,1,2,4,5,6,8,9,10,12,13,14,16,17,18],:], 
                v[[1,2,3,5,6,7,9,10,11,13,14,15,17,18,19],:]))
            # radian 각도를 degree각도로 변경하기
            angle = np.degrees(angle)
            # 구한 각도를 knn모델에 예측시키기
            # 학습을 위해서 타입 변경 (2차원 array)
            X_pred = np.array([angle],dtype = np.float32)
            results = knn.predict(X_pred)
            idx = int(results)
            # 인식된 제스쳐 표현하기
            img_x = img.shape[1]
            img_y = img.shape[0]
            hand_x = res.landmark[0].x
            hand_y = res.landmark[0].y
            #cv2.putText(img, text = gesture[idx].upper(),
             #          org = ( int(hand_x * img_x), int(hand_y * img_y )),
              #         fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, color=(255, 255, 255), thickness=2
               #        )

            if idx in rsp.keys(): # 0,5,9 번 일때만 실행
                cv2.putText(img, text = rsp[idx].upper(),
                         org = ( int(hand_x * img_x), int(hand_y * img_y )),
                        fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, color=(255, 255, 255), thickness=2
                     )
                rsp_result.append({
                     'rsp': rsp[idx],
                     'org': ( int(hand_x * img_x), int(hand_y * img_y )+20),  
                })
            mp_drawing.draw_landmarks(img, res, mp_hands.HAND_CONNECTIONS)
            # 누기 이겼는지 판단하기
            if len(rsp_result) == 2:
                winner = None
                text = ''
                if rsp_result[0]['rsp'] == 'rock':
                    if rsp_result[1]['rsp'] == 'rock': text = 'Tie'; 
                    elif rsp_result[1]['rsp'] =='paper':text = 'Paper win'; winner =1;
                    elif rsp_result[1]['rsp'] == 'scissors':text ='Rock win'; winner = 0;
                elif rsp_result[0]['rsp'] == 'paper':
                    if rsp_result[1]['rsp'] == 'paper': text = 'Tie'; 
                    elif rsp_result[1]['rsp'] =='rock':text = 'Paper win'; winner =0;
                    elif rsp_result[1]['rsp'] == 'scissors':text ='Scissors win'; winner = 1;
                elif rsp_result[0]['rsp'] == 'scissors':
                    if rsp_result[1]['rsp'] == 'scissors': text = 'Tie'; 
                    elif rsp_result[1]['rsp'] =='rock':text = 'Rock win'; winner =1;
                    elif rsp_result[1]['rsp'] == 'paper':text ='Scissors win'; winner = 0;
                cv2.putText(img, text = text,
                            # 이미지 중앙에 결과 표시
                           org =( int(img_x/3),100),
                        fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=2, color=(0, 0, 255), thickness=3
                           )
    k = cv2.waitKey(30)
    if k==49:
        break
    cv2.imshow('hand', img)
video.release()
cv2.destroyAllWindows()

profile
열심히 공부합시다! The best is yet to come! 💜

0개의 댓글

관련 채용 정보