# USAGE
# python opencv_yolo.py --yolo yolo-coco
# python opencv_yolo.py --video dashcam_boston.mp4 --tracker csrt --yolo yolo-coco

# import the necessary packages
import os
import numpy as np
from imutils.video import VideoStream
from imutils.video import FPS
import argparse
import imutils
import time
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video", type=str,
                help="path to input video file")
ap.add_argument("-t", "--tracker", type=str, default="kcf",
                help="OpenCV object tracker type")
ap.add_argument("-y", "--yolo", required=True,
                help="base path to YOLO directory")
ap.add_argument("-c", "--confidence", type=float, default=0.5,
                help="minimum probability to filter weak detections")
ap.add_argument("--threshold", type=float, default=0.3,
                help="threshold when applyong non-maxima suppression")
args = vars(ap.parse_args())

# load the COCO class labels our YOLO model was trained on
labelsPath = os.path.sep.join([args["yolo"], "coco.names"])
LABELS = open(labelsPath).read().strip().split("\n")

# initialize a list of colors to represent TWO possible class labels
np.random.seed(42)
COLORS = np.random.randint(0, 255, size=(2, 3),
                           dtype="uint8")

# derive the paths to the YOLO weights and model configuration
weightsPath = os.path.sep.join([args["yolo"], "yolov3.weights"])
configPath = os.path.sep.join([args["yolo"], "yolov3.cfg"])

# load our YOLO object detector trained on COCO dataset (80 classes)
# and determine only the *output* layer names that we need from YOLO
print("[INFO] loading YOLO from disk...")
net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)
ln = net.getLayerNames()
ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]

# initialize the video stream and frame dimensions
if not args.get("video", False):
    # if a video path was not supplied, grab the reference
    # to the webcam
    vs = VideoStream(src=0).start()
else:
    # otherwise, grab a reference to the video file
    vs = cv2.VideoCapture(args["video"])
writer = None
(W, H) = (None, None)

# define the lower and upper boundaries of the "red"
# boundaries in the HSV color space
redLower = (157, 33, 142)
redUpper = (224, 255, 255)

# initialize the two classes we care about
BIRD_CLASS_ID = 14
PERSON_CLASS_ID = 0

# initialize a dictionary that maps strings to their corresponding
# OpenCV object tracker implementations
OPENCV_OBJECT_TRACKERS = {
    "csrt": cv2.TrackerCSRT_create,
    "kcf": cv2.TrackerKCF_create,
    "boosting": cv2.TrackerBoosting_create,
    "mil": cv2.TrackerMIL_create,
    "tld": cv2.TrackerTLD_create,
    "medianflow": cv2.TrackerMedianFlow_create,
    "mosse": cv2.TrackerMOSSE_create
}
tracker = OPENCV_OBJECT_TRACKERS[args["tracker"]]()

# initialize the bounding box coordinates of the object we are going
# to track
initBB = None

# if a video path was not supplied, grab the reference to the web cam
if not args.get("video", False):
    print("[INFO] starting video stream...")
    vs = VideoStream(src=0).start()
    time.sleep(1.0)

# otherwise, grab a reference to the video file
else:
    vs = cv2.VideoCapture(args["video"])

# initialize the FPS throughput estimator
fps = None

