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
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()
|
|
|
|
|
|
|
|
|