2025년, 코딩은 선택이 아닌 필수!

2025년 모든 학교에서 코딩이 시작 됩니다. 먼저 준비하는 사람만이 기술을 선도해 갑니다~

머신러닝/7. 머신러닝 활용하기

[머신러닝 활용] 손가락 인식 모델 활용하기

파아란기쁨1 2022. 12. 13. 11:49
반응형

원본 코드 : https://google.github.io/mediapipe/solutions/hands.html

 

Hands

Cross-platform, customizable ML solutions for live and streaming media.

google.github.io

1. 패키지 설치 하기

pip install mediapipe

2. 라이브러리 임포트

import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands

3. 카메라에서 손을 인식하여 분석하기

옵션

  • static_image_mode(정적이미지모드):false인 경우 입력이미지를 비디오 스트림으로 처리한다. 첫번째 입력 이미지에서 손을 감지하고 탐지가 성공하면 손랜드마크의 위치를 추가로 파악한다.후속영상에서 max_num_hands만큼의 손이 감지되고 해당 손 랜드마크가 기준이 되면 손을 추적할 수 없을 때 까지 새로 기준을 잡지 않고 랜드마크만 추적한다. 따라서 대기시간이 단축되고 비디오 프레임 처리에 이상적이다. true 인 경우 모든 입력 이미지에서 손감지가 실행되므로 일괄 처리에 이상적이다. 기본값은 false
  • max_num_hands : 손 최대 갯수(기본값은 2)
  • model_complexity(모델 복잡성) : 0또는 1이며 랜드마크 정확도와 추론 지연시간은 모델 복잡성과 함께 증가한다.(기본값은 1)
  • min_detection_confidence(최소 탐지 신뢰도):탐지가 성공한 것으로 간주되는 손감지 모델의 최소 신뢰값, 기본값은 0.5
  • min_tracking_confidence(최소 추적 신뢰도):손랜드마크 추적 모델의 최소 신뢰값(0~1) 이 성공적으로 추적된 것으로 간주된다. 만약 그렇지 않다면 다음 입력 영상에서 기준 손 탐지가 자동으로 호출된다. 이 솔루션을 높은 값으로 설정하면 지연 시간이 길어지는 대신 솔루션의 정확성을 높일 수 있다. static_imae_mode 가 true라면 무시된다. 기본값은 0.5
cap = cv2.VideoCapture(0)
with mp_hands.Hands(
    model_complexity=0,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5) as hands:
    while cap.isOpened():
        success, image = cap.read()
        if not success:
          print("Ignoring empty camera frame.")
          # If loading a video, use 'break' instead of 'continue'.
          continue

        # To improve performance, optionally mark the image as not writeable to
        # pass by reference.
        image.flags.writeable = False
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        results = hands.process(image)

        # Draw the hand annotations on the image.
        image.flags.writeable = True
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
        if results.multi_hand_landmarks:
          for hand_landmarks in results.multi_hand_landmarks:
            mp_drawing.draw_landmarks(
                image,
                hand_landmarks,
                mp_hands.HAND_CONNECTIONS,
                mp_drawing_styles.get_default_hand_landmarks_style(),
                mp_drawing_styles.get_default_hand_connections_style())
        # Flip the image horizontally for a selfie-view display.
        cv2.imshow('MediaPipe Hands', cv2.flip(image, 1))
        if cv2.waitKey(5) & 0xFF == 27:
          break
cap.release()

 

이렇게 인식하는 모델을 다음과 같이 활용해 볼 수 있겠네요.

엄지와 검지 사이의 거리를 측정하여 볼륨 조절기를 만든다든 가 할때 엄지는 4번 인덱스 검지는 8번 인덱스이니까.

그 거리 측정 하는 코드를 활용하여

                thumb = hand_landmarks.landmark[4]
                index = hand_landmarks.landmark[8]

                diff = abs(index.x - thumb.x)

화면에 출력해 보면

              cv2.putText(
                  image, text='Diff: %d' % (int(diff*1000)), org=(10, 30),
                  fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1,
                  color=255, thickness=2)

실행 결과

 

전체 코드

import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands

cap = cv2.VideoCapture(0)

# fourcc 값 받아오기, *는 문자를 풀어쓰는 방식, *'DIVX' == 'D', 'I', 'V', 'X'
fourcc = cv2.VideoWriter_fourcc(*'DIVX')
# 정수 형태로 변환하기 위해 round
w = round(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = round(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS) # 카메라에 따라 값이 정상적, 비정상적

# 웹캠으로 찰영한 영상을 저장하기
# cv2.VideoWriter 객체 생성, 기존에 받아온 속성값 입력
out = cv2.VideoWriter('output.avi', fourcc, fps, (w, h))


with mp_hands.Hands(
    model_complexity=0,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5) as hands:
    while cap.isOpened():
        success, image = cap.read()
        if not success:
          print("Ignoring empty camera frame.")
          # If loading a video, use 'break' instead of 'continue'.
          continue
        #out.write(image)

        # To improve performance, optionally mark the image as not writeable to
        # pass by reference.
        image.flags.writeable = False
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        results = hands.process(image)

        # Draw the hand annotations on the image.
        image.flags.writeable = True
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
        diff = 0
        if results.multi_hand_landmarks:
          for hand_landmarks in results.multi_hand_landmarks:
              thumb = hand_landmarks.landmark[4]
              index = hand_landmarks.landmark[8]

              diff = abs(index.x - thumb.x)
              print(diff)

              mp_drawing.draw_landmarks(
                image,
                hand_landmarks,
                mp_hands.HAND_CONNECTIONS,
                mp_drawing_styles.get_default_hand_landmarks_style(),
                mp_drawing_styles.get_default_hand_connections_style())
        # Flip the image horizontally for a selfie-view display.
        image = cv2.flip(image, 1)
        cv2.putText(
            image, text='Diff: %d' % ( int(diff * 1000)), org=(10, 30),
            fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1,
            color=255, thickness=2)
        cv2.imshow('MediaPipe Hands', image)
        if cv2.waitKey(1) == ord('q'):
            break
cap.release()
out.release()

 

반응형