diff --git a/proj_deepface/readme.md b/proj_deepface/readme.md new file mode 100644 index 0000000..66128b8 --- /dev/null +++ b/proj_deepface/readme.md @@ -0,0 +1,54 @@ +ref: https://github.com/serengil/deepface + +# model store +model checkpoint 放在了 `C:\Users\User\.deepface\weights` + +# installation +``` +$ pip install deepface +``` + +# Usage: +``` +(deepface_v2) PS path/to/workspace> python +Python 3.7.16 (default, Jan 17 2023, 16:06:28) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32 +Type "help", "copyright", "credits" or "license" for more information. +>>> from deepface import DeepFace +``` + +# Model introduce +``` +Deepface is a hybrid face recognition package. It currently wraps many state-of-the-art face recognition models: +model_name Declared LFW Score +VGG-Face 98.9% +Facenet 99.2% +Facenet512 99.6% drop +OpenFace 92.9% +DeepID 97.4% +Dlib 99.3% +SFace 99.5% +ArcFace 99.5% 阈值调整为1.00 ** +GhostFaceNet 99.7% ** +Human-beings 97.5% + +The default configuration uses VGG-Face model. +``` + +``` +backends = { + "opencv": OpenCv.OpenCvClient, + "mtcnn": MtCnn.MtCnnClient, + "ssd": Ssd.SsdClient, + "dlib": Dlib.DlibClient, + "retinaface": RetinaFace.RetinaFaceClient, + "mediapipe": MediaPipe.MediaPipeClient, + "yolov8": Yolo.YoloClient, + "yunet": YuNet.YuNetClient, + "fastmtcnn": FastMtCnn.FastMtCnnClient, +} +``` + +``` +distance_metric = ['euclidean_l2','cosine','euclidean'] +author: Euclidean L2 form seems to be more stable than cosine and regular Euclidean distance based on experiments. +``` \ No newline at end of file diff --git a/proj_deepface/readmeW.md b/proj_deepface/readmeW.md deleted file mode 100644 index 6911e84..0000000 --- a/proj_deepface/readmeW.md +++ /dev/null @@ -1,14 +0,0 @@ -ref: https://github.com/serengil/deepface - -# store -model checkpoint 放在了 `C:\Users\JIALE\.deepface\weights` - -# installation - - -# Usage: -(deepface_v2) PS C:\Users\JIALE\Desktop\bns_proj\proj_deepface> python -Python 3.7.16 (default, Jan 17 2023, 16:06:28) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32 -Type "help", "copyright", "credits" or "license" for more information. ->>> from deepface import DeepFace - diff --git a/proj_deepface/webmain.py b/proj_deepface/webmain.py index 9c978e6..b64009d 100644 --- a/proj_deepface/webmain.py +++ b/proj_deepface/webmain.py @@ -51,6 +51,7 @@ class Status(Enum): BASE64_EMPTY = "base64 is empty" NotImplementedError = "Not Implemented Error" ADD_HAS_EXISTED = "when adding, file has existed" + DB_NO_FACE = "face_db has no face" GLOBAL_DICT = { "ADD": Opt.ADD, @@ -65,6 +66,7 @@ GLOBAL_DICT = { } class FaceHelper: + def __init__(self, db_path: str, detector_backend: str, distance_metric: str, model_name: str): self.db_path = "C:/Users/JIALE/Desktop/bns_proj/proj_deepface/face" self.detector_backend = "opencv" @@ -74,7 +76,11 @@ class FaceHelper: self.target_size = self.model.input_shape self.threshold = verification.find_threshold(model_name, distance_metric) self.pkl_name = f"ds_{self.model_name}_{self.detector_backend}_v2.pkl".replace("-", "").lower() - + + self.dirty = True + self.db_representations = None + self.keepDBLive() + def get_facial_areas(self, img: np.ndarray): """ Find facial area coordinates in the given image @@ -88,8 +94,6 @@ class FaceHelper: detected_face descriptions """ - # print("get facial areas, img.shape: ", img.shape) - # beg = time.time() try: face_objs = detection.extract_faces( img_path = img, @@ -202,8 +206,7 @@ class FaceHelper: if retjson['status'] == 0: return retjson - - # db_imgs = os.listdir(self.db_path) + db_imgs = [db_img.split(".")[0] for db_img in os.listdir(self.db_path) if db_img.endswith(".jpg")] if opt_mode == Opt.ADD: # add if img_name in db_imgs: @@ -215,35 +218,19 @@ class FaceHelper: return Status.NotImplementedError # update the face_db to keep latest - search_identity( # 保证database是最新的 - detected_face=np.zeros([224, 224, 3]), - db_path=self.db_path, - detector_backend=self.detector_backend, - distance_metric=self.distance_metric, - model_name=self.model_name, - ) - + self.dirty = True + self.keepDBLive() + return retjson - #interface 2: face recognition using embeddings on face_db def faceRecog(self, img: Union[str,np.ndarray], img_mode: Ftype): # keep the database is the newest - search_identity( - detected_face=np.zeros([224, 224, 3]), - db_path=self.db_path, - detector_backend=self.detector_backend, - distance_metric=self.distance_metric, - model_name=self.model_name, - ) + if self.dirty: + self.keepDBLive() + if len(self.db_representations) <= 0: + return Status.DB_NO_FACE - # open and read face db - datastore_path = os.path.join(self.db_path, self.pkl_name) - with open(datastore_path, "rb") as f: - db_representations = pickle.load(f) - assert len(db_representations) > 0, 'no face in database' - print(f"{len(db_representations)} faces representataion in {self.pkl_name}.") - # process the img ret = FaceHelper.process_img(img, img_mode) if isinstance(ret, Status): @@ -251,7 +238,7 @@ class FaceHelper: target_img = ret # begin face recognition - df = pd.DataFrame(db_representations) + df = pd.DataFrame(self.db_representations) labels = [] face_coors, detected_faces, descriptions = self.get_facial_areas(target_img) @@ -292,8 +279,27 @@ class FaceHelper: success, encoded_target_img = cv2.imencode('.png', target_img) if success: target_img_base64 = base64.b64encode(encoded_target_img).decode("utf-8") + return labels, face_coors, target_img_base64 + def keepDBLive(self): + # keep the database is the newest + search_identity( + detected_face=np.zeros([224, 224, 3]), + db_path=self.db_path, + detector_backend=self.detector_backend, + distance_metric=self.distance_metric, + model_name=self.model_name, + ) + self.dirty = False + + # load the representations from face_db + datestore_path = os.path.join(self.db_path, self.pkl_name) + with open(datestore_path, "rb") as f: + self.db_representations = pickle.load(f) + + return len(self.db_representations) + facehelper = FaceHelper( db_path = "C:/Users/JIALE/Desktop/bns_proj/proj_deepface/face", @@ -305,22 +311,47 @@ facehelper = FaceHelper( app = FastAPI() class item(BaseModel): - type: str + TYPE: str img: str img_name: str +class config(BaseModel): + db_path: str # default: "C:/Users/JIALE/Desktop/bns_proj/proj_deepface/face" + detector_backend: str #default: + distance_metric: str + model_name: str -# @app.post("/master/") -# def master(input: item ): -# return {"type": item["type"], "img":"fdasfsdf"} +@app.post("/init/") +def init(input: config): + facehelper = FaceHelper( + db_path = input.db_path, + detector_backend = input.detector_backend, + distance_metric = input.distance_metric, + model_name = input.model_name, +) + +@app.get("/keepDBLastest") +def keepDBLastest(): + ret = facehelper.keepDBLive() + return {"status":"the faceDB is lastest", "description": f"db has {ret} faces"} @app.post("/interface/") def main(input: item): - interface_type, img_mode, opt_mode = input.type.split("_") - img_mode = GLOBAL_DICT[img_mode] - if interface_type == "UPDATEDB": + vars = input.TYPE.split("_") + if len(vars) != 3: + return {"status": 0, "description":"wrong TYPE"} + interface_type, img_mode, opt_mode = vars + try: + img_mode = GLOBAL_DICT[img_mode] + except KeyError: + return {"status": 0, "description": "wrong img_mode"} + try: opt_mode = GLOBAL_DICT[opt_mode] + except KeyError: + return {"status": 0, "description": "wrong opt_mode"} + + if interface_type == "UPDATEDB": # call updateFaceDB for handling the picture ret = facehelper.updateFaceDB(img = input.img, img_name = input.img_name,