import base64 import os import requests import cv2 import numpy as np from PIL import Image from .exceptions import InvalidImage from .emotionsmultilanguage import emotions_dict def draw_annotations( frame: np.ndarray, faces: list, boxes=True, scores=True, color: tuple = (0, 155, 255), lang: str = "en", size_multiplier: int = 1, ) -> np.ndarray: """Draws boxes around detected faces. Faces is a list of dicts with `box` and `emotions`.""" if not len(faces): return frame for face in faces: x, y, w, h = face["box"] emotions = face["emotions"] if boxes: cv2.rectangle( frame, (x, y, w, h), color, 2, ) if scores: frame = draw_scores(frame, emotions, (x, y, w, h), lang, size_multiplier) return frame def loadBase64Img(uri): encoded_data = uri.split(",")[1] nparr = np.fromstring(base64.b64decode(encoded_data), np.uint8) img = cv2.imdecode(nparr, cv2.IMREAD_COLOR) return img def pil_to_bgr(pil_image): return cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR) def load_image(img): """Modified from github.com/serengil/deepface. Returns bgr (opencv-style) numpy array.""" is_exact_image = is_base64_img = is_url_img = False if type(img).__module__ == np.__name__: is_exact_image = True elif img is None: raise InvalidImage("Image not valid.") elif len(img) > 11 and img[0:11] == "data:image/": is_base64_img = True elif len(img) > 11 and img.startswith("http"): is_url_img = True if is_base64_img: img = loadBase64Img(img) elif is_url_img: img = pil_to_bgr(Image.open(requests.get(img, stream=True).raw)) elif not is_exact_image: # image path passed as input if not os.path.isfile(img): raise ValueError(f"Confirm that {img} exists") img = cv2.imread(img) if img is None or not hasattr(img, "shape"): raise InvalidImage("Image not valid.") return img def draw_scores( frame: np.ndarray, emotions: dict, bounding_box: dict, lang: str = "en", size_multiplier: int = 1, ) -> np.ndarray: """Draw scores for each emotion under faces.""" GRAY = (211, 211, 211) GREEN = (0, 255, 0) x, y, w, h = bounding_box for idx, (emotion, score) in enumerate(emotions.items()): color = GRAY if score < 0.01 else GREEN if lang != "en": emotion = emotions_dict[emotion][lang] emotion_score = "{}: {}".format( emotion, "{:.2f}".format(score) if score >= 0.01 else "" ) cv2.putText( frame, emotion_score, ( x, y + h + (15 * size_multiplier) + idx * (15 * size_multiplier), ), cv2.FONT_HERSHEY_SIMPLEX, 0.5 * size_multiplier, color, 1 * size_multiplier, cv2.LINE_AA, ) return frame