-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathface_identification.py
executable file
·172 lines (137 loc) · 5.96 KB
/
face_identification.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import os
from time import time
from argparse import ArgumentParser, BooleanOptionalAction
from insightface.app import FaceAnalysis
import cv2 as cv
import numpy as np
from tqdm import tqdm
import onnxruntime as ort
class FaceIdentification:
def __init__(self, model: str, thresh: float, face_bank: str):
self.threshold = thresh
self.app = FaceAnalysis(name=model, providers=ort.get_available_providers())
self.app.prepare(ctx_id=0, det_size=(640, 640))
self.face_bank = np.load(face_bank, allow_pickle=True)
def update_face_bank(self, face_bank_path: str, face_bank_name: str):
files = filter(lambda x: os.path.isdir(
os.path.join(face_bank_path, x)
), os.listdir(face_bank_path))
face_bank = []
img_name: str
for person in tqdm(files):
person_folder_path = os.path.join(face_bank_path, person)
for img_name in os.listdir(person_folder_path):
if img_name.endswith('.jpg') or img_name.endswith('.png'):
img_path = os.path.join(person_folder_path, img_name)
img = cv.cvtColor(cv.imread(img_path), cv.COLOR_BGR2RGB)
result = self.app.get(img)
if len(result) > 1:
print(
f'WARNING: more than one face detected in {img_path}')
continue
embedding = result[0]['embedding']
person_dict = {
'name': person,
'embedding': embedding
}
face_bank.append(person_dict)
np.save(face_bank_name, face_bank)
print('\nFace Bank Updated!\n')
def get_embeddings(self, face_image):
faces = self.app.get(face_image)
embeddings = []
bboxes = []
kpses = []
for face in faces:
embeddings.append(face['embedding'])
bboxes.append(map(lambda x: int(x), face['bbox']))
kpses.append(face['kps'])
return embeddings, bboxes, kpses
@staticmethod
def calc_distance(embedding1, embedding2):
return float(np.sqrt(np.sum(
(embedding1 - embedding2) ** 2
)))
@staticmethod
def draw_info(img, bbox, kps, name='unknown'):
for lm in kps:
cv.circle(img, (int(lm[0]), int(lm[1])), 5, (255, 0, 255), -1)
x1, y1, x2, y2 = bbox
if name == 'unknown':
cv.putText(img, 'unknown',
(x1, y1 - 20), cv.FONT_HERSHEY_PLAIN, 3, (0, 255, 0), 3)
cv.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
else:
cv.putText(img, name,
(x1, y1 - 20), cv.FONT_HERSHEY_PLAIN, 3, (0, 255, 0), 3)
cv.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
return img
def recognize(self, img):
recognized = []
embeddings, bboxes, kpses = self.get_embeddings(
cv.cvtColor(img, cv.COLOR_BGR2RGB))
for embedding, bbox, kps in zip(embeddings, bboxes, kpses):
for person in self.face_bank:
dis = FaceIdentification.calc_distance(
embedding, person['embedding'])
if dis <= self.threshold:
FaceIdentification.draw_info(
img, bbox, kps, person['name'])
recognized.append(person['name'])
return img, recognized
else:
FaceIdentification.draw_info(img, bbox, kps, 'unknown')
return img, []
@staticmethod
def make_online(model, thresh, face_bank_path, camera_id, is_show: bool = True) -> list[bool, str]:
iden = FaceIdentification(model, thresh, face_bank_path)
cap = cv.VideoCapture(camera_id)
is_done = False
c_time, p_time = 0, 0
once = False
while True:
success, frame = cap.read()
if not success:
return False, 'Failed to open camera'
c_time = time()
frame, recognized = iden.recognize(frame)
if c_time - p_time >= 10:
is_done = True
p_time = time()
else:
is_done = False
if len(recognized):
print(recognized)
return True, 'Welcome'
if is_done:
if once:
return False, 'Access Denied'
else:
once = True
if is_show:
cv.imshow(str(camera_id), frame)
if cv.waitKey(1) & 0xFF == 27:
return False, 'Access Denied'
def main():
arg = ArgumentParser()
arg.add_argument('--model', type=str, default='buffalo_s',
help='Enter the model')
arg.add_argument('--img', type=str, required=True,
help='Enter the image path')
arg.add_argument('--thresh', type=float, default=25.,
help='Threshold of compare')
arg.add_argument('--face-bank', type=str, default='face_bank.npy',
help='Enter the face bank file path')
arg.add_argument('--face-bank-path', type=str, default='face_bank',
help='Enter the face bank directory path')
arg.add_argument('--update', type=bool, default=False, action=BooleanOptionalAction,
help='Update the face bank')
opt = arg.parse_args()
iden = FaceIdentification(opt.model, opt.thresh, opt.face_bank)
if opt.update:
iden.update_face_bank(opt.face_bank_path, opt.face_bank)
result_img, recognized = iden.recognize(cv.imread(opt.img))
cv.imshow('Result Image', result_img)
cv.waitKey()
if __name__ == '__main__':
main()