# loop over frames from the video stream
while True:
    # grab the current frame, then handle if we are using a
    # VideoStream or VideoCapture object
    frame = vs.read()
    frame = frame[1] if args.get("video", False) else frame

    # check to see if we have reached the end of the stream
    if frame is None:
        break

    # resize the frame (so we can process it faster) and grab the
    # frame dimensions
    frame = imutils.resize(frame, width=500)
    (H, W) = frame.shape[:2]

    # blur the frame and convert it to the HSV color space
    blurred = cv2.GaussianBlur(frame, (11, 11), 0)
    hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)

    # construct a mask for the color "red", then perform
    # a series of dilations and erosions to remove any small
    # blobs left in the mask
    mask = cv2.inRange(hsv, redLower, redUpper)
    mask = cv2.erode(mask, None, iterations=2)
    mask = cv2.dilate(mask, None, iterations=2)

    # find contours in the mask and initialize the current
    # (x, y) center of the red boundary
    cnts = cv2.findContours(
        mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    boundaryCenter = None

    # only proceed if at least one contour was found
    if len(cnts) > 0:
        # find the largest contour in the mask, then use
        # it to compute the minimum enclosing circle and
        # centroid
        c = max(cnts, key=cv2.contourArea)
        ((x, y), radius) = cv2.minEnclosingCircle(c)
        M = cv2.moments(c)
        boundaryCenter = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
        # print(f"DANGER: RED BOUNDARY DETECTED AT {boundaryCenter}")

    # check to see if we are currently tracking an object
    if initBB is not None:
        # grab the new bounding box coordinates of the object
        (success, box) = tracker.update(frame)

        # check to see if the tracking was a success
        if success:
            (x, y, w, h) = [int(v) for v in box]
            cv2.rectangle(frame, (x, y), (x + w, y + h),
                          (0, 255, 0), 2)

            # update the FPS counter
            fps.update()
            fps.stop()

            # initialize the set of information we'll be displaying on
            # the frame
            info = [
                ("Tracker", args["tracker"]),
                ("Success", "Yes" if success else "No"),
                ("FPS", "{:.2f}".format(fps.fps())),
            ]

            # loop over the info tuples and draw them on our frame
            for (i, (k, v)) in enumerate(info):
                text = "{}: {}".format(k, v)
                cv2.putText(frame, text, (10, H - ((i * 20) + 20)),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)

        else:
            initBB = None

    # show the output frame
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF

    if not initBB or not success:
        # construct a blob from the input frame and then perform a forward
        # pass of the YOLO object detector, giving us our bounding boxes
        # and associated probabilities
        blob = cv2.dnn.blobFromImage(
            frame, 1 / 255.0, (416, 416), swapRB=True, crop=False)
        net.setInput(blob)
        start = time.time()
        layerOutputs = net.forward(ln)
        end = time.time()

        # initialize our lists of detected bounding boxes, confidences,
        # and class IDs, respectively
        boxes = []
        confidences = []
        classIDs = []

        # loop over each of the layer outputs
        for output in layerOutputs:
            # loop over each of the detections
            for detection in output:
                # extract the class ID and confidence (i.e., probability)
                # of the current object detection
                scores = detection[5:]
                classID = np.argmax(scores)
                confidence = scores[classID]

                # filter out weak predictions by ensuring the detected
                # probability is greater than the minimum probability
                if confidence > args["confidence"] and classID in {BIRD_CLASS_ID, PERSON_CLASS_ID}:
                    # scale the bounding box coordinates back relative to
                    # the size of the image, keeping in mind that YOLO
                    # actually returns the center (x, y)-coordinates of
                    # the bounding box followed by the boxes' width and
                    # height
                    box = detection[0:4] * np.array([W, H, W, H])
                    (centerX, centerY, width, height) = box.astype("int")

                    # use the center (x, y)-coordinates to derive the top
                    # and and left corner of the bounding box
                    x = int(centerX - (width / 2))
                    y = int(centerY - (height / 2))

                    # update our list of bounding box coordinates,
                    # confidences, and class IDs
                    boxes.append([x, y, int(width), int(height)])
                    confidences.append(float(confidence))
                    classIDs.append(classID)

        # apply non-maxima suppression to suppress weak, overlapping
        # bounding boxes
        idxs = cv2.dnn.NMSBoxes(
            boxes, confidences, args["confidence"], args["threshold"])

        # ensure at least one detection exists
        if len(idxs) > 0:
            # loop over the indexes we are keeping
            for i in idxs.flatten():
                # extract the bounding box coordinates
                (x, y) = (boxes[i][0], boxes[i][1])
                (w, h) = (boxes[i][2], boxes[i][3])

                # draw a bounding box rectangle and label on the frame
                color = [int(c) for c in COLORS[0 if classIDs[i]
                                                == PERSON_CLASS_ID else 1]]
                cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
                text = "{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i])
                cv2.putText(frame, text, (x, y - 5),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)

                if (classIDs[i] == BIRD_CLASS_ID):
                    initBB = tuple(boxes[i])

                    # start OpenCV object tracker using the supplied bounding box
                    # coordinates, then start the FPS throughput estimator as well
                    tracker = OPENCV_OBJECT_TRACKERS[args["tracker"]]()
                    tracker.init(frame, initBB)
                    fps = FPS().start()
                else:
                    print("Human detected!\n")

        # if the `q` key was pressed, break from the loop
    if key == ord("q"):
        break

# if we are using a webcam, release the pointer
if not args.get("video", False):
    vs.stop()

# otherwise, release the file pointer
else:
    vs.release()

# close all windows
cv2.destroyAllWindows()

71b0d8af75a890d92618dc0f0dff4c8bf9c0b9c3
<mask token>

<mask token>
ap.add_argument('-v', '--video', type=str, help='path to input video file')
ap.add_argument('-t', '--tracker', type=str, default='kcf', help=
    'OpenCV object tracker type')
ap.add_argument('-y', '--yolo', required=True, help=
    'base path to YOLO directory')
ap.add_argument('-c', '--confidence', type=float, default=0.5, help=
    'minimum probability to filter weak detections')
ap.add_argument('--threshold', type=float, default=0.3, help=
    'threshold when applyong non-maxima suppression')
<mask token>
np.random.seed(42)
<mask token>
print('[INFO] loading YOLO from disk...')
<mask token>
if not args.get('video', False):
    vs = VideoStream(src=0).start()
else:
    vs = cv2.VideoCapture(args['video'])
<mask token>
if not args.get('video', False):
    print('[INFO] starting video stream...')
    vs = VideoStream(src=0).start()
    time.sleep(1.0)
else:
    vs = cv2.VideoCapture(args['video'])
<mask token>
while True:
    frame = vs.read()
    frame = frame[1] if args.get('video', False) else frame
    if frame is None:
        break
    frame = imutils.resize(frame, width=500)
    H, W = frame.shape[:2]
    blurred = cv2.GaussianBlur(frame, (11, 11), 0)
    hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, redLower, redUpper)
    mask = cv2.erode(mask, None, iterations=2)
    mask = cv2.dilate(mask, None, iterations=2)
    cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.
        CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    boundaryCenter = None
    if len(cnts) > 0:
        c = max(cnts, key=cv2.contourArea)
        (x, y), radius = cv2.minEnclosingCircle(c)
        M = cv2.moments(c)
        boundaryCenter = int(M['m10'] / M['m00']), int(M['m01'] / M['m00'])
    if initBB is not None:
        success, box = tracker.update(frame)
        if success:
            x, y, w, h = [int(v) for v in box]
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
            fps.update()
            fps.stop()
            info = [('Tracker', args['tracker']), ('Success', 'Yes' if
                success else 'No'), ('FPS', '{:.2f}'.format(fps.fps()))]
            for i, (k, v) in enumerate(info):
                text = '{}: {}'.format(k, v)
                cv2.putText(frame, text, (10, H - (i * 20 + 20)), cv2.
                    FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
        else:
            initBB = None
    cv2.imshow('Frame', frame)
    key = cv2.waitKey(1) & 255
    if not initBB or not success:
        blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416), swapRB=
            True, crop=False)
        net.setInput(blob)
        start = time.time()
        layerOutputs = net.forward(ln)
        end = time.time()
        boxes = []
        confidences = []
        classIDs = []
        for output in layerOutputs:
            for detection in output:
                scores = detection[5:]
                classID = np.argmax(scores)
                confidence = scores[classID]
                if confidence > args['confidence'] and classID in {
                    BIRD_CLASS_ID, PERSON_CLASS_ID}:
                    box = detection[0:4] * np.array([W, H, W, H])
                    centerX, centerY, width, height = box.astype('int')
                    x = int(centerX - width / 2)
                    y = int(centerY - height / 2)
                    boxes.append([x, y, int(width), int(height)])
                    confidences.append(float(confidence))
                    classIDs.append(classID)
        idxs = cv2.dnn.NMSBoxes(boxes, confidences, args['confidence'],
            args['threshold'])
        if len(idxs) > 0:
            for i in idxs.flatten():
                x, y = boxes[i][0], boxes[i][1]
                w, h = boxes[i][2], boxes[i][3]
                color = [int(c) for c in COLORS[0 if classIDs[i] ==
                    PERSON_CLASS_ID else 1]]
                cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
                text = '{}: {:.4f}'.format(LABELS[classIDs[i]], confidences[i])
                cv2.putText(frame, text, (x, y - 5), cv2.
                    FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
                if classIDs[i] == BIRD_CLASS_ID:
                    initBB = tuple(boxes[i])
                    tracker = OPENCV_OBJECT_TRACKERS[args['tracker']]()
                    tracker.init(frame, initBB)
                    fps = FPS().start()
                else:
                    print('Human detected!\n')
    if key == ord('q'):
        break
if not args.get('video', False):
    vs.stop()
else:
    vs.release()
cv2.destroyAllWindows()

<mask token>
ap = argparse.ArgumentParser()
ap.add_argument('-v', '--video', type=str, help='path to input video file')
ap.add_argument('-t', '--tracker', type=str, default='kcf', help=
    'OpenCV object tracker type')
ap.add_argument('-y', '--yolo', required=True, help=
    'base path to YOLO directory')
ap.add_argument('-c', '--confidence', type=float, default=0.5, help=
    'minimum probability to filter weak detections')
ap.add_argument('--threshold', type=float, default=0.3, help=
    'threshold when applyong non-maxima suppression')
args = vars(ap.parse_args())
labelsPath = os.path.sep.join([args['yolo'], 'coco.names'])
LABELS = open(labelsPath).read().strip().split('\n')
np.random.seed(42)
COLORS = np.random.randint(0, 255, size=(2, 3), dtype='uint8')
weightsPath = os.path.sep.join([args['yolo'], 'yolov3.weights'])
configPath = os.path.sep.join([args['yolo'], 'yolov3.cfg'])
print('[INFO] loading YOLO from disk...')
net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)
ln = net.getLayerNames()
ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]
if not args.get('video', False):
    vs = VideoStream(src=0).start()
