# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# + [markdown] colab_type="text" id="cM9RkMXxmg6X"
# ## Mask Adaptivity Detection Using YOLO
#
# Mask became an essential accessory post COVID-19. Most of the countries are making face masks mandatory to avail services like transport, fuel and any sort of outside activity. It is become utmost necessary to keep track of the adaptivity of the crowd. This notebook from DeepHiveMind contains implementation of a face mask adaptivity tracker using YOLO.
#
# ![cover](https://i.ibb.co/RBG6m20/cover.png)

# + colab_type="code" id="ero65aTmh5qu" colab={}
import warnings
import numpy as np
import argparse
import time
import cv2
import os
warnings.filterwarnings("ignore")


# + [markdown] colab_type="text" id="YMRWP7xZlxB8"
# ### Prepare DarkNet Environment

# + colab_type="code" id="0XQThXbm5L6T" outputId="292b0e16-e31f-47b8-df22-1a019cd77b1b" colab={"base_uri": "https://localhost:8080/", "height": 1000}
# Create DarkNet Environment
def prepare_environment():
    os.environ['PATH'] += ':/usr/local/cuda/bin'
    # !rm -fr darknet
    # !git clone https://github.com/AlexeyAB/darknet/
    # !apt install gcc-5 g++-5 -y
    # !ln -s /usr/bin/gcc-5 /usr/local/cuda/bin/gcc 
    # !ln -s /usr/bin/g++-5 /usr/local/cuda/bin/g++
    # %cd darknet
    # !sed -i 's/GPU=0/GPU=1/g' Makefile
    # !sed -i 's/OPENCV=0/OPENCV=1/g' Makefile
    # !make
    # get yolov3 weights
    # #!wget https://pjreddie.com/media/files/darknet53.conv.74.weights
    # !chmod a+x ./darknet
    # !apt install ffmpeg libopencv-dev libgtk-3-dev python-numpy python3-numpy libdc1394-22 libdc1394-22-dev libjpeg-dev libtiff5-dev libavcodec-dev libavformat-dev libswscale-dev libxine2-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libv4l-dev libtbb-dev qtbase5-dev libfaac-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev x264 v4l-utils unzip
    status='Completed'
    return status
prepare_environment()    

# + colab_type="code" id="zCYwTSgQzpwN" outputId="0fe4f8e0-1b70-4249-9b19-849e1e32bac6" colab={"base_uri": "https://localhost:8080/", "height": 121}
from google.colab import drive
drive.mount('/content/drive')

# + colab_type="code" id="ImCWrY-e0ZpQ" outputId="67fa87f4-5c73-40f7-ef91-a2f47ae0ae03" colab={"base_uri": "https://localhost:8080/", "height": 185}
os.listdir('/content/drive/My Drive/darknet/YOLO_Custom')

# + [markdown] colab_type="text" id="8GjNCDE4ZSqK"
# ### Get Tiny YOLO Weight (Skip if Resuming Training)

# + colab_type="code" id="xDOXcABQVpRn" outputId="4e370ab0-f1c7-4868-b981-2e0cdefa45b6" colab={"base_uri": "https://localhost:8080/", "height": 0}
# !wget --header="Host: pjreddie.com" --header="User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36" --header="Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" --header="Accept-Language: en-US,en;q=0.9" --header="Referer: https://github.com/AlexeyAB/darknet" --header="Cookie: __utma=134107727.1364647705.1589636782.1589689587.1589901067.3; __utmz=134107727.1589901067.3.3.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)" --header="Connection: keep-alive" "https://pjreddie.com/media/files/yolov3-tiny.weights" -c -O 'yolov3-tiny.weights'

# + colab_type="code" id="Ryv56nNnW-V9" outputId="3be424c8-3cae-4de9-eed7-150fea6e1adb" colab={"base_uri": "https://localhost:8080/", "height": 0}
# !./darknet partial cfg/yolov3-tiny.cfg yolov3-tiny.weights yolov3-tiny.conv.15 15

# + [markdown] colab_type="text" id="f8dP_2ym7kZB"
#

# + [markdown] colab_type="text" id="eBrnmAohZzPX"
# ### Copy Required Files from Drive

# + colab_type="code" id="28bjxQKML3Nr" colab={}
# Copy fils from Google Drive to the VM local filesystem
# !cp -r "/content/drive/My Drive/darknet/YOLO_Custom" /content/darknet/YOLO_Custom


