anki_vector.faces

Face recognition and enrollment.

Vector is capable of recognizing human faces, tracking their position and rotation (“pose”) and assigning names to them via an enrollment process.

The anki_vector.world.World object keeps track of faces the robot currently knows about, along with those that are currently visible to the camera.

Each face is assigned a Face object, which generates a number of observable events whenever the face is observed or when the face id is updated.

Classes

EvtFaceAppeared(face, image_rect, name, pose)

Triggered whenever a face is first visually identified by a robot.

EvtFaceDisappeared(face)

Triggered whenever a face that was previously being observed is no longer visible.

EvtFaceObserved(face, image_rect, name, pose)

Triggered whenever a face is visually identified by the robot.

Expression

Facial expressions that Vector can distinguish.

Face(robot, pose, image_rect, face_id, name, …)

A single face that Vector has detected.

FaceComponent(robot)

Manage the state of the faces on the robot.

class anki_vector.faces.Expression

Facial expressions that Vector can distinguish.

Facial expression not recognized. Call anki_vector.robot.Robot.vision.enable_face_detection(detect_faces=True)() to enable recognition.

ANGER = 4

Facial expression anger

HAPPINESS = 2

Facial expression happiness

NEUTRAL = 1

Facial expression neutral

SADNESS = 5

Facial expression sadness

SURPRISE = 3

Facial expression surprise

class anki_vector.faces.Face(robot, pose, image_rect, face_id, name, expression, expression_score, left_eye, right_eye, nose, mouth, instantiation_timestamp, **kw)

A single face that Vector has detected.

May represent a face that has previously been enrolled, in which case name will hold the name that it was enrolled with.

Each Face instance has a face_id integer - This may change if Vector later gets an improved view and makes a different prediction about which face he is looking at.

expression

The facial expression Vector has recognized on the face.

Will be Expression.UNKNOWN by default if you haven’t called anki_vector.robot.Robot.vision.enable_face_detection(detect_faces=True, estimate_emotion=True)() to enable the facial expression estimation. Otherwise it will be equal to one of: Expression.NEUTRAL, Expression.HAPPINESS, Expression.SURPRISE, Expression.ANGER, or Expression.SADNESS.

import time

import anki_vector
from anki_vector.events import Events
from anki_vector.util import degrees

def test_subscriber(robot, event_type, event):
    print(f"Subscriber called for: {event_type} = {event}")

    for face in robot.world.visible_faces:
        print(f"Expression: {face.expression}")

with anki_vector.Robot(enable_face_detection=True) as robot:
    # If necessary, move Vector's Head and Lift to make it easy to see his face
    robot.behavior.set_head_angle(degrees(45.0))
    robot.behavior.set_lift_height(0.0)

    robot.events.subscribe(test_subscriber, Events.robot_changed_observed_face_id)
    robot.events.subscribe(test_subscriber, Events.robot_observed_face)

    print("------ show vector your face, press ctrl+c to exit early ------")
    try:
        time.sleep(10)
    except KeyboardInterrupt:
        robot.disconnect()
Return type

str

expression_score

The score/confidence that expression was correct.

Will be 0 if expression is Expression.UNKNOWN (e.g. if anki_vector.robot.Robot.vision.enable_face_detection(detect_faces=True, estimate_emotion=True)() wasn’t called yet). The maximum possible score is 100.

import time

import anki_vector
from anki_vector.events import Events
from anki_vector.util import degrees

def test_subscriber(robot, event_type, event):
    print(f"Subscriber called for: {event_type} = {event}")

    for face in robot.world.visible_faces:
        print(f"Expression score: {face.expression_score}")

with anki_vector.Robot(enable_face_detection=True) as robot:
    # If necessary, move Vector's Head and Lift to make it easy to see his face
    robot.behavior.set_head_angle(degrees(45.0))
    robot.behavior.set_lift_height(0.0)

    robot.events.subscribe(test_subscriber, Events.robot_changed_observed_face_id)
    robot.events.subscribe(test_subscriber, Events.robot_observed_face)

    print("------ show vector your face, press ctrl+c to exit early ------")
    try:
        time.sleep(10)
    except KeyboardInterrupt:
        robot.disconnect()
Return type

List[int]

face_id

The internal ID assigned to the face.

This value can only be assigned once as it is static in the engine.

Getter

Returns the face ID

Setter

Sets the face ID

import time

import anki_vector
from anki_vector.events import Events
from anki_vector.util import degrees