else:
    vs = cv2.VideoCapture(args['video'])
writer = None
W, H = None, None
redLower = 157, 33, 142
redUpper = 224, 255, 255
BIRD_CLASS_ID = 14
PERSON_CLASS_ID = 0
OPENCV_OBJECT_TRACKERS = {'csrt': cv2.TrackerCSRT_create, 'kcf': cv2.
    TrackerKCF_create, 'boosting': cv2.TrackerBoosting_create, 'mil': cv2.
    TrackerMIL_create, 'tld': cv2.TrackerTLD_create, 'medianflow': cv2.
    TrackerMedianFlow_create, 'mosse': cv2.TrackerMOSSE_create}
tracker = OPENCV_OBJECT_TRACKERS[args['tracker']]()
initBB = None
if not args.get('video', False):
    print('[INFO] starting video stream...')
    vs = VideoStream(src=0).start()
    time.sleep(1.0)
else:
    vs = cv2.VideoCapture(args['video'])
fps = None
while True:
    frame = vs.read()
    frame = frame[1] if args.get('video', False) else frame
    if frame is None:
        break
    frame = imutils.resize(frame, width=500)
    H, W = frame.shape[:2]
    blurred = cv2.GaussianBlur(frame, (11, 11), 0)
    hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, redLower, redUpper)
    mask = cv2.erode(mask, None, iterations=2)
    mask = cv2.dilate(mask, None, iterations=2)
    cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.
        CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    boundaryCenter = None
    if len(cnts) > 0:
        c = max(cnts, key=cv2.contourArea)
        (x, y), radius = cv2.minEnclosingCircle(c)
        M = cv2.moments(c)
        boundaryCenter = int(M['m10'] / M['m00']), int(M['m01'] / M['m00'])
    if initBB is not None:
        success, box = tracker.update(frame)
        if success:
            x, y, w, h = [int(v) for v in box]
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
            fps.update()
            fps.stop()
            info = [('Tracker', args['tracker']), ('Success', 'Yes' if
                success else 'No'), ('FPS', '{:.2f}'.format(fps.fps()))]
            for i, (k, v) in enumerate(info):
                text = '{}: {}'.format(k, v)
                cv2.putText(frame, text, (10, H - (i * 20 + 20)), cv2.
                    FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
        else:
            initBB = None
    cv2.imshow('Frame', frame)
    key = cv2.waitKey(1) & 255
    if not initBB or not success:
        blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416), swapRB=
            True, crop=False)
        net.setInput(blob)
        start = time.time()
        layerOutputs = net.forward(ln)
        end = time.time()
        boxes = []
        confidences = []
        classIDs = []
        for output in layerOutputs:
            for detection in output:
                scores = detection[5:]
                classID = np.argmax(scores)
                confidence = scores[classID]
                if confidence > args['confidence'] and classID in {
                    BIRD_CLASS_ID, PERSON_CLASS_ID}:
                    box = detection[0:4] * np.array([W, H, W, H])
                    centerX, centerY, width, height = box.astype('int')
                    x = int(centerX - width / 2)
                    y = int(centerY - height / 2)
                    boxes.append([x, y, int(width), int(height)])
                    confidences.append(float(confidence))
                    classIDs.append(classID)
        idxs = cv2.dnn.NMSBoxes(boxes, confidences, args['confidence'],
            args['threshold'])
        if len(idxs) > 0:
            for i in idxs.flatten():
                x, y = boxes[i][0], boxes[i][1]
                w, h = boxes[i][2], boxes[i][3]
                color = [int(c) for c in COLORS[0 if classIDs[i] ==
                    PERSON_CLASS_ID else 1]]
                cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
                text = '{}: {:.4f}'.format(LABELS[classIDs[i]], confidences[i])
                cv2.putText(frame, text, (x, y - 5), cv2.
                    FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
                if classIDs[i] == BIRD_CLASS_ID:
                    initBB = tuple(boxes[i])
                    tracker = OPENCV_OBJECT_TRACKERS[args['tracker']]()
                    tracker.init(frame, initBB)
                    fps = FPS().start()
                else:
                    print('Human detected!\n')
    if key == ord('q'):
        break
if not args.get('video', False):
    vs.stop()
else:
    vs.release()
cv2.destroyAllWindows()

import os
import numpy as np
from imutils.video import VideoStream
from imutils.video import FPS
import argparse
import imutils
import time
import cv2
ap = argparse.ArgumentParser()
ap.add_argument('-v', '--video', type=str, help='path to input video file')
ap.add_argument('-t', '--tracker', type=str, default='kcf', help=
    'OpenCV object tracker type')
ap.add_argument('-y', '--yolo', required=True, help=
    'base path to YOLO directory')
ap.add_argument('-c', '--confidence', type=float, default=0.5, help=
    'minimum probability to filter weak detections')
ap.add_argument('--threshold', type=float, default=0.3, help=
    'threshold when applyong non-maxima suppression')
args = vars(ap.parse_args())
labelsPath = os.path.sep.join([args['yolo'], 'coco.names'])
LABELS = open(labelsPath).read().strip().split('\n')
np.random.seed(42)
COLORS = np.random.randint(0, 255, size=(2, 3), dtype='uint8')
weightsPath = os.path.sep.join([args['yolo'], 'yolov3.weights'])
configPath = os.path.sep.join([args['yolo'], 'yolov3.cfg'])
print('[INFO] loading YOLO from disk...')
net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)
ln = net.getLayerNames()
ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]
if not args.get('video', False):
    vs = VideoStream(src=0).start()
