AI(4) ≡ Gesture

Acrylic·2024년 4월 2일

Linear Regression

변수와의 관계를 분석하고 값을 예측하는 방법

일단 이 행동을 하려면 그래프를 그려서 어떤 경향이 있긴 한 건지 확인하고
지금 같은 그래프에선 양의 상관관계가 있으니 저렇게 선을 그어 경향을 확인할 수 있습니다.

식은 뭐 이렇습니다.

그리고 실젯값과 예측값을 비슷하게 하는 과정에서 최소제곱법이 나옵니다. 거기서 나온 걸 Cost라고 하겠죠. 그걸 줄이고 줄여서 최소로 만드는 게 목표입니다.

뭐 이런 거고요. 사람이 직접 한다면 이 식에다 직접 대입해야 해서 번거롭지만

잉공지능은 알잘딱하고 빠르게 작업해 줍니다.

CNN(Convolutional Neural Network)

최소한의 전처리(가공)를 하도록 하는 머신러닝의 종류

정말 쉽게 설명하자면 보이는 것만 분석하면 너무 비효율적입니다. 그런 방식은 모든 종류의 개와 그 개의 각도 그런 걸 다 분석해야 한다고 보면 됩니다.

그래서 차라리 숫자로 간략하게 표현해서 분석하는 합성곱 신경망(CNN)을 쓰면 되겠네 한 거죠.

뭐 당연히 너무 적은 자료로는 효율적으로 사용할 수 없고 어느 정도 있으면 분석 결과가 아주 보기 좋게 된다 보시면 됩니다.

CNN 종류로는 Convolutional Layer, Pooling Layer, Fully Connected Layer가 있습니다.

Convolutional Layer

Convolutional Layer는 뭐 이런 거고요. 행렬 제곱으로 특징이 비슷한지 하는 걸 확인할 수 있고요.

Pooling Layer

Pooling Layer는 뭐 이런 겁니다. 흠 뭐 최댓값, 평균, 최솟값을 이용해서 간략하게 표현하는 방법이 있다 정도로 보시면 되겠네요.

Fully Connected Layer

Fully Connected Layer는 뭐 뉴런 생각하시면 되는데 그것마냥 Convolutional Layer 에서 나온 데이터를 1차원으로 펴서 효과적으로 학습한다 보면 되네요.

전이학습

아주 큰 데이터셋에 훈련된 가중치를 들고 와서 보정해 사용하는 것

음, 한마디로 우리 같이 돈 없는 사람이 다른 사람이 학습한 모델을 갖다가 좀 바꿔서 하는 학습이라 보면 되겠네요.

(출처: Flaticon - Eucalyp)

욕하면 모자이크 처리

하 원래 가운데 손가락 안 올리는데... 어쩔 수 없네요.

import cv2
import mediapipe as mp
import numpy as np

max_num_hands = 5
gesture = {	
   0: 'fist', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five',
   6: 'six', 7: 'rock', 8: 'spiderman', 9: 'yeah', 10: 'ok', 11: 'fy'
}

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_fy.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)

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], :]
           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 # [20,3]

           v = v / np.linalg.norm(v, axis=1)[:, np.newaxis]

           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], :]))
                                       
           angle = np.degrees(angle)

           ret, results, neighbours, dist = knn.findNearest(data, 3)
           idx = int(results[0][0])

           if idx == 11:
               x1, y1 = tuple((joint.min(axis=0)[:2] * [img.shape[1], img.shape[0]] * 0.95).astype(int))
               x2, y2 = tuple((joint.max(axis=0)[:2] * [img.shape[1], img.shape[0]] * 1.05).astype(int))

               fy_img = img[y1:y2, x1:x2].copy()
               fy_img = cv2.resize(fy_img, dsize=None, fx=0.05, fy=0.05, interpolation=cv2.INTER_NEAREST)
               fy_img = cv2.resize(fy_img, dsize=(x2 - x1, y2 - y1), interpolation=cv2.INTER_NEAREST)

               img[y1:y2, x1:x2] = fy_img

           # mp_drawing.draw_landmarks(img, res, mp_hands.HAND_CONNECTIONS)

   cv2.imshow('Filter', img)
   if cv2.waitKey(1) == ord('q'):
       break

profile
프런트엔드 개발자 지망생

0개의 댓글