def test_subscriber(robot, event_type, event):
    print(f"Subscriber called for: {event_type} = {event}")

    for face in robot.world.visible_faces:
        print(f"Visible face id: {face.face_id}")

with anki_vector.Robot(enable_face_detection=True) as robot:
    # If necessary, move Vector's Head and Lift to make it easy to see his face
    robot.behavior.set_head_angle(degrees(45.0))
    robot.behavior.set_lift_height(0.0)

    robot.events.subscribe(test_subscriber, Events.robot_changed_observed_face_id)
    robot.events.subscribe(test_subscriber, Events.robot_observed_face)

    print("------ show vector your face, press ctrl+c to exit early ------")
    try:
        time.sleep(10)
    except KeyboardInterrupt:
        robot.disconnect()
Return type

int

has_updated_face_id

True if this face been updated / superseded by a face with a new ID.

import time

import anki_vector
from anki_vector.events import Events
from anki_vector.util import degrees

def test_subscriber(robot, event_type, event):
    print(f"Subscriber called for: {event_type} = {event}")

    for face in robot.world.visible_faces:
        was_face_originally_unrecognized_but_is_now_recognized = face.has_updated_face_id

with anki_vector.Robot(enable_face_detection=True) as robot:
    # If necessary, move Vector's Head and Lift to make it easy to see his face
    robot.behavior.set_head_angle(degrees(45.0))
    robot.behavior.set_lift_height(0.0)

    robot.events.subscribe(test_subscriber, Events.robot_changed_observed_face_id)
    robot.events.subscribe(test_subscriber, Events.robot_observed_face)

    print("------ show vector your face, press ctrl+c to exit early ------")
    try:
        time.sleep(10)
    except KeyboardInterrupt:
        robot.disconnect()
Return type

bool

left_eye

points representing the outline of the left eye.

import time

import anki_vector
from anki_vector.events import Events
from anki_vector.util import degrees

def test_subscriber(robot, event_type, event):
    print(f"Subscriber called for: {event_type} = {event}")

    for face in robot.world.visible_faces:
        print(f"Left eye: {face.left_eye}")

with anki_vector.Robot(enable_face_detection=True) as robot:
    # If necessary, move Vector's Head and Lift to make it easy to see his face
    robot.behavior.set_head_angle(degrees(45.0))
    robot.behavior.set_lift_height(0.0)

    robot.events.subscribe(test_subscriber, Events.robot_changed_observed_face_id)
    robot.events.subscribe(test_subscriber, Events.robot_observed_face)

    print("------ show vector your face, press ctrl+c to exit early ------")
    try:
        time.sleep(10)
    except KeyboardInterrupt:
        robot.disconnect()
Return type

List[CladPoint]

Type

sequence of tuples of float (x,y)

mouth

points representing the outline of the mouth.

import time

import anki_vector
from anki_vector.events import Events
from anki_vector.util import degrees

def test_subscriber(robot, event_type, event):
    print(f"Subscriber called for: {event_type} = {event}")

    for face in robot.world.visible_faces:
        print(f"Mouth: {face.mouth}")

with anki_vector.Robot(enable_face_detection=True) as robot:
    # If necessary, move Vector's Head and Lift to make it easy to see his face
    robot.behavior.set_head_angle(degrees(45.0))
    robot.behavior.set_lift_height(0.0)

    robot.events.subscribe(test_subscriber, Events.robot_changed_observed_face_id)
    robot.events.subscribe(test_subscriber, Events.robot_observed_face)

    print("------ show vector your face, press ctrl+c to exit early ------")
    try:
        time.sleep(10)
    except KeyboardInterrupt:
        robot.disconnect()
Return type

List[CladPoint]

Type

sequence of tuples of float (x,y)

name

The name Vector has associated with the face.

This string will be empty if the face is not recognized or enrolled.

import time

import anki_vector
from anki_vector.events import Events
from anki_vector.util import degrees

def test_subscriber(robot, event_type, event):
    print(f"Subscriber called for: {event_type} = {event}")

    for face in robot.world.visible_faces:
        print(f"Face name: {face.name}")

with anki_vector.Robot(enable_face_detection=True) as robot:
    # If necessary, move Vector's Head and Lift to make it easy to see his face
    robot.behavior.set_head_angle(degrees(45.0))
    robot.behavior.set_lift_height(0.0)

    robot.events.subscribe(test_subscriber, Events.robot_changed_observed_face_id)
    robot.events.subscribe(test_subscriber, Events.robot_observed_face)

    print("------ show vector your face, press ctrl+c to exit early ------")
    try:
        time.sleep(10)
    except KeyboardInterrupt:
        robot.disconnect()
