Webhooks
You can set up FindFace Multi to automatically send notifications about specific events, episodes, and counter records to a given URL. To do so, create and configure a webhook. In this case, when such an event, episode, or a counter record occurs, FindFace Multi will send an HTTP request to the URL configured for the webhook.
You can use webhooks for various purposes, for instance, to notify a user about a specific event, invoke required behavior on a target website, and solve security tasks such as automated access control.
In this section:
Configure Webhook
Important
The user must have corresponding permissions to create, view, change or delete a webhook. To manage permissions, navigate to Settings → Role.
Note
To use the webhooks, make sure that at least one of the following parameters is specified in /opt/findface-multi/configs/findface-multi-legacy/findface-multi-legacy.py
: SERVICE_EXTERNAL_ADDRESS
or EXTERNAL_ADDRESS
.
To create and configure a webhook, do the following:
Navigate to the Settings tab. Click Webhooks.
Click + New webhook.
Specify the webhook header.
Specify URL to automatically send notifications to.
You can send notifications in batches. Specify the maximum number of notifications in a webhook batch. The actual number may be less.
Specify the maximum number of attempts to send a notification. The interval between attempts increases exponentially with a maximum of 100 seconds.
Important
To receive all messages since the connection loss, should it happen, set
0
. Set1
to omit old messages.FindFace Multi will be automatically sending notifications on events, episodes, and counter records that match given filters.
There are two ways to configure filters:
visually
by code
To configure filters visually, click Configure.
Generic filters for recognition events (face, body, vehicle):
Matches: filter events only with/without matches, or all events.
Watch lists: filter events only for a selected watch list, or all events.
Camera groups: filter only events from a selected group of cameras.
Cameras: filter only events from a selected camera.
Record name: filter events with a given record name.
Event’s best shot: filter all events of a track, only events with real-time snapshots, only one event with the best snapshot at the end of a track.
Line: filter events with a given line crossing.
Line crossing direction: filter events with line crossing of a given direction, or all events.
Has reverse crossing: filter events with/without reverse crossing.
Filters specific for face recognition events:
Age: filter events with people of a given age.
Beard: filter events by the fact of having a beard.
Emotions: filter events with given emotions.
Gender: filter events with people of a given gender.
Glasses: filter events by the fact of wearing glasses.
Liveness: filter events by face liveness.
Face mask: filter events by the fact of wearing a face mask.
Head turn: filter events by degree of head turn.
Head tilt: filter events by degree of head tilt.
Filters specific for body recognition events:
Gender by body: filter only events with people of a given gender or all events.
Age by body: filter only events with people of a given age.
Headwear: filter only events with a person wearing headgear of a given type: hat/cap, hood/headscarf, none.
Vest: filter only events with a person wearing a vest of a given color.
Helmet: filter only events with a person wearing a helmet of a given color.
Upper clothes color: filter only events with a person wearing a top of a given color.
Lower clothes color: filter only events with a person wearing a bottom of a given color.
Upper clothes type: filter only events with a person wearing upper body wear of a given specific type: jacket, coat, sleeveless vest, sweatshirt, T-shirt, shirt, dress.
Lower body clothes: filter only events with a person wearing lower body wear of a given type: pants, skirt, shorts, obscured.
Upper body clothes: filter only events with a person wearing upper body wear of a given generalized category: long sleeves, short sleeves, no sleeve.
Bag on the back: filter only events with a person wearing/not wearing a bag on the back.
Bag in hand: filter only events with a person wearing/not wearing a bag in hand.
Filters specific for vehicle recognition events:
Make: filter vehicle events by vehicle make.
Model: filter vehicle events by vehicle model.
Vehicle body type: filter only events with vehicles of a given body type: suv, sedan, crossover, convertible, coupe, shooting brake, pickup, van, minivan, limousine.
Vehicle body color: filter only events with vehicles of a given color.
Country: filter only events with vehicles registered in a given country.
License plate number: filter an event with a given plate number.
Special vehicle: filter only events with vehicles belonging to a given type: police, fire service and EMERCOM vehicles, gas rescue and emergency services, military, municipal vehicles, and others.
Vehicle category: filter only events with vehicles belonging to a given category: motorcycle, scooter, car, car with a trailer, truck, truck with a trailer, bus, articulated bus, and others.
Vehicle weight and body size: filter only events with vehicles of a given weight and body size.
Vehicle orientation: filter only events with vehicles of a given orientation.
Note
License plate color, Region are disabled by default. To enable these parameters, uncomment
"license_plate_number_color"
,"license_plate_region"
in the sectionFFSECURITY_UI_CONFIG
in the configuration file/opt/findface-multi/configs/findface-multi-legacy/findface-multi-legacy.py
.sudo vi /opt/findface-multi/configs/findface-multi-legacy/findface-multi-legacy.py FFSECURITY_UI_CONFIG = { ... "cars": { "features": { ... "license_plate_number_color": [ "unknown", "white", "yellow", "blue", "green", "grey", ], ... "license_plate_region": ["unknown", "DXB", "SHJ", "ADH", "AJM", "UAK", "RAK", "FUJ"], ... }, .... }, }
Restart FindFace Multi containers after you have applied the changes.
cd /opt/findface-multi/ sudo docker-compose restart
Episodes with individuals:
Episode types: filter episodes by status (open/have events/close).
Matches: faces: filter episodes only with/without face matches, or all events.
Matches: bodies: filter episodes only with/without body matches, or all events.
Watch lists: filter episodes only for a selected watch list, or all episodes.
Camera groups: filter only episodes from a selected group of cameras.
Cameras: filter only episodes from a selected camera.
Record name: filter episodes with a given record name.
Count events: filter only episodes with a given number of events.
Episodes with vehicles:
Episode types: filter episodes by status (open/have events/close).
Matches: filter episodes only with/without matches, or all events.
Watch lists: filter episodes only for a selected watch list, or all episodes.
Camera groups: filter only episodes from a selected group of cameras.
Cameras: filter only episodes from a selected camera.
Record name: filter episodes with a given record name.
Episode ID: filter an episode with a given ID.
Count events: filter only episodes with a given number of events.
Counter records:
Camera groups: filter only counter records from a selected group of cameras.
Cameras: filter only counter records from a selected camera.
Count faces ≥: filter counter records by count of faces.
Count bodies ≥: filter counter records by count of bodies.
Count vehicles ≥: filter counter records by count of vehicles.
Counter ID: filter counter records with a given ID.
Minimum distance: send a notification if the detected minimum distance is in specified range.
Maximum distance: send a notification if the detected maximum distance is in specified range.
Average distance: send a notification if the detected average distance is in specified range.
For a number of filters there’s also an option to specify a confidence threshold.
Note
Several parameters are available in the code mode only and are not represented as visual filters. To properly configure these parameters by code, read their descriptions.
To configure filters by code, switch to the Code view. Use the following descriptions:
Generic filters for recognition events (face, body, vehicle):
Sections:
face_events
,body_events
,car_events
."matched_lists"
: watch list ID, [integer]."camera_groups"
: camera group ID, [integer]."cameras"
: camera ID, [integer]."matched_card"
: matched record ID, [integer]."matched"
: thematched
status. Settrue
orfalse
if only matched or unmatched events must trigger sending a notification, boolean."confidence_gte"
: minimum confidence, number. Min 0, Max 1."bs_type"
: object tracking mode, [string]. Possible values:overall
,realtime
."line"
: line crossing ID, [integer]."line_crossing_direction"
: line crossing direction, [enum]. Possible values:AB
,BA
."backward_line_crossing"
: Settrue
orfalse
if event has or hasn’t reverse crossing, boolean.
Filters specific for face recognition events:
Section:
face_events
."headpose_yaw_angle_gte"
: minimum head turn, integer (degrees). If a head is turned fully to the left, the yaw angle is-180
. If it is turned fully to the right, it’s180
. The neutral head position is0
."headpose_yaw_angle_lte"
: maximum head turn, integer (degrees). If a head is turned fully to the left, the yaw angle is-180
. If it is turned fully to the right, it’s180
. The neutral head position is0
."headpose_pitch_angle_gte"
: minimum head tilt, integer (degrees). If a head is tilted forward with the chin touching the chest, it’s-180
. If a head is tilted backward facing the sky, it’s180
. The neutral head position is0
."headpose_pitch_angle_lte"
: maximum head tilt, integer (degrees). If a head is tilted forward with the chin touching the chest, it’s-180
. If a head is tilted backward facing the sky, it’s180
. The neutral head position is0
."gender"
: gender, [string]. Possible values:"male"
,"female"
, [string]."age_lte"
: maximum age, integer."age_gte"
: minimum age, integer."glasses"
: glasses, [string]. Possible values:"none"
,"eye"
(eyeglasses),"sun"
(sunglasses)."emotions"
: emotions, [string]. Possible values:"any"
,"angry"
,"fear"
,"sad"
,"neutral"
,"disgust"
,"happy"
,"surprise"
."beard"
: beard, [string]. Possible values:"none"
,"beard"
."medmask"
: face mask, [string]. Possible values:"correct"
,"incorrect"
,"none"
."liveness"
: liveness, [string]. Possible values:"real"
,"fake"
."temperature_gte"
: minimum temperature, number."liveness_gte"
: minimum algorithm confidence that a face belongs to a live person, number. Min 0, Max 1.
Filters specific for body recognition events:
Section:
body_events
."headwear"
: type of headgear (hat/cap, hood/headscarf, none), [string]. Possible values:"hat"
,"hood"
,"none"
."upper_clothes"
: generalized category of upper body wear (long sleeves, short sleeves, no sleeve), [string]. Possible values:"long_sleeves"
,"short_sleeves"
,"without_sleeves"
."detailed_upper_clothes"
: specific type of upper body wear (jacket, coat, sleeveless vest, sweatshirt, T-shirt, shirt, dress), [string]. Possible values:"jacket"
,"coat"
,"sleeveless"
,"sweatshirt"
,"t-shirt"
,"shirt"
,"dress"
."top_color"
: top clothing color, [string]. Possible values:white
,"black"
,"grey"
,"brown"
,"red"
,"orange"
,"yellow"
,"green"
,"lightblue"
,"blue"
,"purple"
,"pink"
,"beige"
,"violet"
."lower_clothes"
: type of lower body wear (pants, skirt, shorts, nondescript), [string]. Possible values:"pants"
,"obscured"
,"skirt"
,"shorts"
."bottom_color"
: bottom clothing color, [string]. Possible values:white
,"black"
,"grey"
,"brown"
,"red"
,"orange"
,"yellow"
,"green"
,"lightblue"
,"blue"
,"purple"
,"pink"
,"beige"
,"violet"
."bag_hand"
: whether a person has a bag in hand(s), [string]. Possible values:"none"
,"hand"
."bag_ground"
: whether a person has a bag on the ground. Possible values:"ground"
,"none"
."bag_back"
: whether a person has a bag on the back, [string]. Possible values:"none"
,"back"
."vest_type_score_gte"
: minimum recognition confidence of a vest presence, number. Min 0, Max 1."vest_type_score_lte"
: maximum recognition confidence of a vest presence, number. Min 0, Max 1."vest_type"
: presence of personal protective equipment in the form of a vest, [string]. Possible values:"green/yellow"
,"orange"
,"not_visible"
,"none"
."helmet_type_score_lte"
: maximum recognition confidence of a helmet presence, number. Min 0, Max 1."helmet_type_score_gte"
: minimum recognition confidence of a helmet presence, number. Min 0, Max 1."helmet_type"
: presence of personal protective equipment in the form of a helmet, [string]. Possible values:"red/orange"
,"white"
,"other"
,"not_visible"
,"none"
."age_group_score_lte"
: maximum age group recognition confidence, number. Min 0, Max 1."age_group_score_gte"
: minimum age group recognition confidence, number. Min 0, Max 1."age_group"
: age by group, [string]. Possible values:"0-16"
,"17-35"
,"36-50"
,"50+"
."gender_score_lte"
: maximum gender recognition confidence, number."gender_score_gte"
: minimum gender recognition confidence, number."body_gender"
: gender, [string]. Possible values:"male"
,"female"
.
Filters specific for vehicle recognition events:
Section:
car_events
."category_confidence_gte"
: minimum recognition confidence of the vehicle category, number. Min 0, Max 1."category_confidence_lte"
: maximum recognition confidence of the vehicle category, number. Min 0, Max 1."category_type"
: vehicle category, [string]. Possible values:"unknown"
,"A"
,"B"
,"BE"
,"C"
,"CE"
,"D"
,"DE"
,"other"
."color"
vehicle color, [string]. Possible values:"beige"
,"black"
,"blue"
,"brown"
,"cyan"
,"gold"
,"green"
,"grey"
,"orange"
,"pink"
,"purple"
,"red"
,"silver"
,"violet"
,"white"
,"yellow"
."body"
: vehicle body style, [string]. Possible values:"suv"
,"sedan"
,"crossover"
,"convertible"
,"coupe"
,"wagon"
,"cab"
,"minibus"
,"minivan"
,"limousine"
."make"
: vehicle make, [string]. Check out the corresponding event filter to see what makes are supported in the current version."model"
: vehicle model, [string]. Check out the corresponding event filter to see what models are supported in the current version."license_plate_number"
: license plate number, [string]. Wildcards are not supported."license_plate_number_color"
: license plate color, [string]. Possible values:"unknown"
,"white"
,"yellow"
,"blue"
,"green"
,"grey"
."license_plate_number_color_confidence_lte"
: maximum recognition confidence of the license plate color, number."license_plate_number_color_confidence_gte"
: minimum recognition confidence of the license plate color, number."license_plate_country"
: license plate country, [string]. Check out the corresponding event filter to see what countries are supported in the current version."license_plate_region"
: license plate region, [string]. Check out the corresponding event filter to see what regions are supported in the current version."special_vehicle_type"
: special vehicle type, [string]. Possible values:"taxi"
,"route_transport"
,"car_sharing"
,"ambulance"
,"police"
,"rescue_service"
,"gas_service"
,"military"
,"road_service"
,"other_special"
,"not_special"
."weight_type"
: vehicle weight type, [string]. Possible values:"B_light"
,"B_heavy"
,"C_light"
,"C_heavy"
,"D_light"
,"D_long"
,"other"
."weight_type_confidence_lte"
: maximum recognition confidence of the vehicle weight type, number. Min 0, Max 1."weight_type_confidence_gte"
: minimum recognition confidence of the vehicle weight type, number. Min 0, Max 1."orientation"
: vehicle orientation, [string]. Possible values:"front"
,"back"
,"side"
."orientation_confidence_lte"
: maximum recognition confidence of the vehicle orientation, number. Min 0, Max 1."orientation_confidence_gte"
: minimum recognition confidence of the vehicle orientation, number. Min 0, Max 1.
Episodes with individuals:
Section:
human_episodes
."allowed_types"
: episode status, [string]. Possible values: an episode opening (episode_open
), adding a new event into an episode (episode_event
), an episode closing (episode_close
)."matched_lists"
: watch list ID, [integer]."cameras"
: camera ID, [integer]."camera_groups"
: camera group ID, [integer]."events_count_gte"
: minimum number of events in an episode, integer."events_count_lte"
: maximum number of events in an episode, integer."face_matched"
: thematched
status of face events in an episode, boolean. Settrue
if only matched faces orfalse
if only unmatched faces must trigger sending a notification."body_matched"
: thematched
status of body events in an episode, boolean. Settrue
if only matched bodies orfalse
if only unmatched bodies must trigger sending a notification.
Episodes with vehicles:
Section:
car_episodes
."allowed_types"
: episode status, [string]. Possible values: an episode opening (episode_open
), adding a new event into an episode (episode_event
), an episode closing (episode_close
)."matched_lists"
: watch list ID, [integer]."cameras"
: camera ID, number."camera_groups"
: camera group ID, [integer]."events_count_gte"
: minimum number of events in an episode, integer."events_count_lte"
: maximum number of events in an episode, integer."car_matched"
: thematched
status of car events in an episode, boolean. Settrue
if only matched cars orfalse
if only unmatched cars must trigger sending a notification.
Counter records:
Section:
counters
."counter"
: counter ID, [integer]."cameras"
: camera ID, [integer]."camera_groups"
: camera group ID, [integer]."faces_count_gte"
: minimum number of faces in a counter record, integer."faces_count_lte"
: maximum number of faces in a counter record, integer."silhouettes_count_gte"
: minimum number of bodies in a counter record, integer."silhouettes_count_lte"
: maximum number of bodies in a counter record, integer."cars_count_gte"
: minimum number of vehicles in a counter record, integer."cars_count_lte"
: maximum number of vehicles in a counter record, integer."proximity_min_lte"
: send a notification if the minimum detected distance in meters is less than this value, number."proximity_min_gte"
: send a notification if the minimum detected distance in meters is greater than this value, number."proximity_avg_lte"
: send a notification if the average detected distance in meters is less than this value, number."proximity_avg_gte"
: send a notification if the average detected distance in meters is greater than this value, number."proximity_max_lte"
: send a notification if the maximum detected distance in meters is less than this value, number."proximity_max_gte"
: send a notification if the maximum detected distance in meters is greater than this value, number.
Example
Note
This example is given for reference only, substitute your values in corresponding fields.
{ "face_events": { "matched_lists": [ -1 ], "camera_groups": [ -1 ], "cameras": [ 1 ], "matched_card": [ 1 ], "matched": false, "confidence_gte": 0, "bs_type": [ "overall" ], "line": [ 1 ], "line_crossing_direction": [ "AB" ], "backward_line_crossing": false, "headpose_yaw_angle_gte": -180, "headpose_yaw_angle_lte": -180, "headpose_pitch_angle_gte": -180, "headpose_pitch_angle_lte": -180, "gender": [ "A" ], "age_lte": 0, "age_gte": 0, "glasses": [ "A" ], "emotions": [ "A" ], "beard": [ "A" ], "medmask": [ "A" ], "liveness": [ "A" ], "temperature_gte": 0, "liveness_gte": 0 }, "body_events": { "matched_lists": [ -1 ], "camera_groups": [ -1 ], "cameras": [ 1 ], "matched_card": [ 1 ], "matched": false, "confidence_gte": 0, "bs_type": [ "overall" ], "line": [ 1 ], "line_crossing_direction": [ "AB" ], "backward_line_crossing": false, "headwear": [ "A" ], "upper_clothes": [ "A" ], "detailed_upper_clothes": [ "A" ], "top_color": [ "A" ], "lower_clothes": [ "A" ], "bottom_color": [ "A" ], "bag_hand": [ "A" ], "bag_ground": [ "A" ], "bag_back": [ "A" ], "vest_type_score_gte": 0, "vest_type_score_lte": 0, "vest_type": [ "A" ], "helmet_type_score_lte": 0, "helmet_type_score_gte": 0, "helmet_type": [ "A" ], "age_group_score_lte": 0, "age_group_score_gte": 0, "age_group": [ "A" ], "gender_score_lte": 0, "gender_score_gte": 0, "body_gender": [ "A" ] }, "car_events": { "matched_lists": [ -1 ], "camera_groups": [ -1 ], "cameras": [ 1 ], "matched_card": [ 1 ], "matched": false, "confidence_gte": 0, "bs_type": [ "overall" ], "line": [ 1 ], "line_crossing_direction": [ "AB" ], "backward_line_crossing": false, "category_confidence_gte": 0, "category_confidence_lte": 0, "category_type": [ "A" ], "color": [ "A" ], "body": [ "A" ], "make": [ "A" ], "model": [ "A" ], "license_plate_number": [ "A" ], "license_plate_number_color": [ "A" ], "license_plate_number_color_confidence_lte": 0, "license_plate_number_color_confidence_gte": 0, "license_plate_country": [ "A" ], "license_plate_region": [ "A" ], "special_vehicle_type": [ "A" ], "weight_type": [ "A" ], "weight_type_confidence_lte": 0, "weight_type_confidence_gte": 0, "orientation": [ "A" ], "orientation_confidence_lte": 0, "orientation_confidence_gte": 0 }, "human_episodes": { "allowed_types": [ "episode_event" ], "matched_lists": [ -1 ], "cameras": [ 1 ], "camera_groups": [ -1 ], "events_count_gte": 0, "events_count_lte": 1, "face_matched": false, "body_matched": false }, "car_episodes": { "allowed_types": [ "episode_event" ], "matched_lists": [ -1 ], "cameras": [ 1 ], "camera_groups": [ -1 ], "events_count_gte": 0, "events_count_lte": 1, "car_matched": false }, "counters": { "counter": [ 0 ], "cameras": [ 0 ], "camera_groups": [ -1 ], "faces_count_gte": 1, "faces_count_lte": 0, "silhouettes_count_gte": 1, "silhouettes_count_lte": 0, "cars_count_gte": 1, "cars_count_lte": 0, "proximity_min_lte": 0, "proximity_min_gte": 0, "proximity_avg_lte": 0, "proximity_avg_gte": 0, "proximity_max_lte": 0, "proximity_max_gte": 0 } }
Important
Use only filters which match your search needs. To turn off a filter, remove it from a webhook. Do not leave a filter empty (
[]
) as in this case, the result of filtration will be empty as well.Note
To get all notifications, pass only curly braces without any enclosed filters:
{}
Tip
Example #1. Get notifications about all vehicle events:
{ "car_events": {} }
Example #2. Get notifications of the opening of matched episodes that feature human faces and bodies:
{ "human_episodes": { "allowed_types": ["episode_open"], "face_matched": true, "body_matched": true }}
Note
You can specify several values for filters with square braces. In this case, the webhook will be triggered once one of the values from this filter has been matched. In the example below, you will get a body event from the camera group
1
or3
if a matched record is12
or25
.{ "body_events": { "camera_groups": [1, 3], "matched_card": [12, 25] } }
Select Active.
Click Save.
Webhook in Action
Try out a webhook by capturing event notifications with a simple web server in Python:
from pprint import pprint
from aiohttp import web
async def handle(request):
pprint(await request.json())
return web.Response(status=200)
app = web.Application()
# for aiohttp v 3.x
# app.add_routes([web.post('/', handle)])
# for aiohttp v 2.x
app.router.add_post('/', handle)
web.run_app(app, port=8888)
Important
A webhook catcher that you use must return an HTTP 200
response after receiving the webhook request from FindFace Multi, like in the example above.
If no filters are configured for a webhook, this web server will be getting notifications about all events, episodes, and counter records.
To view a webhook pulling status, execute:
sudo journalctl CONTAINER_NAME=findface-multi-findface-multi-legacy-1 -f | grep 'Webhook'
Verbose Webhooks
By default, webhook notifications contain only IDs of such entities as cards, watch lists, cameras, and camera groups. It is possible to get the full content of the mentioned entities by switching webhooks to the verbose mode.
To do so, open the /opt/findface-multi/configs/findface-multi-legacy/findface-multi-legacy.py
configuration file and set 'VERBOSE_WEBHOOKS': True
:
sudo vi /opt/findface-multi/configs/findface-multi-legacy/findface-multi-legacy.py
...
FFSECURITY = {
...
# send serialized cards, card-lists, camera and camera groups in webhooks
'VERBOSE_WEBHOOKS': True,
...
}
...
Be sure to restart FindFace Multi containers after making changes.
cd /opt/findface-multi/
sudo docker-compose restart