else:
    vs = cv2.VideoCapture(args['video'])
writer = None
W, H = None, None
redLower = 157, 33, 142
redUpper = 224, 255, 255
BIRD_CLASS_ID = 14
PERSON_CLASS_ID = 0
OPENCV_OBJECT_TRACKERS = {'csrt': cv2.TrackerCSRT_create, 'kcf': cv2.
    TrackerKCF_create, 'boosting': cv2.TrackerBoosting_create, 'mil': cv2.
    TrackerMIL_create, 'tld': cv2.TrackerTLD_create, 'medianflow': cv2.
    TrackerMedianFlow_create, 'mosse': cv2.TrackerMOSSE_create}
tracker = OPENCV_OBJECT_TRACKERS[args['tracker']]()
initBB = None
if not args.get('video', False):
    print('[INFO] starting video stream...')
    vs = VideoStream(src=0).start()
    time.sleep(1.0)
else:
    vs = cv2.VideoCapture(args['video'])
fps = None
while True:
    frame = vs.read()
    frame = frame[1] if args.get('video', False) else frame
    if frame is None:
        break
    frame = imutils.resize(frame, width=500)
    H, W = frame.shape[:2]
    blurred = cv2.GaussianBlur(frame, (11, 11), 0)
    hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, redLower, redUpper)
    mask = cv2.erode(mask, None, iterations=2)
    mask = cv2.dilate(mask, None, iterations=2)
    cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.
        CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    boundaryCenter = None
    if len(cnts) > 0:
        c = max(cnts, key=cv2.contourArea)
        (x, y), radius = cv2.minEnclosingCircle(c)
        M = cv2.moments(c)
        boundaryCenter = int(M['m10'] / M['m00']), int(M['m01'] / M['m00'])
    if initBB is not None:
        success, box = tracker.update(frame)
        if success:
            x, y, w, h = [int(v) for v in box]
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
            fps.update()
            fps.stop()
            info = [('Tracker', args['tracker']), ('Success', 'Yes' if
                success else 'No'), ('FPS', '{:.2f}'.format(fps.fps()))]
            for i, (k, v) in enumerate(info):
                text = '{}: {}'.format(k, v)
                cv2.putText(frame, text, (10, H - (i * 20 + 20)), cv2.
                    FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
        else:
            initBB = None
    cv2.imshow('Frame', frame)
    key = cv2.waitKey(1) & 255
    if not initBB or not success:
        blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416), swapRB=
            True, crop=False)
        net.setInput(blob)
        start = time.time()
        layerOutputs = net.forward(ln)
        end = time.time()
        boxes = []
        confidences = []
        classIDs = []
        for output in layerOutputs:
            for detection in output:
                scores = detection[5:]
                classID = np.argmax(scores)
                confidence = scores[classID]
                if confidence > args['confidence'] and classID in {
                    BIRD_CLASS_ID, PERSON_CLASS_ID}:
                    box = detection[0:4] * np.array([W, H, W, H])
                    centerX, centerY, width, height = box.astype('int')
                    x = int(centerX - width / 2)
                    y = int(centerY - height / 2)
                    boxes.append([x, y, int(width), int(height)])
                    confidences.append(float(confidence))
                    classIDs.append(classID)
        idxs = cv2.dnn.NMSBoxes(boxes, confidences, args['confidence'],
            args['threshold'])
        if len(idxs) > 0:
            for i in idxs.flatten():
                x, y = boxes[i][0], boxes[i][1]
                w, h = boxes[i][2], boxes[i][3]
                color = [int(c) for c in COLORS[0 if classIDs[i] ==
                    PERSON_CLASS_ID else 1]]
                cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
                text = '{}: {:.4f}'.format(LABELS[classIDs[i]], confidences[i])
                cv2.putText(frame, text, (x, y - 5), cv2.
                    FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
                if classIDs[i] == BIRD_CLASS_ID:
                    initBB = tuple(boxes[i])
                    tracker = OPENCV_OBJECT_TRACKERS[args['tracker']]()
                    tracker.init(frame, initBB)
                    fps = FPS().start()
                else:
                    print('Human detected!\n')
    if key == ord('q'):
        break
if not args.get('video', False):
    vs.stop()
else:
    vs.release()
cv2.destroyAllWindows()

# USAGE
# python opencv_yolo.py --yolo yolo-coco
# python opencv_yolo.py --video dashcam_boston.mp4 --tracker csrt --yolo yolo-coco

# import the necessary packages
import os
import numpy as np
from imutils.video import VideoStream
from imutils.video import FPS
import argparse
import imutils
import time
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video", type=str,
                help="path to input video file")
