Srastog commited on
Commit
2dfe23c
·
1 Parent(s): c79b185

Working API Added

Browse files
.gitattributes CHANGED
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ weights/face_detection_onnx_32.onnx filter=lfs diff=lfs merge=lfs -text
37
+ weights/siamese_onnx_32.onnx filter=lfs diff=lfs merge=lfs -text
38
+ weights/keypoint_68_weights.dat filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ __pycache__
2
+ */__pycache__
3
+ */*/__pycache__
api/__init__.py ADDED
File without changes
api/main.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import os
3
+ from PIL import Image
4
+ import numpy as np
5
+ from fastapi import FastAPI, UploadFile
6
+
7
+ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../src")))
8
+ from image_tagger.main import tagger
9
+
10
+ app = FastAPI(title="Face Recognition")
11
+
12
+
13
+ @app.get("/")
14
+ def display():
15
+ return "Welcome to Image Tagger Api"
16
+
17
+
18
+ @app.post("/predict")
19
+ def predict(file: UploadFile):
20
+ img = Image.open(file.file)
21
+ img = np.array(img)
22
+ img = np.transpose(img, (2, 0, 1)).astype(dtype=np.float32)
23
+ img /= 255.0
24
+ boxes, matrixs, keypoints, results = tagger(img)
25
+
26
+ return {
27
+ "predictions": results,
28
+ "boxes": boxes.tolist(),
29
+ "matrixs": [matrix.tolist() for matrix in matrixs],
30
+ "keypoints": [keypoint.tolist() for keypoint in keypoints],
31
+ }
data/actor_embedding.json ADDED
The diff for this file is too large to render. See raw diff
 
src/image_tagger/__init__.py ADDED
File without changes
src/image_tagger/components.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import dlib
3
+ import numpy as np
4
+ import onnxruntime as ort
5
+ from image_tagger import config
6
+ from image_tagger.utility import FaceAligner
7
+ from image_tagger.utility import face_similarity
8
+
9
+
10
+ def face_recognition(aligned):
11
+ print(config.FACE_EMBEDDING)
12
+ with open(config.FACE_EMBEDDING, "r") as file:
13
+ actor_embeddings = json.load(file)
14
+
15
+ face_identified = []
16
+ for face in aligned:
17
+ embedding = face_embedding(face)
18
+ identity = []
19
+ for actor in sorted(actor_embeddings.keys()):
20
+ similarity = face_similarity(embedding, actor_embeddings[actor])
21
+ identity.append((actor, similarity))
22
+ identity = [
23
+ n
24
+ for i, (n, similar) in enumerate(sorted(identity, key=lambda x: x[1]))
25
+ if i < 3
26
+ ]
27
+ face_identified.append(identity)
28
+ return face_identified
29
+
30
+
31
+ def face_detection(img):
32
+ session = ort.InferenceSession(
33
+ config.FACE_DETECTION_ONNX_WEIGHTS, providers=["CPUExecutionProvider"]
34
+ )
35
+ output = session.run([], {"input": img[np.newaxis, ...]})
36
+ return output
37
+
38
+
39
+ def face_alignment(img, boxes):
40
+ predictor = dlib.shape_predictor(config.FACE_KEYPOINT_DLIB_WEIGHTS)
41
+ aligner = FaceAligner(predictor)
42
+ matrix = []
43
+ aligned = []
44
+ facial_keypoints = []
45
+
46
+ for box in boxes:
47
+ align_image, align_matrix, face_keypoint = aligner.align(img, box)
48
+ matrix.append(align_matrix)
49
+ aligned.append(align_image)
50
+ facial_keypoints.append(face_keypoint)
51
+
52
+ return (aligned, matrix, facial_keypoints)
53
+
54
+
55
+ def face_embedding(img):
56
+ img = (img / 255.0 - config.MEAN) / config.STD
57
+ img = np.transpose(img, (2, 0, 1)).astype(np.float32)
58
+ img = img[np.newaxis, ...]
59
+ session = ort.InferenceSession(config.FACE_EMBEDDING_ONNX_WEIGHTS)
60
+ output = session.run([], {"input": img})[0][0].tolist()
61
+ return output
src/image_tagger/config.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import os
3
+
4
+ PROJECT_DIR=os.getcwd()
5
+ WEIGHT_DIR=os.path.join(PROJECT_DIR,"weights")
6
+ DATA_DIR=os.path.join(PROJECT_DIR,"data")
7
+ FACE_DETECTION_ONNX_WEIGHTS=os.path.join(WEIGHT_DIR,"face_detection_onnx_32.onnx")
8
+ FACE_KEYPOINT_DLIB_WEIGHTS=os.path.join(WEIGHT_DIR,"keypoint_68_weights.dat")
9
+ FACE_EMBEDDING_ONNX_WEIGHTS=os.path.join(WEIGHT_DIR,"siamese_onnx_32.onnx")
10
+ FACE_EMBEDDING=os.path.join(DATA_DIR,"actor_embedding.json")
11
+ MEAN=np.array([0.485,0.456,0.406])
12
+ STD=np.array([0.229,0.224,0.225])
13
+ THRESHOLD=10.50
14
+ PADDING=15
15
+ SIZE=224
src/image_tagger/main.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ from image_tagger.utility import preprocess_img
3
+ from image_tagger.components import face_detection
4
+ from image_tagger.components import face_alignment
5
+ from image_tagger.components import face_recognition
6
+
7
+ def tagger(img):
8
+ boxes,labels,scores=face_detection(img)
9
+ aligned,matrixs,keypoints=face_alignment(img, boxes)
10
+ results=face_recognition(aligned)
11
+
12
+ return (boxes, matrixs, keypoints, results)
13
+
14
+ if __name__ == '__main__':
15
+ parser=argparse.ArgumentParser()
16
+ parser.add_argument("-p","--path",required=True)
17
+ args=vars(parser.parse_args())
18
+
19
+ img=preprocess_img(args["path"])
20
+ boxes, matrixs, results = tagger(img)
21
+
src/image_tagger/utility.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import dlib
4
+ from image_tagger import config
5
+
6
+ def preprocess_img(img_pth):
7
+ img=cv2.imread(img_pth)
8
+ img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
9
+ img=(np.transpose(img,(2,0,1)).astype(dtype=np.float32))
10
+ img/=255.0
11
+
12
+ return img
13
+
14
+ def face_similarity(embed_1,embed_2):
15
+ return np.sqrt(np.sum(np.square(np.array(embed_1)-np.array(embed_2))))
16
+
17
+ class FaceAligner():
18
+ def __init__(self,predictor,desired_left_eye=(0.35,0.35),desired_face_width=config.SIZE, desired_face_height=None):
19
+ self.predictor=predictor
20
+ self.desired_left_eye=desired_left_eye
21
+ self.desired_right_eye=tuple([1-val for val in desired_left_eye])
22
+ self.desired_face_width=desired_face_width
23
+ self.desired_face_height=desired_face_height
24
+
25
+ if self.desired_face_height is None:
26
+ self.desired_face_height=self.desired_face_width
27
+
28
+ def shape_to_np(self,shape, dtype="int"):
29
+ coords = np.zeros((68, 2), dtype=dtype)
30
+ for i in range(0, 68):
31
+ coords[i] = (shape.part(i).x, shape.part(i).y)
32
+ return coords
33
+
34
+ def align(self,img,box):
35
+ image=np.transpose(img,(1,2,0)).copy()
36
+ image=(image*255).astype("uint8")
37
+
38
+ x1=max(int(box[0])-config.PADDING,0)
39
+ x2=min(int(box[2])+config.PADDING,image.shape[1])
40
+ y1=max(int(box[1])-config.PADDING,0)
41
+ y2=min(int(box[3])+config.PADDING,image.shape[0])
42
+
43
+ dlib_box=dlib.rectangle(left=x1, top=y1, right=x2, bottom=y2)
44
+
45
+ face_keypoint=self.predictor(image,dlib_box)
46
+ face_keypoint=self.shape_to_np(face_keypoint)
47
+
48
+ left_eye_center=(np.mean(face_keypoint[36:42,0]),np.mean(face_keypoint[36:42,1]))
49
+ right_eye_center=(np.mean(face_keypoint[42:48,0]),np.mean(face_keypoint[42:48,1]))
50
+
51
+ dy=right_eye_center[1]-left_eye_center[1]
52
+ dx=right_eye_center[0]-left_eye_center[0]
53
+
54
+ angle=np.degrees(np.arctan2(dy, dx))
55
+
56
+ dist=np.sqrt((dx ** 2) + (dy ** 2))
57
+ desired_dist=self.desired_right_eye[0]-self.desired_left_eye[0]
58
+ desired_dist*=self.desired_face_width
59
+ scale=desired_dist/dist
60
+
61
+ eye_center=((left_eye_center[0] + right_eye_center[0]) // 2,
62
+ (left_eye_center[1] + right_eye_center[1]) // 2)
63
+
64
+ Matrix = cv2.getRotationMatrix2D(eye_center, angle, scale)
65
+
66
+ tX = self.desired_face_width * 0.5
67
+ tY = tY = self.desired_face_height * self.desired_left_eye[1]
68
+ Matrix[0, 2] += (tX - eye_center[0])
69
+ Matrix[1, 2] += (tY - eye_center[1])
70
+
71
+ (w, h) = (self.desired_face_width, self.desired_face_height)
72
+ aligned_img = cv2.warpAffine(image, Matrix, (w,h),flags=cv2.INTER_CUBIC)
73
+
74
+ return (aligned_img, Matrix, face_keypoint)
weights/face_detection_onnx_32.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:81ce635a5105481dfd45084b0d4715f9873f8e3e3326e3c768568d75fa2fbf67
3
+ size 76044313
weights/keypoint_68_weights.dat ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fbdc2cb80eb9aa7a758672cbfdda32ba6300efe9b6e6c7a299ff7e736b11b92f
3
+ size 99693937
weights/siamese_onnx_32.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:02353e6dffae29fe97756ccf09153ed79feafb1edad158c81684919020733f26
3
+ size 45221862