손 인식 인공지능 만들기
목표: 손모양을 인식하는 인공지능을 만들껍니다
개발언어 : 파이썬

언어는 파이썬을 사용하며
cv2 , mediapipe, numpy를 사용합니다
mediapipe는 얼굴인식, 다손추적, 헤어분할, 물체감지 및 추적등등 멀티 모달 (예 : 비디오, 오디오, 모든 시계열 데이터), 크로스 플랫폼 (예 : Android, iOS, 웹, 에지 장치) 적용 ML 파이프 라인을 구축하기위한 프레임 워크입니다.
Hands
Cross-platform, customizable ML solutions for live and streaming media.
google.github.io
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | import cv2 import mediapipe as mp import numpy as np #인식하는 손 갯수 max_num_hands = 2 gesture = { 0:'fist', 1:'one', 2:'two', 3:'three', 4:'four', 5:'five', 6:'six', 7:'rock', 8:'spiderman', 9:'yeah', 10:'ok', } # MediaPipe 손 모델 mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils hands = mp_hands.Hands( max_num_hands=max_num_hands, min_detection_confidence=0.5, min_tracking_confidence=0.5) # 제스처 인식 모델 file = np.genfromtxt('data/gesture_train.csv', delimiter=',') angle = file[:,:-1].astype(np.float32) label = file[:, -1].astype(np.float32) knn = cv2.ml.KNearest_create() knn.train(angle, cv2.ml.ROW_SAMPLE, label) #카메라 해상도 cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1024) while cap.isOpened(): ret, img = cap.read() if not ret: continue img = cv2.flip(img, 1) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) result = hands.process(img) img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) if result.multi_hand_landmarks is not None: for res in result.multi_hand_landmarks: joint = np.zeros((21, 3)) 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],:] # Parent joint v2 = joint[[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],:] # Child joint v = v2 - v1 # [20,3] # Normalize v v = v / np.linalg.norm(v, axis=1)[:, np.newaxis] # Get angle using arcos of dot product 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],:])) # [15,] angle = np.degrees(angle) # Convert radian to degree # Inference gesture data = np.array([angle], dtype=np.float32) ret, results, neighbours, dist = knn.findNearest(data, 3) idx = int(results[0][0]) # Draw gesture result if idx in gesture.keys(): cv2.putText(img, text=gesture[idx].upper(), org=(int(res.landmark[0].x * img.shape[1]), int(res.landmark[0].y * img.shape[0] + 20)), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, color=(255, 255, 255), thickness=2) # Other gestures # cv2.putText(img, text=gesture[idx].upper(), org=(int(res.landmark[0].x * img.shape[1]), int(res.landmark[0].y * img.shape[0] + 20)), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, color=(255, 255, 255), thickness=2) mp_drawing.draw_landmarks(img, res, mp_hands.HAND_CONNECTIONS) cv2.imshow('Test', img) if cv2.waitKey(1) == ord('q'): break | cs |
* 인식하는 손 갯수
max_num_hands = 2
gesture = {
0:'fist', 1:'one', 2:'two', 3:'three', 4:'four', 5:'five',
6:'six', 7:'rock', 8:'spiderman', 9:'yeah', 10:'ok',
}
-> max_num_hands는 인식하는 손 갯수입니다 2라면 2개의 손을 인식합니다
gesture = {
0:'fist', 1:'one', 2:'two', 3:'three', 4:'four', 5:'five',
6:'six', 7:'rock', 8:'spiderman', 9:'yeah', 10:'ok',
}
인공지능이 손 모양을 감지했을때 텍스트로 표현할 문자입니다
v1 = joint[[0,1,2,3,0,5,6,7,0,9,10,11,0,13,14,15,0,17,18,19],:] # Parent joint
v2 = joint[[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],:] # Child joint
v = v2 - v1 # [20,3]
# Normalize v
v = v / np.linalg.norm(v, axis=1)[:, np.newaxis]
# Get angle using arcos of dot product
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],:])) # [15,]
-> # 관절 사이의 각도 계산을 하여 손 모양을 인식합니다
예: 0과 1의 각도 1과 2의 각도등등을 계산하여 손 모양 인식
