change readmeW.md to readme.md
This commit is contained in:
parent
93c597dd94
commit
b1a4a892b4
|
|
@ -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.
|
||||||
|
```
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
@ -51,6 +51,7 @@ class Status(Enum):
|
||||||
BASE64_EMPTY = "base64 is empty"
|
BASE64_EMPTY = "base64 is empty"
|
||||||
NotImplementedError = "Not Implemented Error"
|
NotImplementedError = "Not Implemented Error"
|
||||||
ADD_HAS_EXISTED = "when adding, file has existed"
|
ADD_HAS_EXISTED = "when adding, file has existed"
|
||||||
|
DB_NO_FACE = "face_db has no face"
|
||||||
|
|
||||||
GLOBAL_DICT = {
|
GLOBAL_DICT = {
|
||||||
"ADD": Opt.ADD,
|
"ADD": Opt.ADD,
|
||||||
|
|
@ -65,6 +66,7 @@ GLOBAL_DICT = {
|
||||||
}
|
}
|
||||||
|
|
||||||
class FaceHelper:
|
class FaceHelper:
|
||||||
|
|
||||||
def __init__(self, db_path: str, detector_backend: str, distance_metric: str, model_name: str):
|
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.db_path = "C:/Users/JIALE/Desktop/bns_proj/proj_deepface/face"
|
||||||
self.detector_backend = "opencv"
|
self.detector_backend = "opencv"
|
||||||
|
|
@ -75,6 +77,10 @@ class FaceHelper:
|
||||||
self.threshold = verification.find_threshold(model_name, distance_metric)
|
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.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):
|
def get_facial_areas(self, img: np.ndarray):
|
||||||
"""
|
"""
|
||||||
Find facial area coordinates in the given image
|
Find facial area coordinates in the given image
|
||||||
|
|
@ -88,8 +94,6 @@ class FaceHelper:
|
||||||
detected_face
|
detected_face
|
||||||
descriptions
|
descriptions
|
||||||
"""
|
"""
|
||||||
# print("get facial areas, img.shape: ", img.shape)
|
|
||||||
# beg = time.time()
|
|
||||||
try:
|
try:
|
||||||
face_objs = detection.extract_faces(
|
face_objs = detection.extract_faces(
|
||||||
img_path = img,
|
img_path = img,
|
||||||
|
|
@ -203,7 +207,6 @@ class FaceHelper:
|
||||||
if retjson['status'] == 0:
|
if retjson['status'] == 0:
|
||||||
return retjson
|
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")]
|
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 opt_mode == Opt.ADD: # add
|
||||||
if img_name in db_imgs:
|
if img_name in db_imgs:
|
||||||
|
|
@ -215,34 +218,18 @@ class FaceHelper:
|
||||||
return Status.NotImplementedError
|
return Status.NotImplementedError
|
||||||
|
|
||||||
# update the face_db to keep latest
|
# update the face_db to keep latest
|
||||||
search_identity( # 保证database是最新的
|
self.dirty = True
|
||||||
detected_face=np.zeros([224, 224, 3]),
|
self.keepDBLive()
|
||||||
db_path=self.db_path,
|
|
||||||
detector_backend=self.detector_backend,
|
|
||||||
distance_metric=self.distance_metric,
|
|
||||||
model_name=self.model_name,
|
|
||||||
)
|
|
||||||
|
|
||||||
return retjson
|
return retjson
|
||||||
|
|
||||||
|
|
||||||
#interface 2: face recognition using embeddings on face_db
|
#interface 2: face recognition using embeddings on face_db
|
||||||
def faceRecog(self, img: Union[str,np.ndarray], img_mode: Ftype):
|
def faceRecog(self, img: Union[str,np.ndarray], img_mode: Ftype):
|
||||||
# keep the database is the newest
|
# keep the database is the newest
|
||||||
search_identity(
|
if self.dirty:
|
||||||
detected_face=np.zeros([224, 224, 3]),
|
self.keepDBLive()
|
||||||
db_path=self.db_path,
|
if len(self.db_representations) <= 0:
|
||||||
detector_backend=self.detector_backend,
|
return Status.DB_NO_FACE
|
||||||
distance_metric=self.distance_metric,
|
|
||||||
model_name=self.model_name,
|
|
||||||
)
|
|
||||||
|
|
||||||
# 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
|
# process the img
|
||||||
ret = FaceHelper.process_img(img, img_mode)
|
ret = FaceHelper.process_img(img, img_mode)
|
||||||
|
|
@ -251,7 +238,7 @@ class FaceHelper:
|
||||||
target_img = ret
|
target_img = ret
|
||||||
|
|
||||||
# begin face recognition
|
# begin face recognition
|
||||||
df = pd.DataFrame(db_representations)
|
df = pd.DataFrame(self.db_representations)
|
||||||
labels = []
|
labels = []
|
||||||
|
|
||||||
face_coors, detected_faces, descriptions = self.get_facial_areas(target_img)
|
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)
|
success, encoded_target_img = cv2.imencode('.png', target_img)
|
||||||
if success:
|
if success:
|
||||||
target_img_base64 = base64.b64encode(encoded_target_img).decode("utf-8")
|
target_img_base64 = base64.b64encode(encoded_target_img).decode("utf-8")
|
||||||
|
|
||||||
return labels, face_coors, target_img_base64
|
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(
|
facehelper = FaceHelper(
|
||||||
db_path = "C:/Users/JIALE/Desktop/bns_proj/proj_deepface/face",
|
db_path = "C:/Users/JIALE/Desktop/bns_proj/proj_deepface/face",
|
||||||
|
|
@ -305,22 +311,47 @@ facehelper = FaceHelper(
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
class item(BaseModel):
|
class item(BaseModel):
|
||||||
type: str
|
TYPE: str
|
||||||
img: str
|
img: str
|
||||||
img_name: 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/")
|
@app.post("/init/")
|
||||||
# def master(input: item ):
|
def init(input: config):
|
||||||
# return {"type": item["type"], "img":"fdasfsdf"}
|
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/")
|
@app.post("/interface/")
|
||||||
def main(input: item):
|
def main(input: item):
|
||||||
interface_type, img_mode, opt_mode = input.type.split("_")
|
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]
|
img_mode = GLOBAL_DICT[img_mode]
|
||||||
if interface_type == "UPDATEDB":
|
except KeyError:
|
||||||
|
return {"status": 0, "description": "wrong img_mode"}
|
||||||
|
try:
|
||||||
opt_mode = GLOBAL_DICT[opt_mode]
|
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
|
# call updateFaceDB for handling the picture
|
||||||
ret = facehelper.updateFaceDB(img = input.img,
|
ret = facehelper.updateFaceDB(img = input.img,
|
||||||
img_name = input.img_name,
|
img_name = input.img_name,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue