As a makerfaire project, I worked with a friend to build a quadcopter with some search-and-rescue features. The quadcopter’s FPV video is processed by OpenCV to detect humans in the vicinity.
To build the quadcopter, we followed a guide for 3D printing and assembling a Tiny Whoop quadcopter. To maximize the flying time, we carefullly chose the lightest possible components and optimal batteries. The quadcopter contains a FPV camera that streams video to the receiver, where it is displayed on a low-latency monitor for the pilot and fed to a laptop for processing using computer vision. After tuning the PID parameters to stabilize the quadcopter’s flight, we adapted a Python script that detects humans in the video using the computer vision library OpenCV.
We also presented the project at Northwestern University’s High School Project Showcase, where it received a first-place award in engineering projects.
Here is the Python code we used followed by some photos of the components.
from imutils.object_detection import non_max_suppression from imutils import paths import numpy as np import imutils import cv2 screen_size=(1920,1080) cap = cv2.VideoCapture(0) hog = cv2.HOGDescriptor() hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) frame = 0 cv2.namedWindow("Result",cv2.WND_PROP_FULLSCREEN) cv2.setWindowProperty("Result",cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN) while cap.isOpened(): ret, image = cap.read() frame += 1 if (frame % 5 == 0): frame = 0 image = imutils.resize(image, width=min(300, image.shape)) orig = image.copy() # detect people in the image (rects, weights) = hog.detectMultiScale(image, winStride=(4, 4),padding=(8, 8), scale=1.05) # draw bounding boxes for (x, y, w, h) in rects: cv2.rectangle(orig, (x, y), (x + w, y + h), (0, 0, 255), 2) rects = np.array([[x, y, x + w, y + h] for (x, y, w, h) in rects]) pick = non_max_suppression(rects, probs=None, overlapThresh=0.65) for (xA, yA, xB, yB) in pick: cv2.rectangle(image, (xA, yA), (xB, yB), (0, 255, 0), 2) # show the output images cv2.imshow("Result", cv2.resize(image, screen_size)) key=cv2.waitKey(1) # ms delay if key==27: cap.release() cv2.destroyAllWindows() break cap.release() cv2.destroyAllWindows()