ap.add_argument("-t", "--tracker", type=str, default="kcf",
                help="OpenCV object tracker type")
ap.add_argument("-y", "--yolo", required=True,
                help="base path to YOLO directory")
ap.add_argument("-c", "--confidence", type=float, default=0.5,
                help="minimum probability to filter weak detections")
ap.add_argument("--threshold", type=float, default=0.3,
                help="threshold when applyong non-maxima suppression")
args = vars(ap.parse_args())

# load the COCO class labels our YOLO model was trained on
labelsPath = os.path.sep.join([args["yolo"], "coco.names"])
LABELS = open(labelsPath).read().strip().split("\n")

# initialize a list of colors to represent TWO possible class labels
np.random.seed(42)
COLORS = np.random.randint(0, 255, size=(2, 3),
                           dtype="uint8")

# derive the paths to the YOLO weights and model configuration
weightsPath = os.path.sep.join([args["yolo"], "yolov3.weights"])
configPath = os.path.sep.join([args["yolo"], "yolov3.cfg"])

# load our YOLO object detector trained on COCO dataset (80 classes)
# and determine only the *output* layer names that we need from YOLO
print("[INFO] loading YOLO from disk...")
net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)
ln = net.getLayerNames()
ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]

# initialize the video stream and frame dimensions
if not args.get("video", False):
    # if a video path was not supplied, grab the reference
    # to the webcam
    vs = VideoStream(src=0).start()