# + [markdown] colab_type="text" id="UvPkfqEUaAiH"
# ### Train

# + [markdown] colab_type="text" id="DA9t5O5XaGJ6"
# Use the below command to train yolo:  
#                
# # # !./darknet detector train data_file_path config_file_path training_weights_path log_path

# + [markdown] colab_type="text" id="f7GmL-ttsvQN"
# To train yolov3 instead of tiny yolo, replace the following files:
#
# use ***yolov3_train_cfg*** instead of ***yolov3-tiny_obj_train.cfg***
# use ***yolov3_test_cfg*** instead of ***yolov3-tiny_obj_test.cfg*** for testing purpose.
# Replace the yolov3 weight link with the tiny yolo weight link

# + colab_type="code" id="Q5JJidTpPoJs" outputId="510cdf8b-2fe2-4390-e315-1c2aae241c3a" colab={"base_uri": "https://localhost:8080/", "height": 1000}
# !./darknet detector train "/content/darknet/YOLO_Custom/obj.data" "/content/darknet/YOLO_Custom/yolov3-tiny_obj_train.cfg" "/content/darknet/yolov3-tiny.conv.15" "train.log" -dont_show 

# + [markdown] colab_type="text" id="y7e5GdAPimAJ"
# ### Utility Functions

# + colab_type="code" id="sbBdherw_PTU" colab={}
# Define threshold for confidence score and Non max supression here
confthres=0.2
nmsthres=0.1
path="./"
def get_labels(label_dir):
    return open(label_dir).read().split('\n')
      
def get_colors(LABELS):
    # initialize a list of colors to represent each possible class label
    np.random.seed(42)
    COLORS = np.random.randint(0, 255, size=(len(LABELS), 3),dtype="uint8")
    return COLORS

def get_weights(weights_path):
    # derive the paths to the YOLO weights and model configuration
    weightsPath = os.path.sep.join([yolo_path, weights_path])
    return weightsPath

def get_config(config_path):
    configPath = os.path.sep.join([yolo_path, config_path])
    return configPath

def load_model(configpath,weightspath):
    # load our YOLO object detector trained on COCO dataset (80 classes)
    print("[INFO] loading YOLO from disk...")
    net = cv2.dnn.readNetFromDarknet(configpath, weightspath)
    return net


# + colab_type="code" id="gmvObbr3_Ubz" colab={}
#https://medium.com/analytics-vidhya/object-detection-using-yolo-v3-and-deploying-it-on-docker-and-minikube-c1192e81ae7a
def get_predection(image,net,LABELS,COLORS):
    (H, W) = image.shape[:2]

    # determine only the *output* layer names that we need from YOLO
    ln = net.getLayerNames()
    ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]

    # construct a blob from the input image and then perform a forward
    # pass of the YOLO object detector, giving us our bounding boxes and
    # associated probabilities
    blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416),
                                 swapRB=True, crop=False)
    net.setInput(blob)
    start = time.time()
    layerOutputs = net.forward(ln)
    #print(layerOutputs[0])
    end = time.time()

    # show timing information on YOLO
    #print("[INFO] YOLO took {:.6f} seconds".format(end - start))

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

    # 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:]
            #print(detection)
            classID = np.argmax(scores)
            # print(classID)
            confidence = scores[classID]

            # filter out weak predictions by ensuring the detected
            # probability is greater than the minimum probability
            if confidence > confthres:
                # 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)
                if(classID==0):
                  num_class_0 +=1
                elif(classID==1):
                  num_class_1 +=1  

    # apply non-maxima suppression to suppress weak, overlapping bounding
    # boxes
    idxs = cv2.dnn.NMSBoxes(boxes, confidences, confthres,
                            nmsthres)
    if(num_class_0>0 or num_class_1>0):
        index= num_class_0/(num_class_0+num_class_1)
    else:
      index=-1  
    #print(index,)    
    # 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 image
            color = [int(c) for c in COLORS[classIDs[i]]]
            cv2.rectangle(image, (x, y), (x + w, y + h), color, 2)
            text = "{}".format(LABELS[classIDs[i]])
            #print(boxes)
            #print(classIDs)      
            #cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX,0.5, color=(69, 60, 90), thickness=2)
            cv2.rectangle(image, (x, y-5), (x+62, y-15), color, cv2.FILLED)
            cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX,0.5, (0,0,0), 1)
            if(index!=-1 and index<.50):
                cv2.rectangle(image, (40, 46), (220, 16), (0,0,255), cv2.FILLED)
                cv2.putText(image,'Mask Adaptivity: POOR',(40,40),cv2.FONT_HERSHEY_SIMPLEX,0.5, (0,255,255), 1)
            elif(index>=.50 and index<.70):
                cv2.rectangle(image, (40, 46), (255, 16), (0, 165, 255), cv2.FILLED)
                cv2.putText(image,'Mask Adaptivity: MODERATE',(40,40),cv2.FONT_HERSHEY_SIMPLEX,0.5, (0,0,0), 1)  
            elif(index>=0.70):
                cv2.rectangle(image, (40, 46), (220, 16), (42,236,42), cv2.FILLED)
                cv2.putText(image,'Mask Adaptivity: HIGH',(40,40),cv2.FONT_HERSHEY_SIMPLEX,0.5, (0,0,0), 1)      
    return image


