-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathface_detector.py
More file actions
131 lines (101 loc) · 4.12 KB
/
face_detector.py
File metadata and controls
131 lines (101 loc) · 4.12 KB
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
import cv2
from facenet_pytorch import MTCNN, InceptionResnetV1
import torch
import os
import numpy as np
from dotenv import load_dotenv
from pymongo import MongoClient
import datetime
import pytz
import text_speech
load_dotenv()
db_url = os.getenv("DB_URL", "mongodb://localhost:27017/")
workers = 0 if os.name == 'nt' else 2
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
print('Running on device: {}'.format(device))
mtcnn = MTCNN(
image_size=160, margin=0, min_face_size=20,
thresholds=[0.6, 0.7, 0.7], factor=0.709, post_process=True,
device=device
)
resnet = InceptionResnetV1(pretrained='vggface2').eval().to(device)
cam = cv2.VideoCapture(0)
ret, frame = cam.read()
if not ret:
print("Failed to take frame")
name = ""
client = MongoClient(db_url)
db = client.memory_lane
relatives = db.relatives
try:
loaded_dict = torch.load("face_embeddings.pt")
except:
loaded_dict = {}
def updateEmbeddings():
global loaded_dict
try:
loaded_dict = torch.load("face_embeddings.pt")
except:
loaded_dict = {}
def take_photo(intent):
ret, frame = cam.read()
if not ret:
print("Failed to take frame")
return
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
x_aligned, prob = mtcnn(frame, return_prob=True)
if x_aligned is not None:
# print('Face detected with probability: {:8f}'.format(prob))
aligned = []
aligned.append(x_aligned)
# Generate embedding
aligned = torch.stack(aligned).to(device)
embeddings = resnet(aligned).detach().cpu()
distances = []
# Compare with existing embeddings (Calculate distance)
for x in loaded_dict:
for y in loaded_dict[x]:
tempDistance = []
tempDistance.append((embeddings - y).norm().item())
tempDistance = np.array(tempDistance)
distances.append(tempDistance.mean())
distances = np.array(distances)
# Find the closest match
minIndex = np.argmin(distances)
if distances[minIndex] > 0.9:
print("Unknown face")
text_speech.speak("Sorry, I don't know him")
else:
name = list(loaded_dict.keys())[minIndex]
print("Face Recognized :", name)
from bson.objectid import ObjectId
result = relatives.find_one({"_id" : ObjectId(name)})
if result:
if result['gender'].lower() == 'male':
pronoun = "He"
elif result['gender'].lower() == 'female':
pronoun = "She"
else:
pronoun = "It"
if intent == 'name':
text_speech.speak(pronoun + " is " + result[intent])
relatives.update_one({"name" : result['name']}, {"$set" : {"last_meet" : datetime.datetime.utcnow()}})
elif intent == 'address':
text_speech.speak(pronoun + " lives in " + result[intent])
relatives.update_one({"name" : result['name']}, {"$set" : {"last_meet" : datetime.datetime.utcnow()}})
elif intent == 'last_meet':
if 'last_meet' in result:
ist = pytz.timezone('Asia/Kolkata')
ist_now = result[intent].replace(tzinfo=pytz.utc).astimezone(ist)
# print("Last time you met was on", ist_now.strftime("%d %B %Y at %H:%M"))
text_speech.speak("Last time you met was on " + ist_now.strftime("%d %B %Y at %H:%M"))
else:
text_speech.speak("I don't remember when you met him the last time")
elif intent == 'relationship':
text_speech.speak(pronoun + " is your " + result[intent])
relatives.update_one({"name" : result['name']}, {"$set" : {"last_meet" : datetime.datetime.utcnow()}})
else:
print("No face detected")
text_speech.speak("Sorry, I didn't see any face")
def releaseCam():
cam.release()