def __init__( self, model_loc: str = "./models", persistent_data_loc="data/facial_data.json", face_detection_threshold: int = 0.99, face_detector: str = "dlib", ) -> None: """Constructor Args: model_loc (str, optional): Path where model files are saved. Defaults to "./models". persistent_data_loc (str, optional): Path to save the persistence storage file. Defaults to 'data/facial_data.json'. face_detection_threshold (int, optional): Threshold facial model confidence to consider a detection. Defaults to 0.99. face_detector (str, optional): Type of face detector to use. Options: Dlib-HOG and MMOD, MTCNN, OpenCV CNN. Defaults to 'dlib'. Raises: ModelFileMissing: Raised when model file is not found """ keypoints_model_path = os.path.join( model_loc, FaceRecognition.keypoints_model_path ) face_recog_model_path = os.path.join( model_loc, FaceRecognition.face_recog_model_path ) if not ( path_exists(keypoints_model_path) or path_exists(face_recog_model_path) ): raise ModelFileMissing if face_detector == "opencv": self.face_detector = FaceDetectorOpenCV( model_loc=model_loc, crop_forehead=True, shrink_ratio=0.2 ) elif face_detector == "mtcnn": self.face_detector = FaceDetectorMTCNN(crop_forehead=True, shrink_ratio=0.2) else: self.face_detector = FaceDetectorDlib() self.face_detection_threshold = face_detection_threshold self.keypoints_detector = dlib.shape_predictor(keypoints_model_path) self.face_recognizor = dlib.face_recognition_model_v1(face_recog_model_path) self.datastore = FaceDataStore(persistent_data_loc=persistent_data_loc)
def register_face_path(self, img_path: str, name: str) -> None: if not path_exists(img_path): raise PathNotFound try: img = cv2.imread(img_path) facial_data = self.face_recognizer.register_face( image=convert_to_rgb(img), name=name) if facial_data: logger.info("Face registered...") return True return False except Exception as exc: raise exc
def get_all_data(self) -> List: """Returns a list of facial data of all the registered users from cache. Returns: List[Dict]: [description] """ # Data load will fail incase the file doesn't exist if not path_exists(self.db_loc): raise DatabaseFileNotFound try: # load the existing data with open(self.db_loc, "r") as f: data = json.load(f) # convert the list to tuple to keep # consistency across return self.sanitize_data(data) except Exception as exc: raise exc
def add_data(self, face_data: Dict): """Adds facial data to persistent DB. Args: face_data (Dict): [description] """ data = [] # check if the db exists, otherwise create one base_path, filename = os.path.split(self.db_loc) if not path_exists(base_path): logger.info("DB path doesn't exist! Attempting path creation...") os.makedirs(base_path) if os.path.exists(self.db_loc): # load the existing data data = self.get_all_data() try: # Add the new data and save to disk data.append(face_data) self.save_data(data=data) logger.info("Data saved to DB...") except Exception as exc: raise exc
def recognize_face_video( self, video_path: str = None, detection_interval: int = 15, save_output: bool = False, preview: bool = False, output_path: str = "data/output.mp4", resize_scale: float = 0.5, verbose: bool = True, ) -> None: if video_path is None: # If no video source is given, try # switching to webcam video_path = 0 elif not path_exists(video_path): raise FileNotFoundError cap, video_writer = None, None try: cap = cv2.VideoCapture(video_path) # To save the video file, get the opencv video writer video_writer = get_video_writer(cap, output_path) frame_num = 1 matches, name, match_dist = [], None, None t1 = time.time() logger.info("Enter q to exit...") while True: status, frame = cap.read() if not status: break try: # Flip webcam feed so that it looks mirrored if video_path == 0: frame = cv2.flip(frame, 2) if frame_num % detection_interval == 0: # Scale down the image to increase model # inference time. smaller_frame = convert_to_rgb( cv2.resize(frame, (0, 0), fx=resize_scale, fy=resize_scale) ) # Detect faces matches = self.face_recognizer.recognize_faces( image=smaller_frame, threshold=0.6, bboxes=None ) if verbose: self.annotate_facial_data(matches, frame, resize_scale) if save_output: video_writer.write(frame) if preview: cv2.imshow("Preview", cv2.resize(frame, (680, 480))) key = cv2.waitKey(1) & 0xFF if key == ord("q"): break except Exception: pass frame_num += 1 t2 = time.time() logger.info("Time:{}".format((t2 - t1) / 60)) logger.info("Total frames: {}".format(frame_num)) logger.info("Time per frame: {}".format((t2 - t1) / frame_num)) except Exception as exc: raise exc finally: cv2.destroyAllWindows() cap.release() video_writer.release()
def teardown_method(self): if path_exists(self.persistent_db_loc): os.remove(self.persistent_db_loc)