Fix facial recognition
Scaling still seems to be imperfect
This commit is contained in:
parent
b6948aded2
commit
b2f10280b3
|
@ -8,7 +8,7 @@
|
||||||
"name": "Python: Module",
|
"name": "Python: Module",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"module": "set-detect-notify",
|
"module": "set_detect_notify",
|
||||||
"justMyCode": true
|
"justMyCode": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -46,7 +46,8 @@ def main():
|
||||||
# Set it to the env RUN_SCALE if it isn't blank, otherwise set it to 0.25
|
# Set it to the env RUN_SCALE if it isn't blank, otherwise set it to 0.25
|
||||||
default=os.environ["RUN_SCALE"]
|
default=os.environ["RUN_SCALE"]
|
||||||
if "RUN_SCALE" in os.environ and os.environ["RUN_SCALE"] != ""
|
if "RUN_SCALE" in os.environ and os.environ["RUN_SCALE"] != ""
|
||||||
else 0.25, # noqa: E501
|
# else 0.25,
|
||||||
|
else 1,
|
||||||
type=float,
|
type=float,
|
||||||
help="The scale to run the detection at, default is 0.25",
|
help="The scale to run the detection at, default is 0.25",
|
||||||
)
|
)
|
||||||
|
@ -55,7 +56,8 @@ def main():
|
||||||
# Set it to the env VIEW_SCALE if it isn't blank, otherwise set it to 0.75
|
# Set it to the env VIEW_SCALE if it isn't blank, otherwise set it to 0.75
|
||||||
default=os.environ["VIEW_SCALE"]
|
default=os.environ["VIEW_SCALE"]
|
||||||
if "VIEW_SCALE" in os.environ and os.environ["VIEW_SCALE"] != ""
|
if "VIEW_SCALE" in os.environ and os.environ["VIEW_SCALE"] != ""
|
||||||
else 0.75, # noqa: E501
|
# else 0.75,
|
||||||
|
else 1,
|
||||||
type=float,
|
type=float,
|
||||||
help="The scale to view the detection at, default is 0.75",
|
help="The scale to view the detection at, default is 0.75",
|
||||||
)
|
)
|
||||||
|
@ -191,6 +193,26 @@ def main():
|
||||||
for i, r in enumerate(results):
|
for i, r in enumerate(results):
|
||||||
# list of dicts with each dict containing a label, x1, y1, x2, y2
|
# list of dicts with each dict containing a label, x1, y1, x2, y2
|
||||||
plot_boxes = []
|
plot_boxes = []
|
||||||
|
|
||||||
|
# The following is stuff for people
|
||||||
|
# This is still in the for loop as each result, no matter if anything is detected, will be present.
|
||||||
|
# Thus, there will always be one result (r)
|
||||||
|
if face_details := utils.recognize_face(path_to_directory=Path(args.faces_directory), run_frame=run_frame):
|
||||||
|
plot_boxes.append( face_details )
|
||||||
|
objects_and_peoples=notify.thing_detected(
|
||||||
|
thing_name=face_details["label"],
|
||||||
|
objects_and_peoples=objects_and_peoples,
|
||||||
|
detection_type="peoples",
|
||||||
|
detection_window=args.detection_window,
|
||||||
|
detection_duration=args.detection_duration,
|
||||||
|
notification_window=args.notification_window,
|
||||||
|
ntfy_url=args.ntfy_url,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# The following is stuff for objects
|
||||||
# Setup dictionary of object names
|
# Setup dictionary of object names
|
||||||
if objects_and_peoples["objects"] == {} or objects_and_peoples["objects"] is None:
|
if objects_and_peoples["objects"] == {} or objects_and_peoples["objects"] is None:
|
||||||
for name in r.names.values():
|
for name in r.names.values():
|
||||||
|
|
|
@ -44,42 +44,51 @@ def thing_detected(
|
||||||
respective_type = objects_and_peoples[detection_type]
|
respective_type = objects_and_peoples[detection_type]
|
||||||
|
|
||||||
# (re)start cycle
|
# (re)start cycle
|
||||||
if (
|
try:
|
||||||
# If the object has not been detected before
|
|
||||||
respective_type[thing_name]["last_detection_time"] is None
|
|
||||||
# If the last detection was more than 15 seconds ago
|
|
||||||
or time.time() - respective_type[thing_name]["last_detection_time"]
|
|
||||||
> detection_window
|
|
||||||
):
|
|
||||||
# Set the last detection time to now
|
|
||||||
respective_type[thing_name]["last_detection_time"] = time.time()
|
|
||||||
print(f"First detection of {thing_name} in this detection window")
|
|
||||||
# This line is important. It resets the detection duration when the object hasn't been detected for a while
|
|
||||||
# If detection duration is None, don't print anything.
|
|
||||||
# Otherwise, print that the detection duration is being reset due to inactivity
|
|
||||||
if respective_type[thing_name]["detection_duration"] is not None:
|
|
||||||
print(
|
|
||||||
f"Resetting detection duration for {thing_name} since it hasn't been detected for {detection_window} seconds" # noqa: E501
|
|
||||||
)
|
|
||||||
respective_type[thing_name]["detection_duration"] = 0
|
|
||||||
else:
|
|
||||||
# Check if the last notification was less than 15 seconds ago
|
|
||||||
# If it was, then don't do anything
|
|
||||||
if (
|
if (
|
||||||
time.time() - respective_type[thing_name]["last_detection_time"]
|
# If the object has not been detected before
|
||||||
<= notification_window
|
respective_type[thing_name]["last_detection_time"] is None
|
||||||
|
# If the last detection was more than 15 seconds ago
|
||||||
|
or time.time() - respective_type[thing_name]["last_detection_time"]
|
||||||
|
> detection_window
|
||||||
):
|
):
|
||||||
pass
|
# Set the last detection time to now
|
||||||
# If it was more than 15 seconds ago, reset the detection duration
|
respective_type[thing_name]["last_detection_time"] = time.time()
|
||||||
# This effectively resets the notification timer
|
print(f"First detection of {thing_name} in this detection window")
|
||||||
else:
|
# This line is important. It resets the detection duration when the object hasn't been detected for a while
|
||||||
print("Notification timer has expired - resetting")
|
# If detection duration is None, don't print anything.
|
||||||
|
# Otherwise, print that the detection duration is being reset due to inactivity
|
||||||
|
if respective_type[thing_name]["detection_duration"] is not None:
|
||||||
|
print(
|
||||||
|
f"Resetting detection duration for {thing_name} since it hasn't been detected for {detection_window} seconds" # noqa: E501
|
||||||
|
)
|
||||||
respective_type[thing_name]["detection_duration"] = 0
|
respective_type[thing_name]["detection_duration"] = 0
|
||||||
respective_type[thing_name]["detection_duration"] += (
|
else:
|
||||||
time.time() - respective_type[thing_name]["last_detection_time"]
|
# Check if the last NOTIFICATION was less than 15 seconds ago
|
||||||
)
|
# If it was, then don't do anything
|
||||||
# print("Updating detection duration")
|
if (
|
||||||
respective_type[thing_name]["last_detection_time"] = time.time()
|
time.time() - respective_type[thing_name]["last_detection_time"]
|
||||||
|
<= notification_window
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
# If it was more than 15 seconds ago, reset the detection duration
|
||||||
|
# This effectively resets the notification timer
|
||||||
|
else:
|
||||||
|
print("Notification timer has expired - resetting")
|
||||||
|
respective_type[thing_name]["detection_duration"] = 0
|
||||||
|
respective_type[thing_name]["detection_duration"] += (
|
||||||
|
time.time() - respective_type[thing_name]["last_detection_time"]
|
||||||
|
)
|
||||||
|
# print("Updating detection duration")
|
||||||
|
respective_type[thing_name]["last_detection_time"] = time.time()
|
||||||
|
except KeyError:
|
||||||
|
# If the object has not been detected before
|
||||||
|
respective_type[thing_name] = {
|
||||||
|
"last_detection_time": time.time(),
|
||||||
|
"detection_duration": 0,
|
||||||
|
"last_notification_time": None,
|
||||||
|
}
|
||||||
|
print(f"First detection of {thing_name} ever")
|
||||||
|
|
||||||
# (re)send notification
|
# (re)send notification
|
||||||
# Check if detection has been ongoing for 2 seconds or more in the past 15 seconds
|
# Check if detection has been ongoing for 2 seconds or more in the past 15 seconds
|
||||||
|
|
|
@ -3,6 +3,8 @@ import numpy as np
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from deepface import DeepFace
|
from deepface import DeepFace
|
||||||
|
|
||||||
|
first_face_try = True
|
||||||
|
|
||||||
def plot_label(
|
def plot_label(
|
||||||
# list of dicts with each dict containing a label, x1, y1, x2, y2
|
# list of dicts with each dict containing a label, x1, y1, x2, y2
|
||||||
boxes: list = None,
|
boxes: list = None,
|
||||||
|
@ -67,7 +69,7 @@ def recognize_face(
|
||||||
Accepts a path to a directory of images of faces to be used as a refference
|
Accepts a path to a directory of images of faces to be used as a refference
|
||||||
In addition, accepts an opencv image to be used as the frame to be searched
|
In addition, accepts an opencv image to be used as the frame to be searched
|
||||||
|
|
||||||
Returns a list of dictionaries, containing a single dictonary as currently only 1 face can be detected in each frame
|
Returns a single dictonary as currently only 1 face can be detected in each frame
|
||||||
dict contains the following keys: label, x1, y1, x2, y2
|
dict contains the following keys: label, x1, y1, x2, y2
|
||||||
The directory should be structured as follows:
|
The directory should be structured as follows:
|
||||||
faces/
|
faces/
|
||||||
|
@ -84,8 +86,23 @@ def recognize_face(
|
||||||
Point is, `name` is the name of the person in the images in the directory `name`
|
Point is, `name` is the name of the person in the images in the directory `name`
|
||||||
That name will be used as the label for the face in the frame
|
That name will be used as the label for the face in the frame
|
||||||
'''
|
'''
|
||||||
|
global first_face_try
|
||||||
|
|
||||||
|
# If it's the first time the function is being run, remove representations_vgg_face.pkl, if it exists
|
||||||
|
if first_face_try:
|
||||||
|
try:
|
||||||
|
Path("representations_vgg_face.pkl").unlink()
|
||||||
|
print("Removing representations_vgg_face.pkl")
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
first_face_try = False
|
||||||
|
|
||||||
# face_dataframes is a vanilla list of dataframes
|
# face_dataframes is a vanilla list of dataframes
|
||||||
face_dataframes = DeepFace.find(run_frame, db_path=str(path_to_directory))
|
try:
|
||||||
|
face_dataframes = DeepFace.find(run_frame, db_path=str(path_to_directory), enforce_detection=True, silent=True)
|
||||||
|
except ValueError as e:
|
||||||
|
if str(e) == "Face could not be detected. Please confirm that the picture is a face photo or consider to set enforce_detection param to False.":
|
||||||
|
return None
|
||||||
# Iteate over the dataframes
|
# Iteate over the dataframes
|
||||||
for df in face_dataframes:
|
for df in face_dataframes:
|
||||||
# The last row is the highest confidence
|
# The last row is the highest confidence
|
||||||
|
@ -103,8 +120,12 @@ def recognize_face(
|
||||||
"x2": df.iloc[-1]["source_x"] + df.iloc[-1]["source_w"],
|
"x2": df.iloc[-1]["source_x"] + df.iloc[-1]["source_w"],
|
||||||
"y2": df.iloc[-1]["source_y"] + df.iloc[-1]["source_h"],
|
"y2": df.iloc[-1]["source_y"] + df.iloc[-1]["source_h"],
|
||||||
}
|
}
|
||||||
|
distance = df.iloc[-1]["VGG-Face_cosine"]
|
||||||
return [dict(label=label, **coordinates)]
|
# if 0.5 < distance < 0.7:
|
||||||
|
# label = "Unknown"
|
||||||
|
to_return = dict(label=label, **coordinates)
|
||||||
|
print(f'Confindence: {distance}, filname: {path_to_image.name}, to_return: {to_return}')
|
||||||
|
return to_return
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Example dataframe, for reference
|
Example dataframe, for reference
|
||||||
|
|
Loading…
Reference in New Issue