# USAGE
# python webstreaming.py --ip 0.0.0.0 --port 8000

# import the necessary packages
import numpy as np
from imutils.video import VideoStream
from flask import Response
from flask import Flask
from flask import render_template
from time import sleep 
import imutils

import threading
import argparse
import datetime
import time
import cv2

import serial
import random 

 


ser = serial.Serial("/dev/ttyUSB0",9600) 

# initialize the output frame and a lock used to ensure thread-safe
# exchanges of the output frames (useful for multiple browsers/tabs
# are viewing tthe stream)
outputFrame = None
lock = threading.Lock()

# initialize a flask object
app = Flask(__name__)

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--prototxt", type=str, default='MobileNetSSD_deploy.prototxt',
	help="path to Caffe 'deploy' prototxt file")
ap.add_argument("-m", "--model", type=str, default='MobileNetSSD_deploy.caffemodel',
	help="path to Caffe pre-trained model")
ap.add_argument("-c", "--confidence", type=float, default=0.2,
	help="minimum probability to filter weak detections")
ap.add_argument("-u", "--movidius", type=bool, default=0,
	help="boolean indicating if the Movidius should be used")
args = vars(ap.parse_args())

# initialize the list of class labels MobileNet SSD was trained to
# detect, then generate a set of bounding box colors for each class
CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat",
	"bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
	"dog", "horse", "motorbike", "person", "pottedplant", "sheep",
	"sofa", "train", "tvmonitor"]
COLORS = np.random.uniform(0, 255, size=(len(CLASSES), 3))

# load our serialized model from disk
print("[INFO] loading model...")
net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"])


vs = VideoStream(src=0).start()
time.sleep(2.0)

@app.route("/")
def index():
	# return the rendered template
	return render_template("index.html")

def detect_motion(frameCount):
    # grab global references to the video stream, output frame, and
    # lock variables
    global vs, outputFrame, lock



    while True:
		# grab the frame from the threaded video stream and resize it
	# to have a maximum width of 400 pixels
        frame = vs.read()
        frame = imutils.resize(frame, width=400)

        # grab the frame dimensions and convert it to a blob
        (h, w) = frame.shape[:2]
        blob = cv2.dnn.blobFromImage(frame, 0.007843, (300, 300), 127.5)

        # pass the blob through the network and obtain the detections and
        # predictions
        net.setInput(blob)
        detections = net.forward()

        # loop over the detections
        for i in np.arange(0, detections.shape[2]):
			# extract the confidence (i.e., probability) associated with
			# the prediction
            confidence = detections[0, 0, i, 2]

            # filter out weak detections by ensuring the `confidence` is
            # greater than the minimum confidence
            if confidence > 0.2:
				# extract the index of the class label from the
				# `detections`, then compute the (x, y)-coordinates of
				# the bounding box for the 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")

                if (CLASSES[idx] == "person" or CLASSES[idx] == "motorbike" or CLASSES[idx] == "car" or CLASSES[idx] == "cat" or CLASSES[idx] == "dog") : 

                    print("################-->",CLASSES[idx]) 
                    
                    ser.write('STOP_'.encode())
                    ser.write('STOP_'.encode())
                    print("STOP")

                    sleep(1)

                    ser.write('DOWN_'.encode()) 
                    print("DOWN")
                    sleep(2)

                    if random.randint(1,3) == 1 : ### 랜덤 함수 1,3중에 하나일 경우.  
                        ser.write('LEFT'.encode()) 
                        print("LEFT")
                    else  : 
                        ser.write('RIGHT'.encode()) 
                        print("RIGHT")
                    sleep(1) 
                    
					
                else : 
                    ser.write('UP_'.encode())
                    print("UP")
                    sleep(1)  

                # draw the prediction on the frame
                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)
                    
              
        with lock:
            outputFrame = frame.copy()

def generate():
	# grab global references to the output frame and lock variables
	global outputFrame, lock

	# loop over frames from the output stream
	while True:
		# wait until the lock is acquired
		with lock:
			# check if the output frame is available, otherwise skip
			# the iteration of the loop
			if outputFrame is None:
				continue

			# encode the frame in JPEG format
			(flag, encodedImage) = cv2.imencode(".jpg", outputFrame)

			# ensure the frame was successfully encoded
			if not flag:
				continue

		# yield the output frame in the byte format
		yield(b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + 
			bytearray(encodedImage) + b'\r\n')

