.. _object-methods_v2: Object API Methods v2 =================================== .. rubric:: In this section: .. contents:: :local: .. _detect-post_v2: Detect Methods -------------------- Detect Face on the Photo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: POST /v2/detect 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 ``extraction-api`` component, so the ``sf-api`` component formats your initial request and forwards it to ``extraction-api``. .. 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, emotions, and country, while the new API provides recognition of gender, age, emotions, country, beard, and glasses. Each face feature (gender, age, emotions, country, 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 ``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 ``extraction-api`` response will be saved in ``memcached`` under a temporary UUID. You can find this UUID in the ``id`` field of the response. * ``"countries47:``: boolean, enables country recognition (old API). * ``"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 ``sf-api`` configuration file. * ``"attribute"``: array of strings in the format ``["gender", "age", "emotions", "countries47", "beard", "glasses3"]``, enables recognition of the face features passed in the array (new API). * ``roi``: string, a region of interest in the image, takes an array of integers in the format roi=top,left,right,bottom, (e.g. {"left": 0, "right": 1000, "top": 0, "bottom": 1000}). .. tip:: To enable a boolean parameter (``gender``, ``age``, etc.), use any of the following strings: ``1``, ``yes``, ``true``, or ``on``, in any letter case. .. 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 you form a request, 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; * countries (if ``countries47`` enabled): probable countries of origin with algorithm confidence in the result; * attributes (if passed): gender (``male`` or ``female``), age (number of years), emotions (predominant emotion), probable countries of origin, beard (``beard`` or ``none``), glasses (``sun``, ``eye``, or ``none``), along with algorithm confidence in the result; * orientation. .. rubric:: Example .. rubric:: Request. 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 .. 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 } Get Detection Result from the Cache by ID ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: GET /v2/detect/:id This method retrieves the detection results from the cache by their temporary UUID's (including feature vectors of the detected faces). .. rubric:: Parameters in path segments: * ``:id``: the detection result temporary UUID in the cache. .. 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 ``extraction-api`` Response ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: POST /v2/detect/:id This method creates a detection result out of a ``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 {} Get Normalized Detect by ID ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: GET /v2/detect/:id/normalized This method retrieves normalized detect by ID. .. rubric:: Parameters in path segments: * ``:id``: ID. .. rubric:: Returns: Normalized object images on success. .. rubric:: Example .. rubric:: Request .. code:: curl -i http://127.0.0.1:18411/v2/detect/bg2gu31jisghl6pee09g/normalized .. rubric:: Response: .. code:: HTTP/1.1 200 OK Content-Type: image/png X-Request-Id: SF:mjv3Lyvf Date: Thu, 09 Apr 2020 15:59:48 GMT Transfer-Encoding: chunked Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: " to save to a file. Compare Faces -------------------- .. code:: GET /v2/verify This method compares a pair of faces and returns a probability of their belonging to the same person (a.k.a. similarity, or confidence). .. rubric:: Query string parameters: * ``"face1"``: the first face, either a detection result (in the format ``detection:``), or one from the biometric database (in the format ``face:/`` or ``facen:[model:]`` if ``allow-return-facen:true`` ). * ``"face2"``: the second face, from the same possible sources as the first object. .. rubric:: Returns: Algorithm confidence that the faces match. .. rubric:: Example .. rubric:: Request #1. Compare 2 detection results .. code:: curl -s 'http://172.17.47.19:18411/v2/verify?face1=detection:bd3hv4tt8f66ph0eag1g&face2=detection:bd3hv8dt8f66ph0eag2g' | jq .. rubric:: Response .. code:: { "confidence": 0.92764723 } .. rubric:: Request #2. Compare a detection result and a face from a gallery .. code:: curl -s 'http://172.17.47.19:18411/v2/verify?face1=detection:bd3hv4tt8f66ph0eag1g&face2=face:galleryname/2' | jq .. rubric:: Response .. code:: { "confidence": 0.999996 } Gallery Methods ---------------------- List Database Galleries ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: GET /v2/galleries 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:: curl -i -X GET 'http://127.0.0.1:18411/v2/galleries/' .. rubric:: Response .. code:: HTTP/1.1 200 OK Content-Type: application/json X-Request-Id: SF:BjI7i3GZ Date: Wed, 05 Dec 2018 08:19:55 GMT Content-Length: 125 { "galleries": [ { "faces": 22, "name": "history" }, { "faces": 1, "name": "test" }, { "faces": 0, "name": "hello" } ] } Create Database Gallery ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: POST /v2/galleries/:gallery 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:: curl -i -X POST 'http://127.0.0.1:18411/v2/galleries/hello' .. rubric:: Response .. code:: HTTP/1.1 200 OK Content-Type: application/json X-Request-Id: SF:whPaBcoV Date: Wed, 05 Dec 2018 08:16:20 GMT Content-Length: 2 {} Retrieve Gallery Details ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: GET /v2/galleries/:gallery 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:: DELETE /v2/galleries/:gallery 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:: curl -i -X DELETE 'http://127.0.0.1:18411/v2/galleries/hello' .. rubric:: Response .. code:: HTTP/1.1 200 OK Content-Type: application/json X-Request-Id: SF:oJh9FEtX Date: Wed, 05 Dec 2018 08:15:04 GMT Content-Length: 2 {} Rename the Gallery ^^^^^^^^^^^^^^^^^^^^ .. code:: PATCH /v2/galleries/:gallery This method renames the gallery. .. rubric:: Parameters in path segments: * ``:gallery``: string, the name of the gallery to be renamed. .. rubric:: Parameters in request body: ``new_name``: string, new name of the gallery. .. rubric:: Returns: * Empty JSON dictionary on success. * JSON with a relevant error description on failure (409 if the target name is already occupied). .. rubric:: Example .. rubric:: Request .. code:: curl -i -X PATCH -d '{"new_name": "testgal2"}' -H "Content-Type: application/json" http://127.0.0.1:18411/v2/galleries/testgal1 .. rubric:: Response .. code:: HTTP/1.1 200 OK Content-Type: application/json X-Request-Id: SF:AAwdCxmM Date: Tue, 04 Feb 2020 08:10:15 GMT Content-Length: 2 {} List of Galleries ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: GET /v2/galleries .. rubric:: Returns: * JSON dictionary of list of galleries 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/' .. rubric:: Response .. code:: HTTP/1.1 200 OK Content-Type: application/json X-Request-Id: SF:BjI7i3GZ Date: Wed, 05 Dec 2018 08:19:55 GMT Content-Length: 125 { "galleries": [ { "faces": 22, "name": "history" }, { "faces": 1, "name": "test" }, { "faces": 0, "name": "hello" } ] } Methods with Faces in the Gallery ------------------------------------------- Create a Face to Database ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: POST /v2/galleries/:gallery/faces/:id 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``: identifier of the object serving as a source for the one being created: * ``detection:``– result of the detection. * ``face:/`` – existing face in the gallery. * ``inline-detection`` – detection object attached to the request in the field detection. Available only when ``allow-return-facen`` is enabled. If the detector is not specified normalized, such a face cannot be migrated to a new model. * ``facen:[model:]`` – facen (with or without model) in base64. Available only when ``allow-return-facen`` is enabled. Creates incomplete faces that cannot be migrated between models. * ``meta`` [optional]: dictionary of meta-fields. * ``detection``: detection object similar to the one passed in ``POST /v2/detect/:id.`` .. 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 '@-' <`` 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 ``tntapi`` shards are out of service during face identification, ``sf-api`` returns an error. Enable this Boolean parameter to use available ``tntapi`` shards to obtain face identification results. * ``return_facen``: if ``allow_return_facen`` is enabled in config, return facen for each face in response. .. rubric:: Filters in query string parameters: * ``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`). * ``meta:subset:meta1=val1&meta:subset:meta1=val2&...``: select a face if a meta string ``meta1`` includes all the values ``val1``, ``val2``, ..., etc. (`[]string`). * ``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``. * ``detection:bg2gu31jisghl6pee09g=0.75``: select if object is similar to detection ``bg2gu31jisghl6pee09g`` with confidence not lower than 0.75. * ``face:hello/123=0.78``: select if the object looks like face ``123`` from gallery ``hello`` with a confidences not lower than 0.78. * ``meta:like:meta1=val1%``: ~sql like: any combination of characters and % sign is supported, e.g. 'aa%', '%aa', '%aa%' or even '%aa%bb%'. That is, '%' is treated as 'any number of any characters'. For data type ``array/list`` - if any of the values passed the check. Always properly escape ``%``. * ``meta:ilike:meta1=Val1%``: case-insensitive analogue of ``meta:like`` filter. * ``facen:[model:]=0.78``: select if the object is similar to the passed feature vector with a confidences not lower than 0.81. Available only if ``allow-return-facen`` is enabled. * ``=``: 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 ``POST /v2/detect`` 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" } Get a Normalized Objects Image from the Gallery ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: GET /v2/galleries/:gallery/faces/:id/normalized .. rubric:: Parameters in path segments: * ``:gallery``: string, the gallery's name. * ``:id``: object id in the gallery, uint64. .. rubric:: Returns: Returns Header ``location`` and ``text/plain`` with a link to the normalized photo (storage link from ``normalized-storage`` config). Successful response is available only if ``normalized-storage.enabled`` is enabled in config. .. rubric:: Example .. rubric:: Request .. code:: curl -vvv http://localhost:18411/v2/galleries/face:test/faces/123/normalized .. rubric:: Response .. code:: HTTP/1.1 302 Found Content-Type: text/plain Location: http://127.0.0.1:3333/uploads/ZmFjZTpoZWxsbw==/6c/df/1234_cf7umjq92d3l006ou0rg.png X-Request-Id: SF:Edz0ThbX Date: Tue, 24 Jan 2023 14:37:39 GMT Content-Length: 87 http://127.0.0.1:3333/uploads/ZmFjZTpoZWxsbw==/6c/df/1234_cf7umjq92d3l006ou0rg.png