# Subscribe to PyShine Youtube channel for the upcoming educational videos
# PyShine presents Matplotlib integration with Open CV to output the frame rate
# Lets write the face detection code
# This code has two parts: 1) Face.py 2) Plot.py
# Face.py will open Webcam and detect face in video stream
# Also it will generate a csv file which will have the current frame rate
# Plot.py will read the csv file and update the plot of frame rate
# The Face.py will run the Plot.py in a thread
# So lets start the code, by importing the required libraries
#################################### Face.py  Starts ################################################


import cv2
import time
import imutils
import _thread
import numpy as np
import os
# Put the .xml file in the current folder together with Face.py and Plot.py
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# Initiate the Webcam device with default id of 0
video_capture = cv2.VideoCapture(0)
# Generate the 'file.csv' with labels time, FPS: Frame Per Second
print('time,FPS',  file=open('file.csv', 'w'))
# This function will run camera 
def camRun():
	# A counter to count the frames
	cnt=0
	# Number of frames to count after which the frame rate is obtained
	frames_to_count = 20
	# So we will count 20 frames and also note the time duration for these 20 frames 
	# And then simply divide frames by the duration in seconds to get frame rate
	st=0 # Start time st  = 0 seconds
	i=0 # This is a counter for the time samples for each FPS value
	while True:
		ret, frame = video_capture.read() # Get the frame 
		frame = imutils.resize(frame, width=320) # Resize it to 320 width , its optional 
		gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # RGB to Gray Matrix 
		faces = faceCascade.detectMultiScale(
			gray,
			scaleFactor=1.15,  
			minNeighbors=7, 
			minSize=(80, 80), 
			flags=cv2.CASCADE_SCALE_IMAGE
		)
		for (x, y, w, h) in faces:
			cv2.rectangle(frame, (x, y), (x + w, y + h), (214, 169, 33), 4) # Here we put rectangle on a frame
		cv2.imshow('FaceDetection', frame) # Display the frame in a window named FaceDetection
		k = cv2.waitKey(1) 
		if k == 27: # If click on video frame and press Esc, it will quit
			break
		# Frame rate calculation
		if cnt == frames_to_count:
			try: # To avoid divide by 0 we put it in try except
				print(frames_to_count/(time.time()-st),'FPS') 
				fps = frames_to_count/(time.time()-st) 
				print(str(i)+',' +str(fps),  file=open('file.csv','a')) 
				st = time.time()
				cnt=0
			except:
				pass
		# Counters are incremented here
		cnt+=1
		i+=1
# Lets call the Plot.py in a function plot
def plot():
	os.system('python Plot.py')
# Start the thread for the plot function
_thread.start_new_thread(plot,())
# Now run the camRun() function to generate the file.csv 
camRun()
# Relase the capture and windows
video_capture.release()
cv2.destroyAllWindows() 
# Please comment to provide feedback, if you have questions please ask, and
# Share and like , do subscribe to PyShine Youtube Channel.
#################################### Face.py  Ends ################################################
#################################### Plot.py  Starts ################################################

# Subscribe to PyShine Youtube channel for the upcoming educational videos
# Lets write the face detection code
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# Get the Figure
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.set_facecolor((0,0,0)) # Set the background to black
# 
def animate(i):
	ax.clear()
	xs = []
	ys = []
	graph_data = open('file.csv','r').read() # Open file.csv generated by Face.py
	lines = graph_data.split('\n')
	for line in lines[1:]:
		if len(line) > 1: # Skip the first labels line in csv file
			x, y = line.split(',')
			xs.append(float(x))
			ys.append(float(y))
			print(xs,ys)
	# Lets add these lists xs, ys to the plot		
	ax.clear()
	ax.plot(xs, ys,'-o', color = (0,1,0.25))
	ax.set_xlabel("Samples")
	ax.set_ylabel("Frame Rate")
	ax.set_title("Live Plot of Camera Frame Rate")
	fig.tight_layout() # To remove outside borders
	ax.yaxis.grid(True)
# Lets call the animation function 	
ani = animation.FuncAnimation(fig, animate, interval=100)
plt.show()
#################################### Plot.py  Ends ################################################