@app.route("/video_feed")
def video_feed():
	# return the response generated along with the specific media
	# type (mime type)
	return Response(generate(),
		mimetype = "multipart/x-mixed-replace; boundary=frame")

# check to see if this is the main thread of execution
if __name__ == '__main__':
	# construct the argument parser and parse command line arguments
	ap = argparse.ArgumentParser()
	ap.add_argument("-i", "--ip", type=str, default="0.0.0.0",
		help="ip address of the device")
	ap.add_argument("-o", "--port", type=int, default=5001,
		help="ephemeral port number of the server (1024 to 65535)")
	ap.add_argument("-f", "--frame-count", type=int, default=32,
		help="# of frames used to construct the background model")
	args = vars(ap.parse_args())

	# start a thread that will perform motion detection
	t = threading.Thread(target=detect_motion, args=(
		args["frame_count"],))
	t.daemon = True
	t.start()

	# start the flask app
	app.run(host=args["ip"], port=args["port"], debug=True,
		threaded=True, use_reloader=False)

# release the video stream pointer
vs.stop()

# USAGE
# python webstreaming.py --ip 0.0.0.0 --port 8000

# import the necessary packages
import numpy as np
from imutils.video import VideoStream
from flask import Response
from flask import Flask
from flask import render_template
from time import sleep 
import imutils

import threading
import argparse
import datetime
import time
import cv2

import serial
import random 

 


ser = serial.Serial("/dev/ttyUSB0",9600) 

# initialize the output frame and a lock used to ensure thread-safe
# exchanges of the output frames (useful for multiple browsers/tabs
# are viewing tthe stream)
outputFrame = None
lock = threading.Lock()

# initialize a flask object
app = Flask(__name__)

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--prototxt", type=str, default='MobileNetSSD_deploy.prototxt',
	help="path to Caffe 'deploy' prototxt file")
ap.add_argument("-m", "--model", type=str, default='MobileNetSSD_deploy.caffemodel',
	help="path to Caffe pre-trained model")
ap.add_argument("-c", "--confidence", type=float, default=0.2,
	help="minimum probability to filter weak detections")
ap.add_argument("-u", "--movidius", type=bool, default=0,
	help="boolean indicating if the Movidius should be used")
args = vars(ap.parse_args())

# initialize the list of class labels MobileNet SSD was trained to
# detect, then generate a set of bounding box colors for each class
CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat",
	"bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
	"dog", "horse", "motorbike", "person", "pottedplant", "sheep",
	"sofa", "train", "tvmonitor"]
COLORS = np.random.uniform(0, 255, size=(len(CLASSES), 3))

# load our serialized model from disk
print("[INFO] loading model...")
net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"])


vs = VideoStream(src=0).start()
time.sleep(2.0)

@app.route("/")
def index():
	# return the rendered template
	return render_template("index.html")

def detect_motion(frameCount):
    # grab global references to the video stream, output frame, and
    # lock variables
    global vs, outputFrame, lock



    while True:
		# grab the frame from the threaded video stream and resize it
	# to have a maximum width of 400 pixels
        frame = vs.read()
        frame = imutils.resize(frame, width=400)

        # grab the frame dimensions and convert it to a blob
        (h, w) = frame.shape[:2]
        blob = cv2.dnn.blobFromImage(frame, 0.007843, (300, 300), 127.5)

        # pass the blob through the network and obtain the detections and
        # predictions
        net.setInput(blob)
        detections = net.forward()

        # loop over the detections
        for i in np.arange(0, detections.shape[2]):
			# extract the confidence (i.e., probability) associated with
			# the prediction
            confidence = detections[0, 0, i, 2]

            # filter out weak detections by ensuring the `confidence` is
            # greater than the minimum confidence
            if confidence > 0.2:
				# extract the index of the class label from the
				# `detections`, then compute the (x, y)-coordinates of
				# the bounding box for the 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")

                if (CLASSES[idx] == "person" or CLASSES[idx] == "motorbike" or CLASSES[idx] == "car" or CLASSES[idx] == "cat" or CLASSES[idx] == "dog") : 

                    print("################-->",CLASSES[idx]) 
                    
                    ser.write('STOP_'.encode())
                    ser.write('STOP_'.encode())
                    print("STOP")

                    sleep(1)

                    ser.write('DOWN_'.encode()) 
                    print("DOWN")
                    sleep(2)

                    if random.randint(1,3) == 1 : ### 랜덤 함수 1,3중에 하나일 경우.  
                        ser.write('LEFT'.encode()) 
                        print("LEFT")
                    else  : 
                        ser.write('RIGHT'.encode()) 
                        print("RIGHT")
                    sleep(1) 
                    
					
                else : 
                    ser.write('UP_'.encode())
                    print("UP")
                    sleep(1)  

                # draw the prediction on the frame
                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)
                    
              
        with lock:
            outputFrame = frame.copy()

