1. AI 드론 프로그래밍
김 종 현
jhkim3217@gmail.com
2024. 2.
대전대학교 특강
2. 강의 내용
• DJI Tello 드론 기초
• 드론의 종류, 비행원리, Tello 드론 구성요소(HW, SW) 등
• 드론 앱을 사용한 드론 비행 기초 실습
• 드론 비행시 주의 할 점
• Tello SDK를 이용한 파이썬 코딩(1)
• DJITelloPy 모듈
• 기본 동작 제어
• takeoff, land, up/down, forward/backward, cw/ ccw 등
• 키보드 제어
• Tello SDK를 이용한 파이썬 코딩(2)
• OpenCV 기초
• 드론 카메라 이미지 캡쳐 및 저장
• 드론 동영상 전송 및 저장
• 파이썬 기반 AI 드론 코딩
• Cascade Classifier를 이용한 안면 인식
• 드론 제어
• following me 드론 제작
• 팀 프로젝트 : 창의적인 AI 드론 제작
38. 드론 비디오 촬영, 전송
from djitellopy import tello
import cv2
import time
tello = tello.Tello()
tello.connect()
battery_level = tello.get_battery()
print(f"Battery Life Percentage: {battery_level}")
time.sleep(2)
print("Turn Video Stream On")
tello.streamon()
# read a single image from the Tello video feed
print("Read Tello Image")
frame_read = tello.get_frame_read()
print(type(frame_read))
time.sleep(2)
while True:
# read a single image from the Tello video feed
print("Read Tello Image")
tello_video_image = frame_read.frame
# use opencv to write image
if tello_video_image is not None:
cv2.imshow("TelloVideo", tello_video_image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
tello.streamoff()
cv2.destroyWindow('TelloVideo')
cv2.destroyAllWindows()
45. Opencv로 드론 비디오 읽기, 보기
from djitellopy import tello
import cv2
import time
tello = tello.Tello()
tello.connect()
battery_level = tello.get_battery()
print(battery_level)
print("Turn Video Stream On")
tello.streamon()
time.sleep(2)
while True:
# read a single image from the Tello video feed
frame_read = tello.get_frame_read()
tello_video_image = frame_read.frame
# 이미지 크기 조정 “ resize()
image = cv2.resize(tello_video_image, (360, 240))
# use opencv to write image
if image is not None:
cv2.imshow("TelloVideo", image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
tello.streamoff()
cv2.destroyWindow('TelloVideo')
cv2.destroyAllWindows()
46. 드론 비디오 촬영, 전송 : Opencv 키보드 제어
from djitellopy import tello
import cv2
import time
tello = tello.Tello()
tello.connect()
battery_level =
tello.get_battery()
print(battery_level)
time.sleep(2)
tello.streamon()
frame_read =
tello.get_frame_read()
while True:
frame = frame_read.frame
frame = cv2.resize(frame, (360*2, 240*2)) # 이미지 크기
조정
while True:
frame = frame_read.frame
if frame is not None:
cv2.imshow("TelloVideo", frame)
k = cv2.waitKey(5) & 0xFF
if k == ord('q'):
break
elif k == ord('t'):
tello.takeoff()
elif k == ord('u'):
tello.move_up(50)
elif k == ord('c'):
tello.rotate_clockwise(360)
elif k == ord('l'):
tello.land()
else :
print(‘no key!!!’)
tello.streamoff()
cv2.destroyWindow('TelloVideo')
cv2.destroyAllWindows()
48. 드론이 촬영/저장 하면서 동시에 비행하기 : 쓰레드(Thread)
import time, cv2
from threading import Thread
from djitellopy import Tello
tello = Tello()
tello.connect()
battery_level = tello.get_battery()
print(battery_level)
keepRecording = True
tello.streamon()
frame_read = tello.get_frame_read()
def videoRecorder():
height, width, _ = frame_read.frame.shape
# create a VideoWrite object, recoring to ./video.avi
video = cv2.VideoWriter('video3.avi', cv2.VideoWriter_fourcc(*'XVID'), 30, (width, height))
while keepRecording:
tello_video_image = frame_read.frame
tello_video_image = cv2.resize(tello_video_image, (360 * 2, 240 * 2))
# PC에 Tello 촬영 동영상 저장
video.write(frame_read.frame)
if tello_video_image is not None:
cv2.imshow('video', tello_video_image)
time.sleep(1 / 30)
if cv2.waitKey(1) & 0xFF == ord('q'):
cv2.destroyWindow('video')
cv2.destroyAllWindows()
# we need to run the recorder in a seperate thread
recorder = Thread(target=videoRecorder)
recorder.start()
tello.takeoff()
tello.move_up(30)
tello.rotate_counter_clockwise(360)
tello.land()
keepRecording = False
recorder.join()
• 소스 코드 다운로드 : https://drive.google.com/file/d/1jZD-DjCZK8cVg1r-20hhr4-RcYzW9-5-/view?usp=sharing
57. 인식된 얼굴 중심점(cx, cy)과 전체 프레임 중심점(tcx, tcy) 차이
import cv2
from djitellopy import tello
tello = tello.Tello()
tello.connect()
battery_level = tello.get_battery()
print(battery_level)
tello.streamon()
while True:
img = tello.get_frame_read().frame
img = cv2.resize(img, (360*2, 240*2))
faceCascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(imgGray, 1.3, 5)
if len(faces) == 1:
print("face found")
print('faces', faces)
else:
print("face not found")
# 전체 화면의 중심점(center)
tcx = 360
tcy = 240
cv2.circle(img, (tcx, tcy), 10, (255, 0, 0), cv2.FILLED)
# 인식된 얼굴 사각형 박스 그리기
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
cx = x + w // 2
cy = y + h // 2
area = w * h
cv2.circle(img, (cx, cy), 10, (0, 255, 0), cv2.FILLED)
print('area =', area)
# 전체 이미지 중심과 얼굴 이지미 중심 간의 선 그리기기
cv2.line(img, (cx, cy), (tcx, tcy), (255, 0, 0), 2)
cv2.imshow('frame',img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
tello.streamoff()
cv2.destroyAllWindows()
58. forward/ backward 제어
# 얼굴 이미지 크기 : z_area = offset_z
offset_z = w * h
# 얼굴 이미지 크기 update 및 forward/ backward 제어
def adjust_tello_position(offsetz):
f not 15000 <= offset_z <= 30000 and offset_z != 0:
if offset_z < 15000:
tello.move_forward(20)
elif offset_z > 30000:
tello.move_back(20)
실습 소스 : https://drive.google.com/file/d/1fJn9bOhB9cEKs71fDCtqzvWxQfNcb4z5/view?usp=sharing
59. left/ right 제어
offset_x = face_center_x - center_x
def adjust_tello_position(offset_x):
"""
Adjusts the position of the tello drone based on the offset values given from th
e frame
:param offset_x: Offset between center and face x coordinates
"""
if not -90 <= offset_x <= 90 and offset_x != 0:
# offset_x가 음수이면 시계 반대 방향으로 일정 거리 만큼 이동
if offset_x < 0:
tello.rotate_counter_clockwise(10)
# offset_x가 양수이면 시계 방향으로 일정 거리 만큼 이동
elif offset_x > 0:
tello.rotate_clockwise(10)
실습 소스 : https://drive.google.com/file/d/1WXTTag3aDv66SXSCYzapRxOcCA3PNnSK/view?usp=sharing
60. up/ down 제어
# Add 30 so that the drone covers as much of the subject as possible
offset_y = face_center_y - center_y - 30
"""
Adjusts the position of the tello drone based on the offset values given
from the frame
:param offset_y: Offset between center and face y coordinates
"""
if not -70 <= offset_y <= 70 and offset_y != -30:
if offset_y < 0:
print('move up')
tello.move_up(20)
elif offset_y > 0:
print('move down')
tello.move_down(20)
실습 소스 : https://drive.google.com/file/d/1WXTTag3aDv66SXSCYzapRxOcCA3PNnSK/view?usp=sharing
61. Face following 제어
소스 코드 : https://drive.google.com/file/d/1f4Xcq8W4HL7tRSILb-hXrV9Jd-gywPPp/view?usp=sharing
62. Face Detection AI 알고리즘
• Haar Cascade
• https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcas
cade_frontalface_default.xml
• Dlib : HOG + CNN
• https://github.com/davisking/dlib
• MTCNN
• https://github.com/ipazc/mtcnn
• OpenCV DNN : Caffe based DNN
• https://github.com/opencv/opencv/tree/master/samples/dnn/face_detector
• YOLO
• https://velog.io/@hhhong/Object-Detection-with-YOLO
63. AI 드론 프로젝트
• PID 제어
• https://github.com/ivmech/ivPID
• Custom 훈련 데이터
• 전이학습(fine tuning)
• PoseNet
• 제스쳐 인식 제어
• Dlib
• facial landmark 탐지
• YOLO
• 실시간 객체 탐지
64. 손 제스쳐 기반 드론 제어
• MediaPipe
• https://google.github.io/mediapipe/