본문 바로가기

메이커 프로젝트

얼굴 트래킹 레이저 건 메이킹 자료

1. 동작 영상

 

2. 아두이노 코드

#include<Servo.h>

int myArray[2];
byte* ddata = reinterpret_cast<byte*>(&myArray); // pointer for transferData()
size_t pcDataLen = sizeof(myArray);
bool newData=false;

Servo servo1; //servo1 변수 선언
Servo servo2; //servo2 변수 선언

int motor1 = 3; //motor1을 입출력 3번 핀에 연결
int motor2 = 5; //motor2을 입출력 5번 핀에 연결
int angle1 = 90; //초기 각도값 설정  
int angle2 = 90; //초기 각도값 설정

void setup() {
    Serial.begin(115200);//baudrate
    servo1.attach(motor1); //servo1에 입출력 3번 핀을 지정
    servo2.attach(motor2); //servo2에 입출력 5번 핀을 지정
    servo1.write(angle1);
    servo1.write(angle2);
    
}

void loop() {
    checkForNewData();
    if (newData == true) {
       servo1.write(myArray[1]);
       servo2.write(myArray[0]);
        newData = false;
    }
    }

void checkForNewData () {
    if (Serial.available() >= pcDataLen && newData == false) {
        byte inByte;
        for (byte n = 0; n < pcDataLen; n++) {
            ddata [n] = Serial.read();
        }
        newData = true;
    }
}

 

3. 아두이노 회로

- 서보모터 2개 3번, 5번

 

 

4. 모델링 파일 : 

https://www.thingiverse.com/thing:501701

 

Laser gun bracket by mandle

This is an attachable laser gun bracket for Arduino project made by laser pointer, two servo motors. you need 2*sg90(servo), glue gun. YouTube : http://youtu.be/v3RiZMpX2NM

www.thingiverse.com

- 원본은 싱기버스에서 stl 취득

- 틴커캐드에서 일부 유격 및 레이저 출력 파트 수정 후 출력

tracking laser bracket set(revised).stl
0.07MB

 

 

5. 조립과정

 

 

 

 

6. 얼굴인식 모델 : 깃허브 opencv haarcasades xml 파일 사용

https://github.com/opencv/opencv/tree/4.x/data/haarcascades

 

GitHub - opencv/opencv: Open Source Computer Vision Library

Open Source Computer Vision Library. Contribute to opencv/opencv development by creating an account on GitHub.

github.com

 

 

7. 파이썬 개발 환경안내

- vscode, anaconda 사용

- vscode 터미널 Command Prompt 사용(cmd)

- opencv 패키지 사용 

- pyseiral 패키지 사용

가상환경 구성 명령어 모음

conda create -n facedetection
conda activate facedetection
pip install opencv-python
pip install pyserial

 

8. 파이썬 코드 1 - 얼굴인식

 - 이해를 돕기위해 변수 및 함수명 한글 사용 

 - 일반전인 경우에서는 한글 사용 지양

### 얼굴인식.py

import cv2
print(cv2.__version__)

def 얼굴찾기(웹캠화면, 검출분류기, 이미지스케일, 최대검출갯수) :
    
    웹캠복사 = 웹캠화면.copy()
    흑백이미지 = cv2.cvtColor(웹캠복사, cv2.COLOR_BGR2GRAY)
    검출된얼굴들 = 검출분류기.detectMultiScale(흑백이미지, 이미지스케일, 최대검출갯수) #검출된 얼굴들 -> (x, y, w, h) 값으로 출력
    얼굴출력 = []
    
    선두께 = 2
    선색깔 = (255, 0, 255)
    for (x,y,w,h) in 검출된얼굴들 :
        cv2.rectangle(웹캠복사, (x, y), (x+w, y+h), 선색깔, 선두께)
        얼굴출력.append([[x,y,w,h], w*h])

    얼굴출력 = sorted(얼굴출력, key = lambda x:x[1], reverse = True)
    
    return 웹캠복사, 얼굴출력


def main():
    프레임너비 = 640
    프레임높이 = 480
    검출분류기 = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
    캡쳐 = cv2.VideoCapture(0)

    while True :
        _, 웹캠화면 = 캡쳐.read()
        웹캠화면 = cv2.resize(웹캠화면, (프레임너비, 프레임높이))    
        웹캠복사, 얼굴출력 = 얼굴찾기(웹캠화면, 검출분류기, 1.1, 4)

        cv2.imshow("결과창", 웹캠복사)   
        if cv2.waitKey(1) == ord('q') : 
            break


