본문 바로가기

메이킹/아두이노

Hand Gesture로 아두이노 제어하기(LED 밝기 제어)

반응형

저번 시간에 배운 MediaPipe를 활용한 프로젝트 수업입니다.

https://mediapipe.readthedocs.io/en/latest/solutions/hands.html

 

1) MediaPipe를 이용한 손가락 제스처에 따른 크기 조절

- 엄지 손가락(4번)과 두번째 손가락(8번)을 좁혔다가 벌렸다 하는 제스처에 따라 두 손가락 끝의 점의 길이를 측정하여 화면에 출력해주는 소스코드입니다.

- Vscode를 실행하고 'Open Folder'(폴더열기)를 선택하여 'ArduinoHandgesture'폴더를 새로 만들고 그 안에 'HandGestureVolume.py' 파일을 새로 생성합니다.

 

소스코드

import cv2
import mediapipe as mp
import pyautogui

x1 = y1 = x2 = y2 = 0
webcam=cv2.VideoCapture(0)
my_hands = mp.solutions.hands.Hands()
drawing_utils = mp.solutions.drawing_utils


while True:
    _, image = webcam.read()
    image = cv2.flip(image, 1)
    frame_height, frame_width, _ = image.shape
    rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    output = my_hands.process(rgb_image)
    hands = output.multi_hand_landmarks

    if hands:
        for hand in hands:
            drawing_utils.draw_landmarks(image, hand)
            landmarks = hand.landmark
            for id, landmark in enumerate(landmarks):
                x = int(landmark.x * frame_width)
                y = int(landmark.y * frame_height)

                if id == 8:
                    cv2.circle(img=image, center=(x,y), radius=8, color=(0,255,255), thickness=3)
                    x1 = x
                    y1 = y
                if id == 4:
                    cv2.circle(img=image, center=(x, y), radius=8, color=(0,0,255), thickness=3)
                    x2 = x
                    y2 = y

        dist = ((x2-x1)**2 + (y2-y1)**2)**(0.5)//4
        cv2.line(image, (x1,y1), (x2, y2), (0, 255,0), 5)
        print(dist)
        if dist > 50 :
            pyautogui.press("volumeup")
        else:
            pyautogui.press("volumedown")

    cv2.imshow("Img", image)
    key = cv2.waitKey(10)

    if key == 27: #esc key
        break

webcam.release()
cv2.destroyAllWindows()

 

-   'esc'키를 치면 실행이 종료됩니다.

 

- 결과

 

 

2) 손가락 제스처에 따라 LED밝기 조절하기

- 회로도

led를 3번 핀에 연결

 

소스코드

- 아두이노 코드

const int ledPin=3;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop() {

  while(Serial.available()>0){
    int val=Serial.parseInt();
    if(Serial.read()=='\n'){
      val=constrain(val,0,255);
      analogWrite(ledPin, val);
      Serial.print(val);
    }
  }
}

 

- 아두이노 '포트번호를 확인'하고 파이썬 코드에서 수정합니다.

 

- 파이썬 코드

import cv2
import mediapipe as mp
import pyautogui
import serial

x1 = y1 = x2 = y2 = 0
webcam=cv2.VideoCapture(0)
my_hands = mp.solutions.hands.Hands()
drawing_utils = mp.solutions.drawing_utils

arduino = serial.Serial('COM26', 9600)
arduino.timeout = 1

while True:   
    _, image = webcam.read()
    image = cv2.flip(image, 1)
    frame_height, frame_width, _ = image.shape
    rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    output = my_hands.process(rgb_image)
    hands = output.multi_hand_landmarks

    if hands:
        for hand in hands:
            drawing_utils.draw_landmarks(image, hand)
            landmarks = hand.landmark
            for id, landmark in enumerate(landmarks):
                x = int(landmark.x * frame_width)
                y = int(landmark.y * frame_height)

                if id == 8:
                    cv2.circle(img=image, center=(x,y), radius=8, color=(0,255,255), thickness=3)
                    x1 = x
                    y1 = y
                if id == 4:
                    cv2.circle(img=image, center=(x, y), radius=8, color=(0,0,255), thickness=3)
                    x2 = x
                    y2 = y

        dist = ((x2-x1)**2 + (y2-y1)**2)**(0.5)//4
        cv2.line(image, (x1,y1), (x2, y2), (0, 255,0), 5)

        # if dist > 50 :
        #     pyautogui.press("volume up")
        # else:
        #     pyautogui.press("volume down")

        d = int((dist/70)*255)
        print(dist, d)
                
        e='\n'
        if 0<d<256:
            cv2.putText(image, str(d), (40, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 0, 0), 3)
            arduino.write(str(d).encode())
            arduino.write(e.encode())

    cv2.imshow("Img", image)
    key = cv2.waitKey(10)

    if key == 27: #esc key
        break

webcam.release()
cv2.destroyAllWindows()

 

- 결과

 

반응형

'메이킹 > 아두이노' 카테고리의 다른 글

심장박동 센서 활용하기  (0) 2024.06.25
ESP32 와 ESP8266 차이점 비교  (0) 2024.05.23
Mediapipe로 HandTracking 하여 LED 제어하기  (0) 2024.04.17
4x4 키패드 활용하기  (0) 2024.04.11
DS1302 RTC(Real Time Clock)  (0) 2024.04.05