You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
9.2 KiB
Python

#!/usr/bin/python3
import traceback
import datetime, imutils, cv2, argparse,os,sys
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import numpy as np
cur_dir = os.getcwd().split('/')[-1]
if cur_dir=='colemano':
from src.config import *
elif cur_dir =='src':
from config import *
elif cur_dir=='geografia':
from colemano.src.config import *
elif cur_dir=='demo_flask':
sys.path.append('./..')
from src.config import *
class ColeMano():
def __init__(self, gestures_path=GESTURES_PATH,model_path=MODEL_PATH, predict_path=PREDICT_PATH):
self.model = load_model(model_path)
self.gestures_path = gestures_path
self.prepare_predict_path(predict_path)
self.init_gestures()
self.live=False
self.ison=False
def prepare_predict_path(self,predict_path):
self.predict_path = predict_path + '/0'
os.makedirs(self.predict_path,exist_ok=True)
for f in os.listdir(self.predict_path):
os.remove(f"{self.predict_path}/{f}")
def init_gestures(self):
self.datagen_root = ImageDataGenerator(
samplewise_center=True,
samplewise_std_normalization=True,
brightness_range=[0.8, 1.0],
zoom_range=[1.0, 1.2]
)
self.gestures = self.datagen_root.flow_from_directory(
self.gestures_path ,
target_size=TARGET_SIZE,
color_mode="rgb",
shuffle=False,
class_mode='categorical',
batch_size=1).class_indices
self.gestures = {v:k for k,v in self.gestures.items()}
def video_init(self, recorded_video=None):
if recorded_video:
self.video = cv2.VideoCapture(recorded_video)
self.live =False
else:
self.video = cv2.VideoCapture(-1)
self.live = True
print(f'video opened : {self.video.isOpened()}')
self.video.set(cv2.CAP_PROP_FRAME_WIDTH, 480)
self.video.set(cv2.CAP_PROP_FRAME_HEIGHT, 420)
def show_example(self,what):
if isinstance(what,int):
what=self.gestures[what]
def get_gray(self, frame):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
return cv2.GaussianBlur(gray, (21, 21), 0)
def get_frame(self, bg_frame=None,x_origin=-1, y_origin=-1, width=-1, height=-1):
if not bg_frame:
success, bg_frame = self.video.read()
else:
success=True
if not success:
bg_frame = np.zeros((480,420,3))
if x_origin+y_origin+width+height>=4:
cv2.rectangle(bg_frame, (x_origin, y_origin), (x_origin + width, y_origin + height), (255, 0, 0), 2)
frame = bg_frame[x_origin:x_origin+width,y_origin:y_origin+height,:]
else:
frame=bg_frame
return bg_frame, frame
def thresholdContours(self,gray):
# compute the absolute difference between the current frame and first frame
frameDelta = cv2.absdiff(self.firstFrame, gray)
thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1]
# dilate the thresholded image to fill in holes, then find contours on thresholded image
thresh = cv2.dilate(thresh, None, iterations=2)
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
return imutils.grab_contours(cnts)
def contoursLooper(self,frame, cnts,min_area=7000,show_contour_box=True):
# loop over the contours
current_area_sum=0
for ic,c in enumerate(cnts):
# if the contour is too small, ignore it
last_area = cv2.contourArea(c)
if last_area < min_area:
continue
current_area_sum += last_area
# compute the bounding box for the contour, draw it on the frame and update the text
if show_contour_box:
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
return current_area_sum
def predict_routine(self,gesture,ix=0,num_predict_samples=1):
if ix==num_predict_samples-1:
probs = self.model.predict(self.datagen_root.flow(self.frames,batch_size=1))
probs = np.mean(probs,axis=0) # or median
pred = np.argmax(probs)
gesture = self.gestures[pred]
elif ix==num_predict_samples:
ix=0
return gesture,ix
def routine_check(self,frame,ix,last_area_sum,current_area_sum, same_gesture_ratio=.3):
if last_area_sum==0:
last_area_sum=current_area_sum
key = cv2.waitKey(1) & 0xFF
if key == ord(QUIT_BUTTON):
ix=-1
elif (key == ord(PHOTO_BUTTON)) or ((current_area_sum!=0) and (abs((last_area_sum - current_area_sum) / last_area_sum) < same_gesture_ratio)):
self.frames[ix,...] = frame
ix+=1
return ix
def clean_cv2(self):
self.video.release()
cv2.destroyAllWindows()
def flask_routine(self, min_area=7000,same_gesture_ratio=0.3, num_predict_samples=3, show_contour_box=True):
if not self.live:
self.video_init()
self.firstFrame = None
last_area_sum=0
ix=0
gesture='no sign'
empty_frames = np.zeros((num_predict_samples,TARGET_SIZE[0],TARGET_SIZE[1],3))
self.frames = empty_frames.copy()
while True:
try:
bg_frame, frame = self.get_frame(None,X_ORIGIN,Y_ORIGIN,WIDTH,HEIGHT)
gray = self.get_gray(frame)
success=True
except Exception as e:
print(traceback.format_exc())
print("\n\n scostumat', non mi aspettavo proprio un errore come di cui sopra da te \n\n")
bg_frame = np.zeros((480,420,3))
bg_frame, frame = self.get_frame(bg_frame,X_ORIGIN,Y_ORIGIN,WIDTH,HEIGHT)
success=False
if self.ison and success:
gray = self.get_gray(frame)
# if the first frame is None, initialize it
if self.firstFrame is None:
self.firstFrame = gray
continue
cnts = self.thresholdContours(gray)
current_area_sum = self.contoursLooper(frame,cnts, min_area, show_contour_box)
ix=self.routine_check(frame,ix,last_area_sum,current_area_sum,same_gesture_ratio)
if ix<0:
break
gesture,ix = self.predict_routine(gesture, ix=ix, num_predict_samples=num_predict_samples)
last_area_sum=current_area_sum
cv2.putText(frame, "---> {} <---".format(gesture), (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
"""
else:
cv2.putText(bg_frame, "lascia lo sfondo nel riquadro piu neutro ed omogeneo possibile",(10,10),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2)
cv2.putText(bg_frame, "cerca di non apparire con il tuo corpicino la dentro",(10,20),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2)
cv2.putText(bg_frame, "infine premi start per iniziare il riconoscimento",(10,30),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2)
"""
ret, buffer = cv2.imencode('.jpg', bg_frame)
frame = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n') # concat frame one by one and show result
#yield bg_frame
print("\n\n chiudo tutte cose lisio \n\n")
self.clean_cv2()
def routine(self, min_area=7000,same_gesture_ratio=0.3, num_predict_samples=3, show_contour_box=True):
if not self.live:
self.video_init()
self.firstFrame = None
last_area_sum=0
ix=0
gesture='nada'
self.frames = np.zeros((num_predict_samples,TARGET_SIZE[0],TARGET_SIZE[1],3))
try:
while True:
bg_frame, frame = self.get_frame(None,X_ORIGIN,Y_ORIGIN,WIDTH,HEIGHT)
gray = self.get_gray(frame)
# if the first frame is None, initialize it
if self.firstFrame is None:
self.firstFrame = gray
continue
cnts = self.thresholdContours(gray)
current_area_sum = self.contoursLooper(frame,cnts, min_area, show_contour_box)
ix=self.routine_check(frame,ix,last_area_sum,current_area_sum,same_gesture_ratio)
if ix<0:
break
gesture,ix = self.predict_routine(gesture, ix=ix, num_predict_samples=num_predict_samples)
last_area_sum=current_area_sum
cv2.putText(frame, "---> {} <---".format(gesture), (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.imshow("Colemano Reco",bg_frame)
print("\n\n chiudo tutte cose lisio \n\n")
self.clean_cv2()
except Exception as e:
print(traceback.format_exc())
print("\n\n scostumat', non mi aspettavo proprio un errore come di cui sopra da te \n\n")
finally:
self.clean_cv2()