Return type

str

nose

points representing the outline of the nose.

import time

import anki_vector
from anki_vector.events import Events
from anki_vector.util import degrees

def test_subscriber(robot, event_type, event):
    print(f"Subscriber called for: {event_type} = {event}")

    for face in robot.world.visible_faces:
        print(f"Nose: {face.nose}")

with anki_vector.Robot(enable_face_detection=True) as robot:
    # If necessary, move Vector's Head and Lift to make it easy to see his face
    robot.behavior.set_head_angle(degrees(45.0))
    robot.behavior.set_lift_height(0.0)

    robot.events.subscribe(test_subscriber, Events.robot_changed_observed_face_id)
    robot.events.subscribe(test_subscriber, Events.robot_observed_face)

    print("------ show vector your face, press ctrl+c to exit early ------")
    try:
        time.sleep(10)
    except KeyboardInterrupt:
        robot.disconnect()
Return type

List[CladPoint]

Type

sequence of tuples of float (x,y)

right_eye

points representing the outline of the right eye.

import time

import anki_vector
from anki_vector.events import Events
from anki_vector.util import degrees

def test_subscriber(robot, event_type, event):
    print(f"Subscriber called for: {event_type} = {event}")

    for face in robot.world.visible_faces:
        print(f"Right eye: {face.right_eye}")

with anki_vector.Robot(enable_face_detection=True) as robot:
    # If necessary, move Vector's Head and Lift to make it easy to see his face
    robot.behavior.set_head_angle(degrees(45.0))
    robot.behavior.set_lift_height(0.0)

    robot.events.subscribe(test_subscriber, Events.robot_changed_observed_face_id)
    robot.events.subscribe(test_subscriber, Events.robot_observed_face)

    print("------ show vector your face, press ctrl+c to exit early ------")
    try:
        time.sleep(10)
    except KeyboardInterrupt:
        robot.disconnect()
Return type

List[CladPoint]

Type

sequence of tuples of float (x,y)

teardown()

All faces will be torn down by the world when no longer needed.

updated_face_id

The ID for the face that superseded this one (if any, otherwise face_id())

import time

import anki_vector
from anki_vector.events import Events
from anki_vector.util import degrees

def test_subscriber(robot, event_type, event):
    print(f"Subscriber called for: {event_type} = {event}")

    for face in robot.world.visible_faces:
        print(f"Updated face id: {face.updated_face_id}")

with anki_vector.Robot(enable_face_detection=True) as robot:
    # If necessary, move Vector's Head and Lift to make it easy to see his face
    robot.behavior.set_head_angle(degrees(45.0))
    robot.behavior.set_lift_height(0.0)

    robot.events.subscribe(test_subscriber, Events.robot_changed_observed_face_id)
    robot.events.subscribe(test_subscriber, Events.robot_observed_face)

    print("------ show vector your face, press ctrl+c to exit early ------")
    try:
        time.sleep(10)
    except KeyboardInterrupt:
        robot.disconnect()
Return type

int

class anki_vector.faces.FaceComponent(robot)

Manage the state of the faces on the robot.

erase_all_enrolled_faces()

Erase the enrollment (name) records for all faces.

import anki_vector

with anki_vector.Robot() as robot:
    robot.faces.erase_all_enrolled_faces()
erase_enrolled_face_by_id(face_id)

Erase the enrollment (name) record for the face with this ID.

Parameters

face_id (int) – The ID of the face to erase.

import anki_vector

with anki_vector.Robot() as robot:
    robot.faces.erase_enrolled_face_by_id(1)
request_enrolled_names()

Asks the robot for the list of names attached to faces that it can identify.

import anki_vector

with anki_vector.Robot() as robot:
    name_data_list = robot.faces.request_enrolled_names()
    print(f"{name_data_list}")
Return type

RequestEnrolledNamesRequest

update_enrolled_face_by_id(face_id, old_name, new_name)

Update the name enrolled for a given face.

Parameters
  • face_id (int) – The ID of the face to rename.

  • old_name (str) – The old name of the face (must be correct, otherwise message is ignored).

  • new_name (str) – The new name for the face.

import anki_vector

with anki_vector.Robot() as robot:
    robot.faces.update_enrolled_face_by_id(1, 'Hanns', 'Boris')