def generate():
	# grab global references to the output frame and lock variables
	global outputFrame, lock

	# loop over frames from the output stream
	while True:
		# wait until the lock is acquired
		with lock:
			# check if the output frame is available, otherwise skip
			# the iteration of the loop
			if outputFrame is None:
				continue

			# encode the frame in JPEG format
			(flag, encodedImage) = cv2.imencode(".jpg", outputFrame)

			# ensure the frame was successfully encoded
			if not flag:
				continue

		# yield the output frame in the byte format
		yield(b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + 
			bytearray(encodedImage) + b'\r\n')

@app.route("/video_feed")
def video_feed():
	# return the response generated along with the specific media
	# type (mime type)
	return Response(generate(),
		mimetype = "multipart/x-mixed-replace; boundary=frame")

# check to see if this is the main thread of execution
if __name__ == '__main__':
	# construct the argument parser and parse command line arguments
	ap = argparse.ArgumentParser()
	ap.add_argument("-i", "--ip", type=str, default="0.0.0.0",
		help="ip address of the device")
	ap.add_argument("-o", "--port", type=int, default=5001,
		help="ephemeral port number of the server (1024 to 65535)")
	ap.add_argument("-f", "--frame-count", type=int, default=32,
		help="# of frames used to construct the background model")
	args = vars(ap.parse_args())

	# start a thread that will perform motion detection
	t = threading.Thread(target=detect_motion, args=(
		args["frame_count"],))
	t.daemon = True
	t.start()

	# start the flask app
	app.run(host=args["ip"], port=args["port"], debug=True,
		threaded=True, use_reloader=False)

# release the video stream pointer
vs.stop()

# USAGE # python webstreaming.py --ip 0.0.0.0 --port 8000 # import the necessary packages # initialize the output frame and a lock used to ensure thread-safe # exchanges of the output frames (useful for multiple browsers/tabs # are viewing tthe stream) # initialize a flask object # construct the argument parse and parse the arguments # initialize the list of class labels MobileNet SSD was trained to # detect, then generate a set of bounding box colors for each class # load our serialized model from disk # return the rendered template # grab global references to the video stream, output frame, and # lock variables # grab the frame from the threaded video stream and resize it # to have a maximum width of 400 pixels # grab the frame dimensions and convert it to a blob # pass the blob through the network and obtain the detections and # predictions # loop over the detections # extract the confidence (i.e., probability) associated with # the prediction # filter out weak detections by ensuring the `confidence` is # greater than the minimum confidence # extract the index of the class label from the # `detections`, then compute the (x, y)-coordinates of # the bounding box for the object ###############-->",CLASSES[idx]) ### 랜덤 함수 1,3중에 하나일 경우. # draw the prediction on the frame # grab global references to the output frame and lock variables # loop over frames from the output stream # wait until the lock is acquired # check if the output frame is available, otherwise skip # the iteration of the loop # encode the frame in JPEG format # ensure the frame was successfully encoded # yield the output frame in the byte format # return the response generated along with the specific media # type (mime type) # check to see if this is the main thread of execution # construct the argument parser and parse command line arguments # start a thread that will perform motion detection # start the flask app # release the video stream pointer