Tello (드론)를 사용한 얼굴 인식 자동 추적 시스템

6126 단어 파이썬텔로OpenCV

소개



전문학교의 AI전공 2년째가 되는, 제작과제로 작성했습니다. (Qiita 첫 게시물)
얼굴 인식에 대해 더 깊이 알고 물건을 사용하여 더 즐겁게 할 수 있지 않을까라는 생각에서 드론을 사용한 얼굴 인식 시스템을 만들었습니다.

실제로 완성한 것의 동영상은 이쪽↓(함께 만든 친구입니다:허가 가지고 있습니다)
htps : // 꺄. 이 m / 9 네 100 아 8 개 f에서 c1b330c8 에c2d bd

1. 드론의 이륙·착륙·카메라의 기동



드론은 텔로를 사용하고 파이썬으로 제어하고 있습니다.
# telloへのアクセス用
tello_ip = '192.168.10.1'
tello_port = 8889
tello_address = (tello_ip, tello_port)

# telloからの受信用
VS_UDP_IP = '0.0.0.0'
VS_UDP_PORT = 11111

# VideoCapture用のオブジェクト準備
cap = None
# データ受信用のオブジェクト準備
response = None

# 通信用のソケットを作成
# ※アドレスファミリ:AF_INET(IPv4)、ソケットタイプ:SOCK_DGRAM(UDP)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# ビデオストリーミング開始
sent = sock.sendto(b'streamon', tello_address)

udp_video_address = 'udp://@' + VS_UDP_IP + ':' + str(VS_UDP_PORT)
if cap is None:
    cap = cv2.VideoCapture(udp_video_address)
if not cap.isOpened():
    cap.open(udp_video_address)

# 離陸
sent = sock.sendto(b'takeoff', tello_address)
time.sleep(10)

# qキーを押して着陸
    if cv2.waitKey(1) & 0xFF == ord('q'):
        sent = sock.sendto(b'land', tello_address)
        break


# ビデオストリーミング停止
sent = sock.sendto(b'streamoff', tello_address)

2.haarcascade를 사용한 얼굴 인식



이번에 드론 카메라로 얼굴 인식을 사용하고 싶기 때문에 haarcascade 파일을 사용했습니다.
움직이는 사이에, 화상 읽어들이기를 칼라가 아니고 흑백으로 하는 편이 제도가 올랐습니다.
cap = cv2.VideoCapture(0)
cascade_path = "haarcascade_frontalface_default.xml"
face_cascade = cv2.CascadeClassifier(cascade_path)

while(True):
    ret, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    faces = face_cascade.detectMultiScale(gray, 1.3, 5)

    for (x,y,w,h) in faces:
        frame = cv2.rectangle(gray,(x,y),(x+w,y+h),color,2)


cap.release()
cv2.destroyAllWindows()

참고로 한 사이트↓
htps : // m / mi x_dvd / ms / 98 fdc8c98bc7790b30

3. 추적 시스템



추적 시스템입니다만, 아래의 화상은 드론으로 비추는 영상이라고 생각해 주세요.
우선 화상의 중심점과 얼굴 인식의 중심점을 취해, 스스로 결정한 영역내에 들어가지 않았을 경우, 드론 조작으로 오른쪽으로 가거나 왼쪽으로 움직이고 있습니다.

또, 얼굴의 면적을 가져와서 지정한 사이즈보다 크면 뒤로 내려가거나, 작으면 앞으로 이동해 줍니다.


4.완성형



지금 현재의 드론 제어의, 전체 코드는 이런 느낌입니다

tello_tracking.py
import cv2
import socket
import threading
import boto3
import time

color = (0, 0, 0)

# telloへのアクセス用
tello_ip = '192.168.10.1'
tello_port = 8889
tello_address = (tello_ip, tello_port)

# telloからの受信用
VS_UDP_IP = '0.0.0.0'
VS_UDP_PORT = 11111

# VideoCapture用のオブジェクト準備
cap = None
# データ受信用のオブジェクト準備
response = None

# 通信用のソケットを作成
# ※アドレスファミリ:AF_INET(IPv4)、ソケットタイプ:SOCK_DGRAM(UDP)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# リッスン状態にする
sock.bind(('', tello_port))

cap = cv2.VideoCapture(0)
cascade_path = "haarcascade_frontalface_default.xml"
face_cascade = cv2.CascadeClassifier(cascade_path)

# データ受け取り用の関数
def recv():
    count = 0
    while True: 
        try:
            data, server = sock.recvfrom(1518)
            print(data.decode(encoding="utf-8"))
        except Exception:
            print ('\nExit . . .\n')
            break

# コマンドモードを使うため'command'というテキストを投げる
sent = sock.sendto(b'command', tello_address)


# ビデオストリーミング開始
sent = sock.sendto(b'streamon', tello_address)
print("streamon")
# time.sleep(10)qqqqq

udp_video_address = 'udp://@' + VS_UDP_IP + ':' + str(VS_UDP_PORT)
if cap is None:
    cap = cv2.VideoCapture(udp_video_address)
if not cap.isOpened():
    cap.open(udp_video_address)

# 離陸
sent = sock.sendto(b'takeoff', tello_address)
time.sleep(10)

#上に20cm
sent = sock.sendto(b'up 20', tello_address)
time.sleep(10)

#キャプチャ画面の中心点の取得
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
c_x = width//2
c_y = height//2
c_w = width//4
c_h = height//4


c_x_max = c_x + 50
c_x_min = c_x - 50

while(True):
    ret, frame = cap.read()

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    faces = face_cascade.detectMultiScale(gray, 1.3, 5)

    for (x,y,w,h) in faces:
        frame = cv2.rectangle(gray,(x,y),(x+w,y+h),color,2)

        a=x
        b=y
        c=x+w
        d=y+h

        face_area = h * w / 100

        f_x = (a+c)//2
        f_y = (b+d)//2


        print(face_area)   
        # print("center" , c_x, c_y)
        # print("face" , f_x, f_y)
        # print("width" , width)

        #追尾制御 横、前後移動
        if 0 < f_x < 370:

            #右に20cm
            sent = sock.sendto(b'left 20', tello_address)

        elif 590 < f_x < 960:

            #左に20cm
            sent = sock.sendto(b'right 20', tello_address)

        elif 100 < face_area < 200:
            #前に20cm
            sent = sock.sendto(b'forward 20', tello_address)

        elif 500 < face_area < 600:
            #後ろに20cm
            sent = sock.sendto(b'back 20', tello_address)


    cv2.imshow('frame', gray)
    # qキーを押して着陸
    if cv2.waitKey(1) & 0xFF == ord('q'):
        sent = sock.sendto(b'land', tello_address)
        break

cap.release()
cv2.destroyAllWindows()

# ビデオストリーミング停止
sent = sock.sendto(b'streamoff', tello_address)

time.sleep는 드론을 움직일 때 조금 시간이 걸리므로 단번에 명령을 보내면 잘 움직이지 않기 때문에 넣고 있습니다.

전체적으로 보기 어려운 부분이나 변수 등 사용하고 있습니다만 양해 바랍니다.

5.감상



팀 내에서 추적 시스템의 방안을 나누어 실현할 수 있었던 것이 좋았다.
드론을 사용하는 것이 처음으로, 처음에는 손질했지만, 제대로 추적할 수 있었을 때의 달성감이 있었던 것과, 제작해 즐거웠습니다.

앞으로도, 여러가지 제작한 것을 올려 가므로 잘 부탁드립니다.

좋은 웹페이지 즐겨찾기