# + colab_type="code" id="UapmhRcxfr_J" colab={}
# Method to predict  Image
def predict_image(img_path):
    image = cv2.imread(img_path)
    nets=load_model(CFG,Weights)
    #Colors=get_colors(Lables)
    Colors=[(42,236,42),(0,0,255)]
    res=get_predection(image,nets,Lables,Colors)
    # image=cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
    # show the output image
    cv2_imshow(res)
    cv2.waitKey()


# + colab_type="code" id="uDlmOMWChG23" colab={}
# Method to predict Video
def predict_video(input_path,output_path):
    vid = cv2.VideoCapture(input_path)
    op=output_path
    height, width = None, None
    writer = None
    print('[Info] processing Video (It may take several minutes to Run)..')
    while True:
        grabbed, frame = vid.read()
		    # Checking if the complete video is read
        if not grabbed:
		        break
        if width is None or height is None:
		        height, width = frame.shape[:2]
        frame=get_predection(frame,nets,Lables,Colors)
        if writer is None:
          fourcc = cv2.VideoWriter_fourcc(*"mp4v")
          writer = cv2.VideoWriter(op, fourcc, 27,(frame.shape[1], frame.shape[0]), True)
        writer.write(frame)
    print ("[INFO] Cleaning up...")
    writer.release()
    vid.release()
    print ("[INFO] Prediction Completed.")


# + colab_type="code" id="VeDnJ1Frohs6" colab={}
# This will not work  in colab, as colab can't access local hardware
import time
def predict_web_cam():
    #stream = cv2.VideoCapture(0)
    sess = K.get_session()
    while True:
        # Capture frame-by-frame
        grabbed, frame = stream.read()
        if not grabbed:
            break
        # Run detection
        start = time.time()
        image = Image.fromarray(frame)
        output_image =  get_predection(image,nets,Lables,Colors)
        end = time.time()
        print("Inference time: {:.2f}s".format(end - start))
        # Display the resulting frame
        cv2.imshow('Web Cam',np.asarray(output_image))
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    stream.release()    
    cv2.destroyAllWindows() 


# + [markdown] colab_type="text" id="RVTB5zwwg5HQ"
# ### Set the Variables (Must before Prediction)

# + colab_type="code" id="JGotYYL5goIP" colab={}
# Set the pah for test config file, label directory and weights
CFG='/content/darknet/YOLO_Custom/yolov3-tiny_obj_test.cfg'   
label_dir='/content/darknet/YOLO_Custom/obj.names'
#cfgpath=test_config_path
Weights='/content/darknet/YOLO_Custom/yolov3-tiny_obj_train_tiny8.weights'
Lables=get_labels(label_dir)


# + [markdown] colab_type="text" id="mNjBMQk1ggXn"
# ### Predict Image

# + colab_type="code" id="1Nd17EMo_X2n" outputId="f3117978-4f58-46a5-dddc-9f5b0af46124" colab={"base_uri": "https://localhost:8080/", "height": 512}
    from google.colab.patches import cv2_imshow
    img_path='/content/buckey.jpg' 
    predict_image(img_path) 

# + [markdown] colab_type="text" id="q2DUMTvFiLxb"
# ### Predict Video

# + colab_type="code" id="_mDqXjOumaNs" outputId="f9ae3f64-3f01-4556-b26e-788df8c75df6" colab={"base_uri": "https://localhost:8080/", "height": 50}
input_path='/content/in.mp4'
output_path='/content/out.mp4'
predict_video(input_path,output_path)

StarcoderdataJupyterScriptsDedupFiltered