if __name__ == "__main__" :
    main()

- 실행코드 : anaconda 가상환경에서 cmd 터미널에서 실행

python 얼굴인식.py

- 실행 확인

 

 

 

9. 파이썬 코드 - 얼굴 인식 좌표 시리얼 통신 송신 코드

- 파이썬 코드

### 얼굴트랙킹.py

import 얼굴인식
import time
import cv2
import numpy as np
import serial
from struct import *
ser = serial.Serial('COM21',115200)
perrorLR, perrorUD = 0, 0
cnt = 0

def 중앙찾기(웹캠복사, 얼굴출력):
    엑스중앙좌표, 와이중앙좌표 = -1, -1
    선두께 = 2
    선색깔 = (0, 255, 0)

    if len(얼굴출력) != 0:
        x, y, w, h = 얼굴출력[0][0]
        엑스중앙좌표 = x + w//2
        와이중앙좌표 = y + h//2
        cv2.circle(웹캠복사, (엑스중앙좌표, 와이중앙좌표), 선두께, 선색깔, cv2.FILLED)

        프레임높이, 프레임너비, 컬러가지수 = 웹캠복사.shape   # print(웹캠복사.shape) -> (480, 640, 3)

        cv2.line(웹캠복사, (프레임너비//2, 와이중앙좌표), (엑스중앙좌표, 와이중앙좌표), 선색깔, 선두께//2)
        cv2.line(웹캠복사, (엑스중앙좌표, 프레임높이//2), (엑스중앙좌표, 와이중앙좌표), 선색깔, 선두께//2)


    return 엑스중앙좌표, 와이중앙좌표, 웹캠복사


def 얼굴추적(엑스중앙좌표, 와이중앙좌표, 너비, 높이) :

    global perrorLR, perrorUD, cnt

    KLR = [0.6, 0.1]
    KUD = [0.6, 0.1]

    
    if 엑스중앙좌표 != -1:
        # 좌우 편차 계산
        errorLR = 너비//2 - 엑스중앙좌표
        posX = KLR[0] * errorLR +KLR[1] * (errorLR-perrorLR)
        posX = int(np.interp(posX, [-너비//2, 너비//2], [20, 160]))
        perrorLR = errorLR
        

        # 위아래 편차 계산
        errorUD = 높이//2 - 와이중앙좌표
        posY = KUD[0] * errorUD +KUD[1] * (errorUD-perrorUD)
        posY = int(np.interp(posY, [-너비//2, 너비//2], [20, 160]))
        perrorUD = errorUD
        

        # 서보모터 X,Y 각도 확인 -> 정 가운데 -> X, Y = 90, 90
        if cnt == 10 : 
            print("y값 : ", posY)
            print("x값 : ", posX)
            ser.write(pack('2h',posX, posY))
        else : 
            cnt+=1

def main():
    프레임너비 = 640
    프레임높이 = 480
    검출분류기 = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
    캡쳐 = cv2.VideoCapture(0)

    while True :
        _, 웹캠화면 = 캡쳐.read()
        웹캠화면 = cv2.resize(웹캠화면, (프레임너비, 프레임높이))    
        웹캠복사, 얼굴출력 = 얼굴인식.얼굴찾기(웹캠화면, 검출분류기, 1.1, 4)

        엑스중앙좌표, 엑스와이좌표, 웹캠복사 = 중앙찾기(웹캠복사, 얼굴출력)

        얼굴추적(엑스중앙좌표, 엑스와이좌표, 프레임너비, 프레임높이)
        

        cv2.line(웹캠복사, (0, 프레임높이//2), (프레임너비, 프레임높이//2), (0, 0, 255), 2)
        cv2.line(웹캠복사, (프레임너비//2, 0), (프레임너비//2, 프레임높이), (0, 0, 255), 2)

        cv2.imshow("결과창", 웹캠복사)   
        if cv2.waitKey(1) == ord('q') : 
            break

if __name__ == "__main__" :
    main()

 

- 실행 확인 : 위 영상 확인 

 

 

끝.

 

작성날짜 ; 22.11.08

작성자 : 성원경 / 경기기계공업고등학교 항공드론과 교사