import cv2 import os import gradio as gr import numpy as np from keras.models import load_model from keras.utils import load_img, img_to_array from tensorflow.image import resize from PIL import Image #gradio interface def process_image(img): """ Parameters: img: np.ndarray an image (e.g., returned by cv2.imread) Returns: img: np.ndarray an image annotated with the bounding box and label """ cv2_face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') img = resize_img(img) img, _ = annotate_objects_in_image(img, cv2_face_cascade, model.labeldict, model.predictor) return(img) def annotate_objects_in_image(img, obj_cascade, labeldict, model): """ Parameters: img: np.ndarray an image (e.g., returned by cv2.imread) obj_cascade: cv2.CascadeClassifier OpenCV cascade classifier that can detect certain objects labeldict: dict a dictionary for decoding the model predictions, (e.g., {0:happy, 1:sad}) model: keras.engine.functional.Functional a Keras model instance (e.g., that is returned by keras.models.load_model) Returns: img: np.ndarray an image annotated with the bounding box and label emotion : str predicted emotion of the face image """ img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) objects = obj_cascade.detectMultiScale(img_gray, 1.1, 4) emotion = "" try: for (x, y, w, h) in objects: face = img[y-50:y+h+50, x-50:x+w+50] emotion, prob = predict_emotion_from_image(face, labeldict, model) font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(img, emotion, (x, y), font, 1, (0, 0, 255), 2, cv2.LINE_AA) cv2.rectangle(img, (x-25, y-25), (x+w+25, y+h+25), (0, 255, 0), 2) except Exception as ex: emotion = "" return img, emotion def predict_emotion_from_image (face_raw, labeldict, model): """ Parameters: face_raw: np.ndarray a square-like image of a human face (e.g., returned by cv2.imread) label_dict: dict a dictionary for decoding the model predictions, (e.g., {0:happy, 1:sad}) model: keras.engine.functional.Functional a Keras model instance (e.g., that is returned by keras.models.load_model) Returns: emotion: str predicted emotion of the face image prob: float percent probability of the predicted emotion """ face_res_arr = np.array(cv2.resize(face_raw, (48, 48))) face_res_arr_gray = face_res_arr/255 face_res_arr_gray_4dims = np.expand_dims(face_res_arr_gray, axis=0) prediction_vec = model.predict(face_res_arr_gray_4dims) prediction = np.argmax(prediction_vec) emotion = labeldict[prediction] prob = prediction_vec.max()*100 return (emotion,prob) def resize_img(img): """ Parameters: img: np.ndarray a potentially oversized image (e.g., returned by cv2.imread) Returns: img: np.ndarray a resized and potentially L-R flipped image """ if img.shape[0]> 960: img_AR = img.shape[0]/img.shape[1] #print(f'img shape: {img.shape}; aspect ratio: {img_AR}') img = cv2.resize(img, (640, int(np.round(640*img_AR)))) return img class ModelClass: def __init__(self,name='EDA_CNN.h5'): self.name = name self.predictor = load_model(os.path.join("models",modeltouse)) if name == "model_mobilenet_oncleandata_valacc078.h5": self.labeldict = {0: 'fear', 1: 'Angry', 2: 'Neutral', 3: 'Happy'} else: self.labeldict = {0: 'Angry', 1: 'Disgust', 2: 'Fear', 3: 'Happy', 4: 'Sad', 5: 'Surprise', 6: 'Neutral'} if name == "EDA_CNN.h5": self.channelno = 1 else: self.channelno = 3 #modeltouse = "EDA_CNN.h5" modeltouse = "MobileNet12blocks_wdgenaug_onrawdata_valacc063.h5" #modeltouse = "model_mobilenet_oncleandata_valacc078.h5" model = ModelClass(modeltouse) image_in = gr.inputs.Image() #shape=(48,48) image_out = gr.inputs.Image() examples = ['OnurH_CerenH.jpg', 'OnurA_CerenH.jpg'] #fname = 'Onur_happy.jpg' #image = cv2.imread(fname) #process_image(image, model) intf = gr.Interface(fn=process_image, inputs=image_in, outputs=image_out, examples=examples) intf.launch(inline=False)