import numpy as np
import time
import cv2
from flask import Flask, render_template, Response

# Arguments construction
args={
"prototxt":"MobileNetSSD_deploy.prototxt.txt",
"model":"MobileNetSSD_deploy.caffemodel",
"confidence":0.2,
}

# ModelNet SSD Object list init
CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat", "bottle",
           "bus", "car", "cat", "chair", "cow", "diningtable" , " dog",
           "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", 
           "train", "monitor"]

COLORS = np.random.uniform(0, 255, size=(len(CLASSES), 3))

# Load model file
print("Load Neural Network...")
net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"])

print("Start Camera...")
camera = cv2.VideoCapture(0)
time.sleep(2.0)

app = Flask(__name__)

def generate_frames():
    prev_time = time.time()
    fps = 0

    while True:
        # Get video sttream. max width 800 pixels 
        success, frame = camera.read()
        if not success:
            break
        else:
            ret, frame=camera.read() #from video or ip cam
            # frame = imutils.resize(frame, width=800)
            
            # Create blob from image
            (h, w) = frame.shape[:2]
            blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 0.007843, (300, 300), 127.5)

            # Feed input to neural network 
            net.setInput(blob)
            detections = net.forward()

            # Detection loop
            for i in np.arange(0, detections.shape[2]):
                # Compute Object detection probability
                confidence = detections[0, 0, i, 2]
                
                # Suppress low probability
                if confidence > args["confidence"]:
                    # Get index and position of detected object
                    idx = int(detections[0, 0, i, 1])
                    box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
                    (startX, startY, endX, endY) = box.astype("int")

                    # Create box and label
                    label = "{}: {:.2f}%".format(CLASSES[idx], confidence * 100)
                    cv2.rectangle(frame, (startX, startY), (endX, endY), COLORS[idx], 2)
                    
                    y = startY - 15 if startY - 15 > 15 else startY + 15
                    cv2.putText(frame, label, (startX, y),cv2.FONT_HERSHEY_SIMPLEX, 0.5, COLORS[idx], 2)
            
             # Calculate FPS
            curr_time = time.time()
            fps = 1 / (curr_time - prev_time)
            prev_time = curr_time
            # Draw a white background rectangle for the FPS text
            cv2.rectangle(frame, (frame.shape[1] - 150, 5), (frame.shape[1], 35), (255, 255, 255), -1)
            # Display FPS on the frame in the top-right corner
            cv2.putText(frame, f"FPS: {int(fps)}", (frame.shape[1] - 150, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)

            # Buffering
            ret, buffer = cv2.imencode('.jpg', frame)
            frame = buffer.tobytes()
            yield (b'--frame\r\n'
                    b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/video_feed')
def video_feed():
    return Response(generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == "__main__":
    # app.run(debug=False)
    app.run(host='0.0.0.0', debug=False)

camera.release()
