Module misty2py_skills.face_recognition
This module implements a face recognition skill that allows Misty to greet people with their chosen name.
Global variables
var TESTING_NAME-
The name of the person testing this module. For convenience, the faces commencing with this name are forgotten in at beginning of the skill so they can be learnt again.
var UNKNOWN_LABEL-
The label used by Misty's REST API for an unknown face.
var UPDATE_TIME-
The minimum amount of time (in seconds) that must pass between Misty greets the same person again.
Functions
def face_recognition(misty: misty2py.robot.Misty) ‑> Dict-
Expand source code
def face_recognition(misty: Misty) -> Dict: """Misty detects a face, if she knows the person, she greets them by their name, else she prompts them to join a face training session. Args: misty (Misty): The Misty to perform the skill. Returns: Dict: The dictionary with `"overall_success"` key (bool) and keys for every action performed (dictionarised Misty2pyResponse). """ cancel_skills(misty) set_volume = misty.perform_action( "volume_settings", data="low_volume" ).parse_to_dict() get_faces_known = ( misty.get_info("faces_known").parse_to_dict().get("rest_response", {}) ) known_faces = get_faces_known.get("result") if not known_faces is None: print("Your misty currently knows these faces: %s." % ", ".join(known_faces)) purge_testing_faces(misty, known_faces) else: print("Your Misty currently does not know any faces.") start_face_recognition = misty.perform_action( "face_recognition_start" ).parse_to_dict() subscribe_face_recognition = misty.event( "subscribe", type="FaceRecognition", name=event_face_rec, event_emitter=ee ).parse_to_dict() status.set_(status=StatusLabels.MAIN) print(subscribe_face_recognition) print(">>> Type 'stop' to terminate <<<") user_input = "" while not ( user_input in UserResponses.STOP and status.get_("status") == StatusLabels.MAIN ): user_input = input().lower() handle_user_input(misty, user_input) unsubscribe_face_recognition = misty.event( "unsubscribe", name=event_face_rec ).parse_to_dict() print(unsubscribe_face_recognition) face_recognition_stop = misty.perform_action( "face_recognition_stop" ).parse_to_dict() speak_wrapper(misty, "Bye!") return success_of_action_dict( set_volume=set_volume, get_faces_known=get_faces_known, start_face_recognition=start_face_recognition, subscribe_face_recognition=subscribe_face_recognition, unsubscribe_face_recognition=unsubscribe_face_recognition, face_recognition_stop=face_recognition_stop, )Misty detects a face, if she knows the person, she greets them by their name, else she prompts them to join a face training session.
Args
misty:Misty- The Misty to perform the skill.
Returns
Dict- The dictionary with
"overall_success"key (bool) and keys for every action performed (dictionarised Misty2pyResponse).
def handle_greeting(misty: misty2py.robot.Misty, user_name: str) ‑> None-
Expand source code
def handle_greeting(misty: Misty, user_name: str) -> None: """Greets a person.""" status.set_(status=StatusLabels.GREET) utterance = f"Hello, {user_from_face_id(user_name)}!" speak_wrapper(misty, utterance) status.set_(status=StatusLabels.MAIN)Greets a person.
def handle_recognition(misty: misty2py.robot.Misty, label: str, det_time: float) ‑> None-
Expand source code
def handle_recognition(misty: Misty, label: str, det_time: float) -> None: """Handles recognition of a face.""" status.set_(data=label, time=det_time) if label == UNKNOWN_LABEL: training_prompt(misty) else: handle_greeting(misty, label)Handles recognition of a face.
def handle_user_input(misty: misty2py.robot.Misty, user_input: str) ‑> None-
Expand source code
def handle_user_input(misty: Misty, user_input: str) -> None: """Handles keyboard inputs.""" if user_input in UserResponses.YES and status.get_("status") == StatusLabels.PROMPT: initialise_training(misty) elif ( status.get_("status") == StatusLabels.INIT and not user_input in UserResponses.STOP ): perform_training(misty, user_input) elif ( status.get_("status") == StatusLabels.INIT and user_input in UserResponses.STOP ): d = misty.perform_action("face_train_cancel").parse_to_dict() print(d) status.set_(status=StatusLabels.MAIN) elif ( status.get_("status") == StatusLabels.TALK and user_input in UserResponses.STOP ): d = misty.perform_action("speak_stop").parse_to_dict() print(d) status.set_(status=StatusLabels.MAIN) elif status.get_("status") == StatusLabels.PROMPT: print("Training not initialised.") status.set_(status=StatusLabels.MAIN)Handles keyboard inputs.
def initialise_training(misty: misty2py.robot.Misty)-
Expand source code
def initialise_training(misty: Misty): """Initialises the face training session, including prompting the user to enter their name.""" status.set_(status=StatusLabels.INIT) speak_wrapper( misty, "<p>How should I call you?</p><p>Please enter your name in the terminal.</p>", ) print("Enter your name (the first name suffices)")Initialises the face training session, including prompting the user to enter their name.
def listener(data: Dict) ‑> None-
Expand source code
@ee.on(event_face_train) def listener(data: Dict) -> None: """Handles face training events and terminates the training session if the data states the training is complete. Args: data (Dict): The data received from Misty's WebSocket API along with the face training event. """ if data.get("message") == "Face training embedding phase complete.": speak_wrapper(misty_glob, "Thank you, the training is complete now.") status.set_(status=StatusLabels.MAIN) d = misty_glob.event("unsubscribe", name=event_face_train).parse_to_dict() print(d)Handles face training events and terminates the training session if the data states the training is complete.
Args
data:Dict- The data received from Misty's WebSocket API along with the face training event.
def perform_training(misty: misty2py.robot.Misty, name: str) ‑> None-
Expand source code
def perform_training(misty: Misty, name: str) -> None: """Performs the training. Args: misty (Misty): The Misty to learn the user's face. name (str): The name of the user. """ status.set_(status=StatusLabels.TRAIN) d = misty.get_info("faces_known").parse_to_dict().get("rest_response", {}) new_name = name if not d.get("result") is None: while new_name in d.get("result"): new_name = name + "_" + get_random_string(3) if new_name != name: print(f"The name {name} is already in use, using {new_name} instead.") if new_name == "": new_name = get_random_string(6) print(f"The name {name} is invalid, using {new_name} instead.") d = misty.perform_action( "face_train_start", data={"FaceId": new_name} ).parse_to_dict() print(d) speak_wrapper(misty, "The training has commenced, please do not look away now.") misty.event( "subscribe", type="FaceTraining", name=event_face_train, event_emitter=ee )Performs the training.
Args
misty:Misty- The Misty to learn the user's face.
name:str- The name of the user.
def purge_testing_faces(misty: misty2py.robot.Misty, known_faces: List) ‑> None-
Expand source code
def purge_testing_faces(misty: Misty, known_faces: List) -> None: """Forgets the faces of users that start with `TESTING NAME`.""" for face in known_faces: if face.startswith(TESTING_NAME): d = ( misty.perform_action("face_delete", data={"FaceId": face}) .parse_to_dict() .get("rest_response", {}) ) if d.get("success"): print("Successfully forgot the face of %s." % face) else: print("Failed to forget the face of %s." % face)Forgets the faces of users that start with
TESTING NAME. def speak_wrapper(misty: misty2py.robot.Misty, utterance: str) ‑> None-
Expand source code
def speak_wrapper(misty: Misty, utterance: str) -> None: """Changes status to `StatusLabels.TALK` while Misty is talking.""" prev_stat = status.get_("status") status.set_(status=StatusLabels.TALK) print(speak(misty, utterance)) status.set_(status=prev_stat)Changes status to
StatusLabels.TALKwhile Misty is talking. def training_prompt(misty: misty2py.robot.Misty)-
Expand source code
def training_prompt(misty: Misty): """Misty asks whether to begin a face training session.""" status.set_(status=StatusLabels.PROMPT) speak_wrapper( misty, "Hello! I do not know you yet, do you want to begin the face training session?", ) print("An unknown face detected.\nDo you want to start training (yes/no)? [no]")Misty asks whether to begin a face training session.
def user_from_face_id(face_id: str) ‑> str-
Expand source code
def user_from_face_id(face_id: str) -> str: """Returns the name from a face ID.""" return face_id.split("_")[0].capitalize()Returns the name from a face ID.
Classes
class StatusLabels (value, names=None, *, module=None, qualname=None, type=None, start=1)-
Expand source code
class StatusLabels(Enum): """Represents states in which the skill can be.""" MAIN = "running_main" """The main state of waiting for a face recognition event.""" PROMPT = "running_train_prompt" """The state of running the training prompt and waiting for the user's response.""" TRAIN = "running_training" """The face training state.""" INIT = "running_training_initialisation" """The state of the initialisation of face training.""" GREET = "running_greeting" """The state of greeting a person.""" TALK = "talking" """The state of talking."""Represents states in which the skill can be.
Ancestors
- enum.Enum
Class variables
var GREET-
The state of greeting a person.
var INIT-
The state of the initialisation of face training.
var MAIN-
The main state of waiting for a face recognition event.
var PROMPT-
The state of running the training prompt and waiting for the user's response.
var TALK-
The state of talking.
var TRAIN-
The face training state.
class UserResponses-
Expand source code
class UserResponses: """Represents responses that a user can give to different prompts used in this skill.""" YES = frozenset(["yes", "y"]) NO = frozenset(["no", "n"]) STOP = frozenset(["stop", "s", "terminate"])Represents responses that a user can give to different prompts used in this skill.
Class variables
var NOvar STOPvar YES