else:
    # otherwise, grab a reference to the video file
    vs = cv2.VideoCapture(args["video"])
writer = None
(W, H) = (None, None)

# define the lower and upper boundaries of the "red"
# boundaries in the HSV color space
redLower = (157, 33, 142)
redUpper = (224, 255, 255)

# initialize the two classes we care about
BIRD_CLASS_ID = 14
PERSON_CLASS_ID = 0

# initialize a dictionary that maps strings to their corresponding
# OpenCV object tracker implementations
OPENCV_OBJECT_TRACKERS = {
    "csrt": cv2.TrackerCSRT_create,
    "kcf": cv2.TrackerKCF_create,
    "boosting": cv2.TrackerBoosting_create,
    "mil": cv2.TrackerMIL_create,
    "tld": cv2.TrackerTLD_create,
    "medianflow": cv2.TrackerMedianFlow_create,
    "mosse": cv2.TrackerMOSSE_create
}
tracker = OPENCV_OBJECT_TRACKERS[args["tracker"]]()

# initialize the bounding box coordinates of the object we are going
# to track
initBB = None

# if a video path was not supplied, grab the reference to the web cam
if not args.get("video", False):
    print("[INFO] starting video stream...")
    vs = VideoStream(src=0).start()
    time.sleep(1.0)

