.. _biometric-methods: Biometric API Methods -------------------------- .. rubric:: In this section: .. contents:: :local: .. _detect-post: Detect Face in Image ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: /detect POST This method detects a face in a provided image and returns coordinates of the rectangle around the face (a.k.a. bbox) and the face orientation. .. note:: Face detection is done by the ``findface-extraction-api`` component, so the ``findface-sf-api`` component formats your initial request and forwards it to ``findface-extraction-api``. .. important:: Be sure to pass the enabled ``facen`` parameter in the ``/detect POST`` query string in order to save the returned result in ``memcached``. To retrieve the returned result from ``memcached``, use the ``/detect GET`` method. .. tip:: To enable a boolean parameter (``gender``, ``age``, etc.), use any of the following strings: ``1``, ``yes``, ``true``, or ``on``, in any letter case. .. important:: To enable recognition of face features, you can use either the new (preferred) or old API parameters (see the query string parameters for details). The old API allows you to recognize gender, age, and emotions, while the new API provides recognition of gender, age, emotions, beard, and glasses. Each face feature (gender, age, emotions, beard, or glasses) must be mentioned only once in a request, either in the new or old API format. .. rubric:: Query string parameters: * ``"detector"``: string, face detector to be applied to the image: ``nnd`` (regular detector) or ``normalized`` (accepts a normalized face image, skipping the face detection stage). * ``"gender"``: Boolean, enables gender recognition (old API). * ``"age"``: Boolean, enables age recognition (old API). * ``"emotions"``: Boolean, enables emotions recognition (old API). * ``"facen"``: Boolean, the formatted request to ``findface-extraction-api`` will include such parameters as ``need_facen`` (extract a face feature vector) and ``need_normalized`` (obtain a normalized face image), while the full ``findface-extraction-api`` response will be saved in ``memcached`` under a temporary UUID. You can find this UUID in the ``id`` field of the response. * ``"autorotate"``: Boolean, auto-rotates an original image to 4 different orientations and returns faces detected in each orientation. * ``"return_facen"``: Boolean, returns a face feature vector in the response. Requires the enabled ``allow-return-facen`` flag in the ``findface-sf-api`` configuration file. * ``"attribute"``: Array of strings in the format ``["gender", "age", "emotions", "beard", "glasses3"]``, enables recognition of the face features passed in the array (new API). .. rubric:: Parameters in request body: Image as a file of the ``image/jpeg``, ``image/png``, or ``image/webp`` MIME-type, or as a ``text/x-url`` link to a relevant public URL. .. rubric:: Returns: * list of coordinates of the rectangles around the detected faces; * temporary UUID of the detection result (``id``, if ``facen`` enabled); .. important:: When writing code, be sure to check the relevance of the temporary UUID before you refer to it as it tends to become irrelevant with time. If so, re-detect the face. * feature vector (if ``return_facen`` enabled); * gender (if ``gender`` enabled): ``male`` or ``female``, with algorithm confidence in the result (``"score"``); * age (if ``age`` enabled): number of years; * emotions (if ``emotions`` enabled): 6 basic emotions + neutral (``angry``, ``disgust``, ``fear``, ``happy``, ``sad``, ``surprise``, ``neutral``) with algorithm confidence in each emotion expression; * attributes (if passed): gender (``male`` or ``female``), age (number of years), emotions (predominant emotion), beard (``beard`` or ``none``), glasses (``sun``, ``eye``, or ``none``), along with algorithm confidence in the result; * orientation. .. rubric:: Examples .. rubric:: Request #1. Old and new API simultaneous usage .. code:: curl -i -X POST 'http://127.0.0.1:18411/v2/detect?facen=on&age=on&gender=on&emotions=on&attribute=glasses3' -H 'Content-Type: image/jpeg' --data-binary @sample.jpg HTTP/1.1 100 Continue .. rubric:: Response .. code:: HTTP/1.1 200 OK Content-Type: application/json X-Request-Id: SF:BpLnfgDs Date: Thu, 23 May 2019 12:00:22 GMT Content-Length: 713 { "faces": [ { "id": "bjj8mlhjisgjrk6hj1v0", "bbox": { "left": 595, "top": 127, "right": 812, "bottom": 344 }, "features": { "gender": { "gender": "FEMALE", "score": 0.9998938 }, "age": 25, "score": -0.000696103, "emotions": [ { "emotion": "neutral", "score": 0.99958 }, { "emotion": "sad", "score": 0.0004020365 }, { "emotion": "happy", "score": 8.603454e-06 }, { "emotion": "surprise", "score": 8.076766e-06 }, { "emotion": "disgust", "score": 6.6535216e-07 }, { "emotion": "angry", "score": 6.1434775e-07 }, { "emotion": "fear", "score": 7.3372125e-10 } ], "attributes": { "glasses3": { "attribute": "glasses3", "model": "glasses3.v0", "result": [ { "confidence": 0.99958307, "name": "none" }, { "confidence": 0.00033243417, "name": "eye" }, { "confidence": 8.4465064e-05, "name": "sun" } ] } } } } ], "orientation": 1 } .. rubric:: Request #2. New API usage .. code:: curl -s -X POST 'http://master:18411/v2/detect?attribute=gender' -H 'Content-Type: image/jpeg' --data-binary @pasha.jpg | jq { "faces": [ { "bbox": { "left": 1019, "top": 1138, "right": 1666, "bottom": 2041 }, "features": { "score": -0.00035252835, "attributes": { "gender": { "extractor": "gender", "model": "gender.v2", "result": [ { "confidence": 0.9999999, "name": "male" }, { "confidence": 7.935678e-08, "name": "female" } ] }, "quality": { "extractor": "quality", "model": "quality.v0", "result": 0.00035252835 } } } } ], "orientation": 1 } Retrieve Detection Result from ``memcached`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: /detect/:id GET This method retrieves the detection results from ``memcached`` by their temporary UUID's (including feature vectors of the detected faces). .. rubric:: Parameters in path segments: * ``:id``: the detection result temporary UUID in ``memcached``. .. rubric:: Returns: JSON representation of the detection result. .. rubric:: Example .. rubric:: Request .. code:: curl -i -X GET 'http://127.0.0.1:18411/v2/detect/bg2gu31jisghl6pee09g' .. rubric:: Response: .. code:: { "bbox": { "bottom": 343, "left": 593, "right": 824, "top": 112 }, "features": { "age": 26.096783, "emotions": [ { "emotion": "neutral", "score": 0.9094986 }, { "emotion": "happy", "score": 0.11464329 }, { "emotion": "sad", "score": 0.005675929 }, { "emotion": "surprise", "score": -0.02556022 }, { "emotion": "fear", "score": -0.14499822 }, { "emotion": "angry", "score": -0.19491306 }, { "emotion": "disgust", "score": -0.31617728 } ], "gender": { "gender": "FEMALE", "score": -2.7309942 }, "score": -0.000696103 }, "id": "bg2gu31jisghl6pee09g" } Create Detection Result out of ``findface-extraction-api`` Response ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: /detect/:id POST This method creates a detection result out of a ``findface-extraction-api`` response. .. rubric:: Parameters in path segments: * ``:id``: specify UUID under which the newly created detection result will be stored in cache. .. rubric:: Returns: Empty JSON on success. .. rubric:: Example .. rubric:: Request .. code:: $ curl -i -X POST 'http://127.0.0.1:18411/v2/detect/bg2gu31jisghl6peea9g' -H 'Content-Type: application/json' --data-binary '@extapi-face.json' .. rubric:: Response: .. code:: HTTP/1.1 200 OK Content-Type: application/json X-Request-Id: jFSBuSPm Date: Wed, 05 Dec 2018 08:08:56 GMT Content-Length: 2 {} List Database Galleries ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: /galleries GET This method returns the list of all galleries in the biometric database. .. rubric:: Parameters: The method doesn't accept any parameters. .. rubric:: Returns: JSON dictionary with the list of gallery names. .. rubric:: Example .. rubric:: Request .. code:: GET /v2/galleries HTTP/1.1 Host: 172.17.47.19:18411 .. rubric:: Response .. code:: HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Fri, 02 Feb 2018 10:11:43 GMT Content-Length: 35   {"galleries":[{"name":"sandbox"}]} Create Database Gallery ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: /galleries/:gallery POST This method creates a gallery under a given name. .. rubric:: Parameters in path segments: ``:gallery``: a new gallery's name. It can contain English letters, numbers, underscore and minus sign (``[a-zA-Z0-9_-]+``) and must be no longer than 48 characters. .. rubric:: Returns: * Empty JSON on success. * JSON with a relevant error description on failure. .. rubric:: Example .. rubric:: Request .. code:: POST /v2/galleries/newone HTTP/1.1 Host: 172.17.47.19:18411 .. rubric:: Response .. code:: HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Fri, 02 Feb 2018 10:18:01 GMT Content-Length: 2   {} Retrieve Gallery Details ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: /galleries/:gallery GET This method checks a gallery existence and retrieves the number of faces in it. .. rubric:: Parameters in path segments: ``:gallery``: a gallery's name. .. rubric:: Returns: * JSON dictionary with the number of faces and gallery name on success. * JSON with a relevant error description on failure. .. rubric:: Example .. rubric:: Request .. code:: curl -i -X GET 'http://127.0.0.1:18411/v2/galleries/hello' .. rubric:: Response .. code:: HTTP/1.1 200 OK Content-Type: application/json X-Request-Id: Ard3exjn Date: Wed, 05 Dec 2018 08:17:54 GMT Content-Length: 29 { "faces": 123, "name": "hello" } Delete Gallery ^^^^^^^^^^^^^^^^^^^^ .. code:: /galleries/:gallery DELETE This method deletes a given gallery with all the faces. .. rubric:: Parameters in path segments: ``:gallery``: the name of the gallery to be deleted. .. rubric:: Returns: * Empty JSON on success. * JSON with a relevant error description on failure. .. rubric:: Example .. rubric:: Request .. code:: DELETE /v2/galleries/newone HTTP/1.1 Host: 172.17.47.19:18411 .. rubric:: Response .. code:: HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Fri, 02 Feb 2018 10:18:01 GMT Content-Length: 2   {} Add Face to Database ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: /galleries/:gallery/faces/:id POST This method takes a detected face from ``memcached`` or a face from a gallery. It then adds the face with its feature vector to a given gallery under a custom id. The custom id and destination gallery are to be specified in the path segments. Along with the face, you can also add metadata which uniquely describes the person, for example, the person's name. .. rubric:: Parameters in path segments: * ``:gallery``: the name of the gallery to add the face in. * ``:id``: permanent face id in the gallery, uint64. .. rubric:: Parameters in request body: * ``"from"``: temporary UUID of the detected face in ``memcached`` (``"from": "detection:"``) or face id in a gallery (``"from: "face:/"``). * ``"meta"`` [optional]: the person's metadata such as the person's name, original image details, detection date and time, etc., dictionary. .. rubric:: Returns: * JSON representation of the added face on success. * Error on failure. .. rubric:: Example .. rubric:: Request .. code:: curl -i -X POST http://127.0.0.1:18411/v2/galleries/hello/faces/123/ -H 'Content-Type: application/json' --data-binary '@-' <``: cursor of the next page with search results. The ```` value is returned in the response in the ``next_page`` parameter along with the previous page results (see details below). * ``?ignore_errors``: By default, if one or several ``findface-tarantool-server`` shards are out of service during face identification, ``findface-sf-api`` returns an error. Enable this Boolean parameter to use available ``findface-tarantool-server`` shards to obtain face identification results. * ``?meta:in:meta1=val1&meta:in:meta1=val2&...``: select a face if a meta string ``meta1`` is equal to one of the values ``val1``/``val2``/ ..., etc. (`uint64`, `string`). * ``?meta:gte:meta1=val1``: select all faces with a meta string ``meta1`` greater or equal to ``val1`` (`uint64`). * ``?meta:lte:meta1=val1``: select all faces with a meta string ``meta1`` less or equal to ``val1`` (`uint64`). * ``?id:in=value_id``: select all faces with ``id`` equal to ``value_id``. * ``?id:gte=value_id``: select all faces with ``id`` greater or equal to ``value_id``. * ``?id:lte=value_id``: select all faces with id less or equal to ``value_id``. * ``?meta:subset:meta1=val1&meta:subset:meta1=val2&...``: select a face if a meta string ``meta1`` includes all the values ``val1``, ``val2``, ..., etc. (`[]string`).  * ``?=``: specifies a feature vector to search for in the biometric database, via the ```` parameter, as well as the threshold similarity in the search results as ````. The ```` parameter can be either a face ID in a database gallery (specify ```` as ``face:/``), or the temporary UUID of a detection result stored in ``memcached`` (``detection:``) (see the ``/detect POST`` method and examples below). The ranges from 0 to 1. .. rubric:: Returns: JSON representation of an array with found faces. By default, faces in the response are sorted by id. Should you specify a feature vector to search for, faces will be sorted in decreasing order by similarity. The response format is the following: .. code:: { "faces": [ { ... face 1 data ... "confidence": 0.123 // if you search for a feature vector }, { ... face 2 data ... "confidence": 0.123 // if you search for a feature vector }, ... ], "next_page": "vgszk2bkexbl" // next page cursor } The ``next_page`` parameter is a URL-safe string that you will have to pass in the ``?page=`` in the next request in order to get the next page of results. Pagination is available only if the filtration by feature vector is disabled. .. rubric:: Request #1. Face identification (search a gallery for a face) .. code:: curl -s 'http://172.17.47.19:18411/v2/galleries/galleryname/faces?detection:bd3hv4tt8f66ph0eag1g=0.5&limit=1' | jq .. rubric:: Response .. code:: { "faces": [ { "id": { "gallery": "galleryname", "face": 2 }, "features": { "gender": { "gender": "FEMALE", "score": -2.6415923 }, "age": 26.04833, "score": 0.9999999, "emotions": [ { "emotion": "neutral", "score": 0.99958 }, { "emotion": "sad", "score": 0.0004020398 }, { "emotion": "happy", "score": 8.603504e-06 }, { "emotion": "surprise", "score": 8.076798e-06 }, { "emotion": "disgust", "score": 6.653509e-07 }, { "emotion": "angry", "score": 6.14346e-07 }, { "emotion": "fear", "score": 7.33713e-10 } ] }, "meta": {}, "normalized_id": "2_bd323f5t8f66ph0eafp0.png", "confidence": 0.9999 } ], "next_page": "There are more than 1 results, but pagination is not supported when filtering by FaceN" } .. rubric:: Request #2. List faces in gallery .. code:: curl -s 'http://172.17.47.19:18411/v2/galleries/galleryname/faces?limit=2' | jq .. rubric:: Response .. code:: { "faces": [ { "id": { "gallery": "galleryname", "face": 1 }, "features": { "gender": { "gender": "FEMALE", "score": -2.6415923 }, "age": 26.04833, "score": 0.9999999, "emotions": [ { "emotion": "neutral", "score": 0.99958 }, { "emotion": "sad", "score": 0.0004020398 }, { "emotion": "happy", "score": 8.603504e-06 }, { "emotion": "surprise", "score": 8.076798e-06 }, { "emotion": "disgust", "score": 6.653509e-07 }, { "emotion": "angry", "score": 6.14346e-07 }, { "emotion": "fear", "score": 7.33713e-10 } ] }, "meta": {}, "normalized_id": "1_bd321tlt8f66ph0eaflg.png" }, { "id": { "gallery": "galleryname", "face": 2 }, "features": { "gender": { "gender": "FEMALE", "score": -2.6415923 }, "age": 26.04833, "score": 0.9999999, "emotions": [ { "emotion": "neutral", "score": 0.99958 }, { "emotion": "sad", "score": 0.0004020398 }, { "emotion": "happy", "score": 8.603504e-06 }, { "emotion": "surprise", "score": 8.076798e-06 }, { "emotion": "disgust", "score": 6.653509e-07 }, { "emotion": "angry", "score": 6.14346e-07 }, { "emotion": "fear", "score": 7.33713e-10 } ] }, "meta": {}, "normalized_id": "2_bd323f5t8f66ph0eafp0.png" } ], "next_page": "3" } .. rubric:: Request #3. Advanced face identification .. code:: curl -i -X GET http://127.0.0.1:18411/v2/galleries/history/faces/?limit=5&meta:in:camera=openspace&meta:in:camera=entrance&meta:lte:timestamp=1543845934&meta:gte:timestamp=1514801655&detection:bg2gu31jisghl6pee09g=0.4 | jq .. rubric:: Response .. code:: HTTP/1.1 200 OK Content-Type: application/json X-Request-Id: SF:ibKVYpcb Date: Wed, 05 Dec 2018 08:37:33 GMT Transfer-Encoding: chunked { "faces": [ { "confidence": 0.6026, "features": { "score": 1 }, "id": { "face": 4141715030051545133, "gallery": "history" }, "meta": { "bbox": "[607, 802, 738, 933]", "camera": "openspace", "is_friend": 0, "labels": [], "score": 9999999999998079040, "timestamp": 1542909082 }, "normalized_id": "4141715030051545133_bfrep71jisghl6pedvk0.png" }, { "confidence": 0.5325, "features": { "score": 1 }, "id": { "face": 4141715086422990894, "gallery": "history" }, "meta": { "bbox": "[741, 905, 953, 1117]", "camera": "openspace", "is_friend": 0, "labels": [], "score": 9999999999993877300, "timestamp": 1542909103 }, "normalized_id": "4141715086422990894_bfrepc9jisghl6pedvl0.png" }, { "confidence": 0.531, "features": { "age": 41.2622, "gender": { "gender": "FEMALE", "score": -0.880698 }, "score": 1 }, "id": { "face": 4141716493024780347, "gallery": "history" }, "meta": { "bbox": "[90, 869, 166, 945]", "camera": "openspace", "is_friend": 0, "labels": [], "score": 10000000000000000013, "timestamp": 1542909627 }, "normalized_id": "4141716493024780347_bfretf9jisghl6pee020.png" }, { "confidence": 0.5236, "features": { "age": 48.949913, "gender": { "gender": "FEMALE", "score": -0.7653318 }, "score": 1 }, "id": { "face": 4141716498393489468, "gallery": "history" }, "meta": { "bbox": "[56, 853, 125, 923]", "camera": "openspace", "is_friend": 0, "labels": [], "score": 9999999999999999053, "timestamp": 1542909629 }, "normalized_id": "4141716498393489468_bfretg1jisghl6pee030.png" }, { "confidence": 0.5212, "features": { "age": 33.3112, "gender": { "gender": "MALE", "score": 1.9504981 }, "score": 1 }, "id": { "face": 4141715338752319538, "gallery": "history" }, "meta": { "bbox": "[-36, 862, 60, 958]", "camera": "openspace", "is_friend": 0, "labels": [], "score": 9999999999999999425, "timestamp": 1542909197 }, "normalized_id": "4141715338752319538_bfreq4pjisghl6pedvp0.png" } ], "next_page": "There are more than 5 results, but pagination is not supported when filtering by FaceN" }