# otherwise, grab a reference to the video file
else:
    vs = cv2.VideoCapture(args["video"])

# initialize the FPS throughput estimator
fps = None

# loop over frames from the video stream
while True:
    # grab the current frame, then handle if we are using a
    # VideoStream or VideoCapture object
    frame = vs.read()
    frame = frame[1] if args.get("video", False) else frame

    # check to see if we have reached the end of the stream
    if frame is None:
        break

    # resize the frame (so we can process it faster) and grab the
    # frame dimensions
    frame = imutils.resize(frame, width=500)
    (H, W) = frame.shape[:2]

    # blur the frame and convert it to the HSV color space
    blurred = cv2.GaussianBlur(frame, (11, 11), 0)
    hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)

    # construct a mask for the color "red", then perform
    # a series of dilations and erosions to remove any small
    # blobs left in the mask
    mask = cv2.inRange(hsv, redLower, redUpper)
    mask = cv2.erode(mask, None, iterations=2)
    mask = cv2.dilate(mask, None, iterations=2)

    # find contours in the mask and initialize the current
    # (x, y) center of the red boundary
    cnts = cv2.findContours(
        mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    boundaryCenter = None

    # only proceed if at least one contour was found
    if len(cnts) > 0:
        # find the largest contour in the mask, then use
        # it to compute the minimum enclosing circle and
        # centroid
        c = max(cnts, key=cv2.contourArea)
        ((x, y), radius) = cv2.minEnclosingCircle(c)
        M = cv2.moments(c)
        boundaryCenter = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
        # print(f"DANGER: RED BOUNDARY DETECTED AT {boundaryCenter}")

    # check to see if we are currently tracking an object
    if initBB is not None:
        # grab the new bounding box coordinates of the object
        (success, box) = tracker.update(frame)

        # check to see if the tracking was a success
        if success:
            (x, y, w, h) = [int(v) for v in box]
            cv2.rectangle(frame, (x, y), (x + w, y + h),
                          (0, 255, 0), 2)

            # update the FPS counter
            fps.update()
            fps.stop()

            # initialize the set of information we'll be displaying on
            # the frame
            info = [
                ("Tracker", args["tracker"]),
                ("Success", "Yes" if success else "No"),
                ("FPS", "{:.2f}".format(fps.fps())),
            ]

            # loop over the info tuples and draw them on our frame
            for (i, (k, v)) in enumerate(info):
                text = "{}: {}".format(k, v)
                cv2.putText(frame, text, (10, H - ((i * 20) + 20)),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)

        else:
            initBB = None

    # show the output frame
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF

    if not initBB or not success:
        # construct a blob from the input frame and then perform a forward
        # pass of the YOLO object detector, giving us our bounding boxes
        # and associated probabilities
        blob = cv2.dnn.blobFromImage(
            frame, 1 / 255.0, (416, 416), swapRB=True, crop=False)
        net.setInput(blob)
        start = time.time()
        layerOutputs = net.forward(ln)
        end = time.time()

        # initialize our lists of detected bounding boxes, confidences,
        # and class IDs, respectively
        boxes = []
        confidences = []
        classIDs = []

        # loop over each of the layer outputs
        for output in layerOutputs:
            # loop over each of the detections
            for detection in output:
                # extract the class ID and confidence (i.e., probability)
                # of the current object detection
                scores = detection[5:]
                classID = np.argmax(scores)
                confidence = scores[classID]

                # filter out weak predictions by ensuring the detected
                # probability is greater than the minimum probability
                if confidence > args["confidence"] and classID in {BIRD_CLASS_ID, PERSON_CLASS_ID}:
                    # scale the bounding box coordinates back relative to
                    # the size of the image, keeping in mind that YOLO
                    # actually returns the center (x, y)-coordinates of
                    # the bounding box followed by the boxes' width and
                    # height
                    box = detection[0:4] * np.array([W, H, W, H])
                    (centerX, centerY, width, height) = box.astype("int")

                    # use the center (x, y)-coordinates to derive the top
                    # and and left corner of the bounding box
                    x = int(centerX - (width / 2))
                    y = int(centerY - (height / 2))

                    # update our list of bounding box coordinates,
                    # confidences, and class IDs
                    boxes.append([x, y, int(width), int(height)])
                    confidences.append(float(confidence))
                    classIDs.append(classID)

        # apply non-maxima suppression to suppress weak, overlapping
        # bounding boxes
        idxs = cv2.dnn.NMSBoxes(
            boxes, confidences, args["confidence"], args["threshold"])

        # ensure at least one detection exists
        if len(idxs) > 0:
            # loop over the indexes we are keeping
            for i in idxs.flatten():
                # extract the bounding box coordinates
                (x, y) = (boxes[i][0], boxes[i][1])
                (w, h) = (boxes[i][2], boxes[i][3])

                # draw a bounding box rectangle and label on the frame
                color = [int(c) for c in COLORS[0 if classIDs[i]
                                                == PERSON_CLASS_ID else 1]]
                cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
                text = "{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i])
                cv2.putText(frame, text, (x, y - 5),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)

                if (classIDs[i] == BIRD_CLASS_ID):
                    initBB = tuple(boxes[i])

                    # start OpenCV object tracker using the supplied bounding box
                    # coordinates, then start the FPS throughput estimator as well
                    tracker = OPENCV_OBJECT_TRACKERS[args["tracker"]]()
                    tracker.init(frame, initBB)
                    fps = FPS().start()
                else:
                    print("Human detected!\n")

        # if the `q` key was pressed, break from the loop
    if key == ord("q"):
        break

# if we are using a webcam, release the pointer
if not args.get("video", False):
    vs.stop()

# otherwise, release the file pointer
else:
    vs.release()

# close all windows
cv2.destroyAllWindows()
