Contact
https://verifeye-docs.realeyes.ai/contact/
# Contact Us
Get in touch with our team for support, sales inquiries, or questions.
**Email**: [verifeye@realeyes.ai](https://verifeye-docs.realeyes.ai/mailto:verifeye@realeyes.ai)
[!button variant="contrast" text="Email"](https://verifeye-docs.realeyes.ai/mailto:verifeye@realeyes.ai)
Index
https://verifeye-docs.realeyes.ai/
Index
https://verifeye-docs.realeyes.ai/introduction/
# Welcome to VerifEye
VerifEye verifies that a real, unique human is on the other end of a session — from a selfie, in about three seconds, without collecting government IDs and without storing personally identifiable information. Proven at 1B+ verifications per day (11k+ per second).
One lightweight capture answers four questions at once: is this a live human, are they unique across your accounts, what is their age range, and is it still the same person controlling the account over time.
---
## Get started in 5 minutes
1. Sign up at the [Developer Console](https://verifeye-console.realeyes.ai/)
2. Generate your API key
3. Drop our Redirect URL into your flow — no SDK install, no backend work
[Create an account →](https://verifeye-console.realeyes.ai/)
---
## Choose your integration path
Most teams start with **Redirect** to validate the use case, then evolve to Cloud API or on-prem SDK as their needs mature. Each tier has a different architecture — particularly around who manages the biometric collection — so the right choice depends on your control, compliance, and volume requirements.
### Tier 1 · Redirect — *Start here*
**Turn-key hosted flow.** Point your users at a VerifEye URL and we guide them through a browser-based camera experience, running the verifiers you've configured (liveness, face recognition, age and gender). Supports full-page redirect, embedded iframe, and popup integration patterns. We handle consent capture, biometric capture, data storage, and backend processing — you handle your privacy policy. Ships with API signatures and webhooks for production hardening.
*Best for: initial validation, pilots, lowest engineering lift*
[Redirect quickstart →](https://verifeye-docs.realeyes.ai/redirect/)
### Tier 2 · Cloud API & SDKs
**Full flexibility, your UX.** Call our REST API directly or embed our mobile and web SDKs. You own the user experience; we run the models in our cloud and manage the biometric collection on your behalf.
*Best for: native apps, custom UX, server-to-server integrations*
[REST API reference →](https://verifeye-docs.realeyes.ai/rest-api/)
### Tier 3 · Private SDKs
**On-prem, edge, or private cloud.** Run the same models inside your own data center, private cloud, or at the edge. You manage the biometric collection entirely within your environment. Best unit economics at volume, full data residency control, and no external network dependency. C++ libraries for Windows, Linux, macOS, iOS, and Android.
*Best for: regulated industries, high-volume deployments, sovereign data requirements*
[Native SDKs →](https://verifeye-docs.realeyes.ai/native-sdk/)
> **On the roadmap:** client-side models running fully in-browser and on-device for the lowest possible latency and zero server round-trip.
---
## What VerifEye can do
A single selfie capture drives multiple capabilities. Choose what you need for your use case — you can enable more over time from the same integration.
| Capability | What it answers |
|---|---|
| **Liveness detection** | Is this a real, present human — not a photo, mask, deepfake, or injected video feed? |
| **Uniqueness (1:N)** | Has this person already created another account in your system? |
| **Re-verification (1:1)** | Is this the same person who originally set up the account? Use at login, high-risk actions, or account recovery. |
| **Age & demographics** | Is the user within a required age range? What demographic signals exist for fraud analytics? |
| **Continuity of control** | Silent, continuous re-verification to detect when account control has transferred to someone else. |
| **Account recovery** | Restore access when a user has lost their device, password, or passkey — using their face as the durable credential. |
---
## AI-friendly documentation
Use AI coding assistants to accelerate your VerifEye integration. Copy and paste this prompt into Claude Code, Cursor, or your preferred AI assistant:
```
Please read the VerifEye documentation from https://verifeye-docs.realeyes.ai/llms.txt and help me integrate face verification into my application.
```
[View the AI context file](https://verifeye-docs.realeyes.ai/llms.txt)
---
## Support
Need help getting started? [Contact us](https://verifeye-docs.realeyes.ai/contact/).
---
*Last updated: 2026-05-04*
Api C
https://verifeye-docs.realeyes.ai/native-sdk/demographic-estimation/api-c/
# C API Documentation
## Structs
### DELPoint2d
Point2d class for landmarks
```c
typedef struct DELPoint2d {
float x;
float y;
} DELPoint2d;
```
**Members:**
- `float x` - x coordinate of the point
- `float y` - y coordinate of the point
### DELPoint2dArray
Array of Point2d
```c
typedef struct DELPoint2dArray {
int count;
DELPoint2d* points;
} DELPoint2dArray;
```
**Members:**
- `int count` - number of points
- `DELPoint2d* points` - pointer to the array of points
### DELBoundingBox
Bounding Box class for the faces
```c
typedef struct DELBoundingBox {
int x;
int y;
int width;
int height;
} DELBoundingBox;
```
**Members:**
- `int x` - x coordinate of the top-left corner
- `int y` - y coordinate of the top-left corner
- `int width` - width of the bounding box in pixels
- `int height` - height of the bounding box in pixels
### DELImageHeader
Descriptor class for image data (non-owning)
```c
typedef struct DELImageHeader {
const uint8_t* data;
int width;
int height;
int stride;
DELImageFormat format;
} DELImageHeader;
```
**Members:**
- `const uint8_t* data` - pointer to the byte array of the image
- `int width` - width of the image in pixels
- `int height` - height of the image in pixels
- `int stride` - length of one row of pixels in bytes (e.g: 3*width + padding)
- `DELImageFormat format` - image format
### DELOutput
Output struct for various estimated outputs
```c
typedef struct DELOutput {
DELOutputType type;
union {
DELGender gender;
float float_value;
};
const char* name;
} DELOutput;
```
**Members:**
- `DELOutputType type` - type of the output
- `DELGender gender` - gender value (when type is DELOutputTypeGender)
- `float float_value` - float value (when type is DELOutputTypeAge or DELOutputTypeAgeUncertainty)
- `const char* name` - name of the output (valid only during callback)
### DELOutputArray
Array of Outputs
```c
typedef struct DELOutputArray {
int count;
DELOutput* outputs;
} DELOutputArray;
```
**Members:**
- `int count` - number of outputs
- `DELOutput* outputs` - pointer to the array of outputs
### DELVersion
Semantic version number for the SDK
```c
typedef struct DELVersion {
int major;
int minor;
int patch;
} DELVersion;
```
### DELFaceArray
Array of Faces
```c
typedef struct DELFaceArray {
int count;
DELFace** faces;
} DELFaceArray;
```
**Members:**
- `int count` - number of faces
- `DELFace** faces` - pointer to the array of face pointers
## Enums
### DELImageFormat
Image format enum
**Values:**
- `DELImageFormatGrayscale = 0` - 8-bit grayscale
- `DELImageFormatRGB = 1` - 24-bit RGB
- `DELImageFormatRGBA = 2` - 32-bit RGBA or 32-bit RGB_
- `DELImageFormatBGR = 3` - 24-bit BGR
- `DELImageFormatBGRA = 4` - 32-bit BGRA or 32-bit BGR_
### DELOutputType
Type of the output in Output struct
**Values:**
- `DELOutputTypeAge = 0` - Age estimation
- `DELOutputTypeGender = 1` - Gender classification
- `DELOutputTypeAgeUncertainty = 2` - Age uncertainty estimation
### DELGender
Gender enum
**Values:**
- `DELGenderFemale = 0` - Female
- `DELGenderMale = 1` - Male
## Callbacks
### DELDetectFacesCallback
```c
typedef void (*DELDetectFacesCallback)(void* user_data, DELFaceArray* faces, const char* error_msg);
```
Callback for face detection
**Parameters:**
- `user_data` - user data passed to the function
- `faces` - array of detected faces. The array and its contents are owned by the library and are valid only during the callback.
- `error_msg` - error message if any, otherwise NULL
### DELEstimateCallback
```c
typedef void (*DELEstimateCallback)(void* user_data, DELOutputArray* outputs, const char* error_msg);
```
Callback for demographic estimation
**Parameters:**
- `user_data` - user data passed to the function
- `outputs` - array of estimation outputs. The array and its contents are owned by the library and are valid only during the callback.
- `error_msg` - error message if any, otherwise NULL
## DemographicEstimator Functions
### del_demographic_estimator_new
```c
DELDemographicEstimator* del_demographic_estimator_new(const char* model_file,
int max_concurrency,
char** errorMessage);
```
Constructor: loads model file, sets up the processing.
**Parameters:**
- `model_file` - path for the used model
- `max_concurrency` - maximum allowed concurrency, 0 means automatic (using all cores), default: 0
- `errorMessage` - pointer to a char* that will be set to an error message string on failure, or NULL on success. The caller is responsible for freeing the string using free(). If errorMessage is a NULL pointer, no error message will be returned.
**Returns:** pointer to the new DemographicEstimator instance, or NULL on failure
### del_demographic_estimator_free
```c
void del_demographic_estimator_free(DELDemographicEstimator* estimator);
```
Destructor
**Parameters:**
- `estimator` - pointer to the DemographicEstimator instance to free
### del_demographic_estimator_detect_faces
```c
void del_demographic_estimator_detect_faces(DELDemographicEstimator* estimator,
const DELImageHeader* image_header,
DELDetectFacesCallback callback,
void* user_data);
```
Detects the faces on an image with a callback API.
**Note:** The given ImageHeader doesn't own the image data, and it is safe to delete the data after the call, a copy is happening internally. See DELImageHeader for details.
**Note:** Calling this function is non-blocking, so calling it again with the next frame without waiting for the result is possible. Also see del_demographic_estimator_get_concurrent_calculations().
**Parameters:**
- `estimator` - pointer to the DemographicEstimator instance
- `image_header` - image descriptor
- `callback` - callback to call with the result
- `user_data` - user data to pass to the callback
### del_demographic_estimator_estimate
```c
void del_demographic_estimator_estimate(DELDemographicEstimator* estimator,
const DELFace* face,
DELEstimateCallback callback,
void* user_data);
```
Returns the demographic estimation of the detected face.
**Note:** Calling this function is non-blocking, so calling it again with the next frame without waiting for the result is possible. Also see del_demographic_estimator_get_concurrent_calculations().
**Parameters:**
- `estimator` - pointer to the DemographicEstimator instance
- `face` - the previously detected face to estimate
- `callback` - callback to call with the result
- `user_data` - user data to pass to the callback
### del_demographic_estimator_get_concurrent_calculations
```c
int del_demographic_estimator_get_concurrent_calculations(const DELDemographicEstimator* estimator);
```
Returns the value of the atomic counter for the number of calculations currently running concurrently. You can use this to limit the number of concurrent calculations.
**Parameters:**
- `estimator` - pointer to the DemographicEstimator instance
**Returns:** The (approximate) number of calculations currently in-flight.
### del_demographic_estimator_get_model_name
```c
char* del_demographic_estimator_get_model_name(const DELDemographicEstimator* estimator);
```
Returns the name (version etc) of the loaded model.
**Parameters:**
- `estimator` - pointer to the DemographicEstimator instance
**Returns:** name of the model. The caller is responsible for freeing the returned string using free().
### del_demographic_estimator_get_sdk_version
```c
DELVersion del_demographic_estimator_get_sdk_version();
```
Returns the version of the SDK (and not the model)
**Returns:** version of the SDK
### del_demographic_estimator_get_sdk_version_string
```c
char* del_demographic_estimator_get_sdk_version_string();
```
Returns the version string of the SDK (and not the model)
**Returns:** version string of the SDK. The caller is responsible for freeing the returned string using free().
## Face Functions
### del_face_new
```c
DELFace* del_face_new(const DELImageHeader* image_header,
const DELPoint2d* landmarks,
int num_landmarks,
const DELBoundingBox* bbox,
float confidence,
char** errorMessage);
```
Constructor for the Face object to support 3rd party face detectors
**Parameters:**
- `image_header` - image descriptor
- `landmarks` - face landmarks
- `num_landmarks` - number of landmarks
- `bbox` - face bounding box
- `confidence` - face detection confidence
- `errorMessage` - pointer to a char* that will be set to an error message string on failure, or NULL on success. The caller is responsible for freeing the string using free(). If errorMessage is a NULL pointer, no error message will be returned.
**Returns:** pointer to the new Face instance, or NULL on failure
### del_face_copy
```c
DELFace* del_face_copy(const DELFace* other);
```
Copy constructor
**Parameters:**
- `other` - pointer to the Face instance to copy
**Returns:** pointer to the new Face instance, or NULL on failure
### del_face_free
```c
void del_face_free(DELFace* face);
```
Destructor
**Parameters:**
- `face` - pointer to the Face instance to free
### del_face_bounding_box
```c
DELBoundingBox del_face_bounding_box(const DELFace* face);
```
Returns the bounding box of the detected face
**Parameters:**
- `face` - pointer to the Face instance
**Returns:** DELBoundingBox
### del_face_confidence
```c
float del_face_confidence(const DELFace* face);
```
Returns the confidence value of the detected face
**Parameters:**
- `face` - pointer to the Face instance
**Returns:** float
### del_face_landmarks
```c
DELPoint2dArray* del_face_landmarks(const DELFace* face);
```
Returns the landmarks of the face
**Parameters:**
- `face` - pointer to the Face instance
**Returns:** pointer to DELPoint2dArray. The caller is responsible for freeing the returned array using free().
Api Cpp
https://verifeye-docs.realeyes.ai/native-sdk/demographic-estimation/api-cpp/
# C++ API Documentation
## Estimator class
### class del::DemographicEstimator
The Demographic Estimator class
#### Constructors
```cpp
DemographicEstimator(const std::string& modelFile, int maxConcurrency = 0)
```
Constructor: loads model file, sets up the processing.
**Parameters:**
- `modelFile` - path for the used model
- `maxConcurrency` - maximum allowed concurrency, 0 means automatic (using all cores), default: 0
```cpp
~DemographicEstimator()
```
Destructor
#### Methods
```cpp
std::future> detectFaces(const del::ImageHeader& imageHeader)
```
Detects the faces on an image with the std::future API.
**Note:** The given ImageHeader doesn't own the image data, and it is safe to delete the data after the call, a copy is happening internally. See del::ImageHeader for details.
**Note:** Calling this function is non-blocking, so calling it again with the next image without waiting for the result is possible. Also see getConcurrentCalculations().
**Note:** This is the std::future based API, for callback API see `del::DemographicEstimator::detectFaces(const del::ImageHeader&, std::function>)>)`.
**Parameters:**
- `imageHeader` - image descriptor
---
```cpp
void detectFaces(const del::ImageHeader& imageHeader,
std::function>)> callback)
```
Detects the faces on an image with a callback API.
**Note:** The given ImageHeader doesn't own the image data, and it is safe to delete the data after the call, a copy is happening internally. See del::ImageHeader for details.
**Note:** Calling this function is non-blocking, so calling it again with the next frame without waiting for the result is possible. Also see getConcurrentCalculations().
**Note:** This is the callback based API, for std::future API see `del::DemographicEstimator::detectFaces(const del::ImageHeader&)`.
**Parameters:**
- `imageHeader` - image descriptor
- `callback` - callback to call with the result
**Returns:** tracked landmarks and emotions
---
```cpp
std::future> estimate(const del::Face& face)
```
Returns the demographic estimation of the detected face.
**Note:** Calling this function is non-blocking, so calling it again with the next frame without waiting for the result is possible. Also see getConcurrentCalculations().
**Note:** This is the std::future based API, for callback API see `del::DemographicEstimator::estimate(const del::Face&, std::function>)>)`.
**Parameters:**
- `face` - the previously detected face to embed
**Returns:** estimations
---
```cpp
void estimate(const del::Face& face,
std::function>)> callback)
```
Returns the demographic estimation of the detected face.
**Note:** Calling this function is non-blocking, so calling it again with the next frame without waiting for the result is possible. Also see getConcurrentCalculations().
**Note:** This is the callback based API, for std::future API see `del::DemographicEstimator::estimate(const del::Face&)`.
**Parameters:**
- `face` - the previously detected face to embed
- `callback` - callback to call with the result
---
```cpp
int getConcurrentCalculations() const
```
Returns the value of the atomic counter for the number of calculations currently running concurrently. You can use this to limit the number of concurrent calculations.
**Returns:** The (approximate) number of calculations currently in-flight.
---
```cpp
std::string getModelName() const
```
Returns the name (version etc) of the loaded model.
**Returns:** name of the model
---
```cpp
static del::Version getSDKVersion()
```
Returns the version of the SDK (and not the model)
**Returns:** version of the SDK
---
```cpp
static std::string getSDKVersionString()
```
Returns the version string of the SDK (and not the model)
**Returns:** version string of the SDK
## Image header class
### struct del::ImageHeader
Descriptor class for image data (non-owning)
**Members:**
- `const uint8_t* data` - pointer to the byte array of the image
- `int width` - width of the image in pixels
- `int height` - height of the image in pixels
- `int stride` - length of one row of pixels in bytes (e.g: 3*width + padding)
- `del::ImageFormat format` - image format
### enum class del::ImageFormat
**Values:**
- `Grayscale = 0` - 8-bit grayscale
- `RGB = 1` - 24-bit RGB
- `RGBA = 2` - 32-bit RGBA or 32-bit RGB_
- `BGR = 3` - 24-bit BGR
- `BGRA = 4` - 32-bit BGRA or 32-bit BGR_
## Result classes
### Face
See also: [landmarks specification](https://verifeye-docs.realeyes.ai/overview.md#target-to-face-specs).
#### class del::Face
Face Class
##### Constructors
```cpp
Face(const del::ImageHeader& imageHeader,
const std::vector& landmarks,
const del::BoundingBox& bbox = del::BoundingBox(),
float confidence = 0.0f)
```
Constructor for the Face object to support 3rd party face detectors
**Parameters:**
- `imageHeader` - image descriptor
- `landmarks` - face landmarks
- `bbox` - face bounding box
- `confidence` - face detection confidence
```cpp
~Face()
```
Destructor
##### Methods
```cpp
BoundingBox boundingBox() const
```
Returns the bounding box of the detected face
**Returns:** BoundingBox
---
```cpp
float confidence() const
```
Returns the confidence value of the detected face
**Returns:** float
---
```cpp
std::vector landmarks() const
```
Returns the landmarks of the face
**Returns:** std::vector
### Point2d
#### struct del::Point2d
Point2d class for landmarks
**Members:**
- `float x` - x coordinate of the point
- `float y` - y coordinate of the point
### BoundingBox
#### struct del::BoundingBox
Bounding Box class for the faces
**Members:**
- `int x` - x coordinate of the top-left corner
- `int y` - y coordinate of the top-left corner
- `int width` - width of the bounding box in pixels
- `int height` - height of the bounding box in pixels
### OutputType
#### enum class del::OutputType
Type of the output in Output struct.
**Values:**
- `AGE = 0`
- `GENDER = 1`
- `AGE_UNCERTAINTY = 2`
### Gender
#### enum class del::Gender
Gender enum.
**Values:**
- `FEMALE = 0`
- `MALE = 1`
### Output
#### struct del::Output
Output struct for various estimated outputs.
**Members:**
- `del::OutputType type` - type of the output
- `std::variant value` - value of the output
- `std::string name` - name of the output
Api Dotnet
https://verifeye-docs.realeyes.ai/native-sdk/demographic-estimation/api-dotnet/
# .NET API Documentation
## DemographicEstimator class
### class Realeyes.DemographicEstimation.DemographicEstimator
Main entry point for face detection and demographic estimation operations.
This class is thread-safe and supports concurrent asynchronous operations.
#### Constructor
```csharp
DemographicEstimator(string modelPath, int maxConcurrency = 0)
```
Creates a new DemographicEstimator instance
**Parameters:**
- `modelPath` (string) - Path to the demographic estimation model file (.realZ)
- `maxConcurrency` (int) - Maximum concurrency (0 for automatic/all cores), default: 0
**Throws:**
- `ArgumentNullException` - When modelPath is null
- `DemographicEstimationException` - When model loading fails
#### Methods
##### DetectFacesAsync(imageHeader)
```csharp
Task DetectFacesAsync(ImageHeader imageHeader)
```
Detects faces in an image asynchronously.
This method is non-blocking and thread-safe - multiple calls can be made concurrently.
**Parameters:**
- `imageHeader` (ImageHeader) - Image to process
**Returns:** Task
**Throws:**
- `DemographicEstimationException` - When detection fails
##### EstimateAsync(face)
```csharp
Task EstimateAsync(Face face)
```
Estimates demographic information (age, gender, age uncertainty) for a detected face asynchronously.
This method is non-blocking and thread-safe - multiple calls can be made concurrently.
**Parameters:**
- `face` (Face) - Previously detected face
**Returns:** Task
**Throws:**
- `ArgumentNullException` - When face is null
- `DemographicEstimationException` - When estimation fails
#### Properties
##### ConcurrentCalculations
```csharp
int ConcurrentCalculations { get; }
```
Gets the number of calculations currently running concurrently.
Use this to limit the number of concurrent calculations if needed.
##### ModelName
```csharp
string ModelName { get; }
```
Gets the name/version of the loaded model
##### SdkVersion
```csharp
static Version SdkVersion { get; }
```
Gets the SDK version (static property)
##### SdkVersionString
```csharp
static string SdkVersionString { get; }
```
Gets the SDK version as a string (static property)
## ImageHeader class
### class Realeyes.DemographicEstimation.ImageHeader
Image descriptor for passing image data to the Demographic Estimation Library
#### Constructor
```csharp
ImageHeader(byte[] data, int width, int height, int stride, ImageFormat format)
```
Creates a new image header
**Parameters:**
- `data` (byte[]) - Image data bytes
- `width` (int) - Width in pixels
- `height` (int) - Height in pixels
- `stride` (int) - Length of one row in bytes (e.g., 3*width + padding)
- `format` (ImageFormat) - Pixel format
**Throws:**
- `ArgumentNullException` - When data is null
- `ArgumentOutOfRangeException` - When width, height, or stride is not positive
#### Properties
- `Data` (byte[]) - Image data bytes
- `Width` (int) - Width of the image in pixels
- `Height` (int) - Height of the image in pixels
- `Stride` (int) - Length of one row of pixels in bytes (e.g: 3*width + padding)
- `Format` (ImageFormat) - Image pixel format
## Result classes
### FaceList
#### class Realeyes.DemographicEstimation.FaceList
A disposable collection of Face objects that automatically disposes all faces when disposed.
Inherits from List.
##### Methods
###### Dispose()
```csharp
void Dispose()
```
Disposes all Face objects in the collection synchronously
###### DisposeAsync()
### Face
#### class Realeyes.DemographicEstimation.Face
Represents a detected face with landmarks, bounding box, and confidence information
##### Constructor
```csharp
Face(ImageHeader imageHeader, Point2d[] landmarks, BoundingBox boundingBox, float confidence)
```
Creates a Face object from a third-party face detector
**Parameters:**
- `imageHeader` (ImageHeader) - Image containing the face
- `landmarks` (Point2d[]) - Face landmarks
- `boundingBox` (BoundingBox) - Bounding box of the face
- `confidence` (float) - Detection confidence score
**Throws:**
- `ArgumentNullException` - When imageHeader or landmarks is null
- `DemographicEstimationException` - When face creation fails
##### Properties
- `BoundingBox` (BoundingBox) - Gets the bounding box of this face
- `Confidence` (float) - Gets the detection confidence score
##### Methods
###### GetLandmarks()
```csharp
Point2d[] GetLandmarks()
```
Gets the facial landmarks
**Returns:** Point2d[]
###### Clone()
```csharp
Face Clone()
```
Creates a copy of this face
**Returns:** Face
**Throws:**
- `DemographicEstimationException` - When cloning fails
###### Dispose()
```csharp
void Dispose()
```
Disposes the face and releases native resources
### Point2d
#### struct Realeyes.DemographicEstimation.Point2d
2D point representing a landmark coordinate
##### Properties
- `X` (float) - X coordinate of landmark
- `Y` (float) - Y coordinate of landmark
### BoundingBox
#### struct Realeyes.DemographicEstimation.BoundingBox
Bounding box representing a rectangular region
##### Properties
- `X` (int) - X coordinate of the top-left corner
- `Y` (int) - Y coordinate of the top-left corner
- `Width` (int) - Width of the bounding box in pixels
- `Height` (int) - Height of the bounding box in pixels
- `Right` (int) - Gets the right edge X coordinate (computed property)
- `Bottom` (int) - Gets the bottom edge Y coordinate (computed property)
- `Area` (int) - Gets the area of the bounding box (computed property)
### EstimationResult
#### class Realeyes.DemographicEstimation.EstimationResult
Result of demographic estimation containing optional age, gender, and age uncertainty values
##### Properties
- `Age` (float?) - Estimated age in years (if available)
- `Gender` (Gender?) - Estimated gender (if available)
- `AgeUncertainty` (float?) - Age uncertainty estimation (if available)
##### Methods
###### ToString()
```csharp
string ToString()
```
Returns a string representation of the estimation result
**Returns:** string
## Enumerations
### OutputType
#### enum Realeyes.DemographicEstimation.OutputType
Type of demographic estimation output
**Values:**
- `Age = 0` - Age estimation
- `Gender = 1` - Gender classification
- `AgeUncertainty = 2` - Age uncertainty estimation
### Gender
#### enum Realeyes.DemographicEstimation.Gender
Gender classification
**Values:**
- `Female = 0` - Female
- `Male = 1` - Male
### ImageFormat
#### enum Realeyes.DemographicEstimation.ImageFormat
Image pixel format
**Values:**
- `Grayscale = 0` - 8-bit grayscale
- `RGB = 1` - 24-bit RGB
- `RGBA = 2` - 32-bit RGBA or RGB with padding
- `BGR = 3` - 24-bit BGR
- `BGRA = 4` - 32-bit BGRA or BGR with padding
### Version
#### struct Realeyes.DemographicEstimation.Version
Semantic version number
##### Properties
- `Major` (int) - Major version number
- `Minor` (int) - Minor version number
- `Patch` (int) - Patch version number
##### Methods
###### ToString()
```csharp
string ToString()
```
Returns the version as a string
**Returns:** string
## Exceptions
### DemographicEstimationException
#### class Realeyes.DemographicEstimation.DemographicEstimationException
Exception thrown when demographic estimation operations fail
Disposes all Face objects in the collection asynchronously
Api Python
https://verifeye-docs.realeyes.ai/native-sdk/demographic-estimation/api-python/
# Python API Documentation
## Module Functions
### get_sdk_version_string()
Returns the version string of the SDK (and not the model).
**Returns:** str
## DemographicEstimator class
### class realeyes.demographic_estimation.DemographicEstimator(model_file, max_concurrency=0)
The Demographic Estimator class
#### \_\_init\_\_(self, model_file, max_concurrency=0)
DemographicEstimator constructor: loads model file, sets up the processing.
**Parameters:**
- `model_file` (str) - path for the used model
- `max_concurrency` (int) - maximum allowed concurrency, 0 means automatic (using all cores), default: 0
#### detect_faces(self, image)
Detects the faces on an image.
**Parameters:**
- `image` (numpy.ndarray) - image of the face(s)
**Returns:** list[Face]
#### estimate(self, face)
Returns the estimated demographics of the detected face.
**Parameters:**
- `face` (Face) - face to estimate.
**Returns:** list[Output]
#### get_model_name(self)
Returns the name (version etc) of the loaded model.
**Returns:** str
## Result classes
### Face
#### class realeyes.demographic_estimation.Face
##### \_\_init\_\_(self, image, landmarks, bbox=BoundingBox(x=0, y=0, width=0, height=0), confidence=0.0)
Face constructor to use a 3rd party face detector as face source
**Parameters:**
- `image` (numpy.ndarray) - image of the face
- `landmarks` (list[Point2d]) - landmarks of the face, see [landmarks specification](https://verifeye-docs.realeyes.ai/overview.md#target-to-face-specs)
- `bbox` (BoundingBox) - bounding box of the face
- `confidence` (float) - confidence value of the detected face
##### bounding_box(self)
Returns the bounding box of the detected face.
**Returns:** BoundingBox
##### confidence(self)
Returns the confidence value of the detected face.
**Returns:** float
##### landmarks(self)
Returns the landmarks of the detected face.
**Returns:** list[Point2d]
See also: [landmarks specification](https://verifeye-docs.realeyes.ai/overview.md#target-to-face-specs).
### Point2d
#### class realeyes.demographic_estimation.Point2d
Point2d class for the landmarks
##### \_\_init\_\_(self, x, y)
Point2d constructor
**Parameters:**
- `x` (float) - X coordinate of the point
- `y` (float) - Y coordinate of the point
##### Attributes
- `x` (float) - X coordinate of the point.
- `y` (float) - Y coordinate of the point.
### BoundingBox
#### class realeyes.demographic_estimation.BoundingBox
Bounding Box class for the faces
##### \_\_init\_\_(self, x, y, width, height)
BoundingBox constructor
**Parameters:**
- `x` (int) - X coordinate of the top-left corner
- `y` (int) - Y coordinate of the top-left corner
- `width` (int) - Width of the bounding box in pixels
- `height` (int) - Height of the bounding box in pixels
##### Attributes
- `x` (int) - X coordinate of the top-left corner.
- `y` (int) - Y coordinate of the top-left corner.
- `width` (int) - Width of the bounding box in pixels.
- `height` (int) - Height of the bounding box in pixels.
### OutputType
#### class realeyes.demographic_estimation.OutputType
**Attributes:**
- `AGE` = 0
- `GENDER` = 1
- `AGE_UNCERTAINTY` = 2
### Gender
#### class realeyes.demographic_estimation.Gender
**Attributes:**
- `FEMALE` = 0
- `MALE` = 1
### Output
#### class realeyes.demographic_estimation.Output
**Attributes:**
- `name` (str) - Name of the output
- `type` (OutputType) - Type of the output
- `value` (Union[Gender, float]) - Value of the output
Index
https://verifeye-docs.realeyes.ai/native-sdk/demographic-estimation/
# Demographic Estimation Library
Welcome to Demographic Estimation Library documentation!
## Contents:
- [Overview](https://verifeye-docs.realeyes.ai/overview.md)
- [C++ API](https://verifeye-docs.realeyes.ai/api-cpp.md)
- [C API](https://verifeye-docs.realeyes.ai/api-c.md)
- [Python API](https://verifeye-docs.realeyes.ai/api-python.md)
- [.NET API](https://verifeye-docs.realeyes.ai/api-dotnet.md)
Overview
https://verifeye-docs.realeyes.ai/native-sdk/demographic-estimation/overview/
# Overview
The Demographic Estimation Library is a portable C++ library to estimate the persons' demographic characteristics (age, gedner, etc).
The SDK provides wrappers in the following languages:
* C++ (native)
* C
* Python
* C# / .NET
## Release Notes
* **Version 1.0.0 (24 Jan 2024)**
* Initial release
## Getting Started
### Hardware requirements
The SDK doesn't have any special hardware requirement:
- **CPU:** No special requirement, any modern 64 bit capable CPU (x86-64 with AVX, ARM8) is supported
- **GPU:** No special requirement
- **RAM:** 2 GB of available RAM required
- **Camera:** No special requirement, minimum resolution: 640x480.
### Software requirements
The SDK is regularly tested on the following Operating Systems:
- Windows 10
- Ubuntu 22.4
- Mac OS 12 Monterey
- iOS 14
- Android 12
### 3rd Party Licenses
While the SDK is released under a proprietary license, the following Open-Source projects where used in it with their respective licenses:
- OpenCV - [3 clause BSD](https://opencv.org/license/)
- Tensorflow - [Apache License 2.0](https://github.com/tensorflow/tensorflow/blob/master/LICENSE)
- Protobuf - [3 clause BSD](https://github.com/protocolbuffers/protobuf/blob/master/LICENSE)
- zlib - [zlib license](https://www.zlib.net/zlib_license.html)
- minizip-ng - [zlib license](https://github.com/zlib-ng/minizip-ng/blob/master/LICENSE)
- stlab - [Boost Software License 1.0](https://github.com/stlab/libraries/blob/main/LICENSE)
- docopt.cpp - [MIT License](https://github.com/docopt/docopt.cpp/blob/master/LICENSE-MIT)
- pybind11 - [3 clause BSD](https://github.com/pybind/pybind11/blob/master/LICENSE)
- fmtlib - [MIT License](https://github.com/fmtlib/fmt/blob/master/LICENSE.rst)
### Dependencies
The public C++ API hides all the implementation details from the user, and it only depends on the C++17 Standard Library.
It also provides a binary compatible interface, making it possible to change the underlying implementation
without the need of recompilation of the user code.
### Installation
#### C++
Extract the SDK contents, include the headers from the `include` folder and link `libDemographicEstimationLibrary` to your C++ project.
#### Python
The python version of the SDK can be installed with pip:
```bash
$ pip install realeyes.demographic_estimation
```
#### C# / .NET
The .NET version of the SDK can be installed via NuGet:
```bash
$ dotnet add package Realeyes.DemographicEstimation
```
## Usage
### C++
The main entry point of this library is the `del::DemographicEstimator` class.
After a **estimator** object was constructed, the user can call the `del::DemographicEstimator::detectFaces()` function to get the faces
for a frame of a video or other frame source.
The resulting `del::Face` objects can be used to call `del::DemographicEstimator::estimate()` to get the classifiers estimations of the face.
The results returned in `del::Output` structs.
`del::DemographicEstimator::detectFaces()` and `del::DemographicEstimator::estimate()` has two versions both are non-blocking async calls, one is returning **std::future** the other
is calling the callback on completion. After one call a subsequent call is possible without waiting for the result.
For the frame data, the user must construct a `del::ImageHeader` object and pass that to `del::DemographicEstimator::detectFaces()`.
The frame data must outlive this object since it is a non-owning view of the data, but it only needs to be valid during the
`del::DemographicEstimator::detectFaces()` call, the library will copy the frame data internally.
The following example shows the basic usage of the library using OpenCV for loading images and feeding them to the estimator:
```cpp
#include "demographicestimator.h"
#include
#include
#include
int main()
{
del::DemographicEstimator estimator("model/model.realZ");
cv::Mat image = cv::imread("image.jpg");
std::vector faces = estimator.detectFaces({image.ptr(), image.cols, image.rows, static_cast(image.step1()), del::ImageFormat::BGR}).get();
for (const del::Face& face: faces) {
auto results = estimator.estimate(face).get();
del::BoundingBox bbox = face.boundingBox();
std::cout << "User at (" << bbox.x << ", " << bbox.y << ", " << bbox.width << ", " << bbox.height << ") has the following estimated characteristics:" << std::endl;
for (const del::Output& result: results) {
std::cout << " " << result.name << " = ";
if (result.type == del::OutputType::AGE || result.type == del::OutputType::AGE_UNCERTAINTY)
std::cout << std::get(result.value) << std::endl;
else
std::cout << ((std::get(result.value) == del::Gender::FEMALE) ? "FEMALE" : "MALE") << std::endl;
}
std::cout << std::endl;
}
return 0;
}
```
### Python
The main entry point of this library is the `realeyes.demographic_estimation.DemographicEstimator` class.
After a **estimator** object was constructed, the user can call the `realeyes.demographic_estimation.DemographicEstimator.detect_faces()` function to get the faces
for a frame of a video or other frame source.
The resulting `realeyes.demographic_estimation.Face` objects can be used to call `realeyes.demographic_estimation.DemographicEstimator.estimate()` to get the classifiers estimations of the face.
The following example shows the basic usage of the library using OpenCV for loading images and feeding them to the estimator:
```python
import realeyes.demographic_estimation as del
import cv2
estimator = del.DemographicEstimator('model/model.realZ')
image = cv2.imread('image.jpg')[:, :, ::-1] # opencv reads BGR we need RGB
faces = estimator.detect_faces(image)
for face in faces:
print(f'User at {face.bounding_box()} has the following estimated characteristics:')
results = estimator.estimate(face)
for result in results:
print(f' {result.name} = {result.value} ')
```
### C# / .NET
The main entry point of this library is the `DemographicEstimator` class.
After an **estimator** object is constructed, you can call the `DetectFacesAsync()` method to detect faces
in a frame. The method returns a `Task` allowing for asynchronous, non-blocking operation.
The resulting `Face` objects can be used to call `EstimateAsync()` to get demographic estimations.
Both methods support concurrent execution - you can start multiple operations in parallel without waiting for results.
The following example demonstrates parallel processing of multiple frames using the async interface:
```csharp
using Realeyes.DemographicEstimation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
using var estimator = new DemographicEstimator("model/model.realZ");
// Load an image (example using raw byte array)
byte[] imageData = LoadImageData("image.jpg");
var imageHeader = new ImageHeader(imageData, 1920, 1080, 1920 * 3, ImageFormat.RGB);
// Detect faces asynchronously
await using var faces = await estimator.DetectFacesAsync(imageHeader);
Console.WriteLine($"Detected {faces.Count} face(s)");
// Start parallel demographic estimation for all faces
var estimationTasks = faces.Select(face => estimator.EstimateAsync(face)).ToList();
// Check concurrent calculations in flight
Console.WriteLine($"Running {estimator.ConcurrentCalculations} concurrent calculations");
// Wait for all estimations to complete
var demographics = await Task.WhenAll(estimationTasks);
// Process results
for (int i = 0; i < faces.Count; i++)
{
var face = faces[i];
var result = demographics[i];
Console.WriteLine($"Face at ({face.BoundingBox.X}, {face.BoundingBox.Y}, " +
$"{face.BoundingBox.Width}, {face.BoundingBox.Height}):");
if (result.Age.HasValue)
Console.WriteLine($" Age: {result.Age.Value:F1}");
if (result.Gender.HasValue)
Console.WriteLine($" Gender: {result.Gender.Value}");
if (result.AgeUncertainty.HasValue)
Console.WriteLine($" Age Uncertainty: {result.AgeUncertainty.Value:F2}");
}
}
static byte[] LoadImageData(string path)
{
// Implementation depends on your image loading library
throw new NotImplementedException();
}
}
```
## Results {#target-to-face-specs}
The **Face** objects consist of the following members:
* **bounding_box:** Bounding box of the detected face (left, top, width height).
* **confidence:** Confidence of the detection ([0,1] more is better).
* **landmarks:** 5 landmarks from the face:
1. left eye
2. right eye
3. nose (tip)
4. left mouth corner
5. right mouth corner

## 3rd party face detector
It is possible to calculate the embedding of a face which was detected with a different library. One can create
`Face` object by specifying the source image and the landmarks.
C
https://verifeye-docs.realeyes.ai/native-sdk/face-verification/api-reference/c/
# C API Reference
The C API provides a plain C interface to the Face Verification Library, suitable for integration with C programs and other languages through FFI.
---
## Opaque Types
### FVLFaceVerifier
```c
typedef struct FVLFaceVerifier FVLFaceVerifier;
```
Opaque handle to a FaceVerifier instance.
### FVLFace
```c
typedef struct FVLFace FVLFace;
```
Opaque handle to a Face instance.
---
## FaceVerifier Functions
### fvl_face_verifier_new
```c
FVLFaceVerifier* fvl_face_verifier_new(const char* model_file, int max_concurrency, char** errorMessage);
```
Creates a new FaceVerifier instance. Loads the model file and sets up processing.
| Parameter | Type | Description |
|-----------|------|-------------|
| model_file | `const char*` | Path to the `.realZ` model file |
| max_concurrency | `int` | Maximum allowed concurrency. 0 means automatic (all cores) |
| errorMessage | `char**` | Output: set to error message on failure, `NULL` on success. Caller must `free()`. Pass `NULL` to skip. |
**Returns:** Pointer to the new instance, or `NULL` on failure.
### fvl_face_verifier_free
```c
void fvl_face_verifier_free(FVLFaceVerifier* verifier);
```
Frees a FaceVerifier instance.
| Parameter | Type | Description |
|-----------|------|-------------|
| verifier | [`FVLFaceVerifier`](#fvlfaceverifier)`*` | Instance to free |
### fvl_face_verifier_detect_faces
```c
void fvl_face_verifier_detect_faces(FVLFaceVerifier* verifier, const FVLImageHeader* image_header,
FVLDetectFacesCallback callback, void* user_data);
```
Detects faces on an image asynchronously. The callback is invoked with the result.
| Parameter | Type | Description |
|-----------|------|-------------|
| verifier | [`FVLFaceVerifier`](#fvlfaceverifier)`*` | FaceVerifier instance |
| image_header | `const` [`FVLImageHeader`](#fvlimageheader)`*` | Image descriptor |
| callback | [`FVLDetectFacesCallback`](#fvldetectfacescallback) | Callback invoked with the result |
| user_data | `void*` | User data passed to the callback |
The image data is copied internally — it is safe to free the data after the call. This call is non-blocking.
### fvl_face_verifier_embed_face
```c
void fvl_face_verifier_embed_face(FVLFaceVerifier* verifier, const FVLFace* face,
FVLEmbedFaceCallback callback, void* user_data);
```
Computes the embedding of a detected face asynchronously.
| Parameter | Type | Description |
|-----------|------|-------------|
| verifier | [`FVLFaceVerifier`](#fvlfaceverifier)`*` | FaceVerifier instance |
| face | `const` [`FVLFace`](#fvlface)`*` | The previously detected face |
| callback | [`FVLEmbedFaceCallback`](#fvlembedFacecallback) | Callback invoked with the result |
| user_data | `void*` | User data passed to the callback |
### fvl_face_verifier_compare_faces
```c
FVLMatch fvl_face_verifier_compare_faces(FVLFaceVerifier* verifier,
const float* embedding1, int size1,
const float* embedding2, int size2);
```
Compares two face embeddings.
| Parameter | Type | Description |
|-----------|------|-------------|
| verifier | [`FVLFaceVerifier`](#fvlfaceverifier)`*` | FaceVerifier instance |
| embedding1 | `const float*` | First face embedding |
| size1 | `int` | Size of the first embedding |
| embedding2 | `const float*` | Second face embedding |
| size2 | `int` | Size of the second embedding |
**Returns:** [`FVLMatch`](#fvlmatch) — match result with similarity metric.
### fvl_face_verifier_get_concurrent_calculations
```c
int fvl_face_verifier_get_concurrent_calculations(const FVLFaceVerifier* verifier);
```
Returns the approximate number of calculations currently in-flight.
| Parameter | Type | Description |
|-----------|------|-------------|
| verifier | `const` [`FVLFaceVerifier`](#fvlfaceverifier)`*` | FaceVerifier instance |
**Returns:** `int` — number of concurrent calculations.
### fvl_face_verifier_get_model_name
```c
char* fvl_face_verifier_get_model_name(const FVLFaceVerifier* verifier);
```
Returns the name (version, etc.) of the loaded model.
| Parameter | Type | Description |
|-----------|------|-------------|
| verifier | `const` [`FVLFaceVerifier`](#fvlfaceverifier)`*` | FaceVerifier instance |
**Returns:** `char*` — model name string. **Caller must `free()` the returned string.**
### fvl_face_verifier_get_sdk_version
```c
FVLVersion fvl_face_verifier_get_sdk_version();
```
Returns the SDK version.
**Returns:** [`FVLVersion`](#fvlversion) — SDK version.
### fvl_face_verifier_get_sdk_version_string
```c
char* fvl_face_verifier_get_sdk_version_string();
```
Returns the SDK version as a string.
**Returns:** `char*` — version string. **Caller must `free()` the returned string.**
---
## Face Functions
### fvl_face_new
```c
FVLFace* fvl_face_new(const FVLImageHeader* image_header, const FVLPoint2d* landmarks,
int num_landmarks, const FVLBoundingBox* bbox, float confidence,
char** errorMessage);
```
Creates a Face object to support 3rd party face detectors.
| Parameter | Type | Description |
|-----------|------|-------------|
| image_header | `const` [`FVLImageHeader`](#fvlimageheader)`*` | Image descriptor |
| landmarks | `const` [`FVLPoint2d`](#fvlpoint2d)`*` | Face landmarks array |
| num_landmarks | `int` | Number of landmarks |
| bbox | `const` [`FVLBoundingBox`](#fvlboundingbox)`*` | Face bounding box |
| confidence | `float` | Detection confidence |
| errorMessage | `char**` | Output: error message on failure. Caller must `free()`. Pass `NULL` to skip. |
**Returns:** Pointer to the new Face instance, or `NULL` on failure.
### fvl_face_copy
```c
FVLFace* fvl_face_copy(const FVLFace* other);
```
Creates a copy of a Face instance.
| Parameter | Type | Description |
|-----------|------|-------------|
| other | `const` [`FVLFace`](#fvlface)`*` | Face to copy |
**Returns:** Pointer to the new Face copy, or `NULL` on failure.
### fvl_face_free
```c
void fvl_face_free(FVLFace* face);
```
Frees a Face instance.
| Parameter | Type | Description |
|-----------|------|-------------|
| face | [`FVLFace`](#fvlface)`*` | Face to free |
### fvl_face_detection_quality
```c
FVLDetectionQuality fvl_face_detection_quality(const FVLFace* face);
```
Returns the detection quality of the face.
| Parameter | Type | Description |
|-----------|------|-------------|
| face | `const` [`FVLFace`](#fvlface)`*` | Face instance |
**Returns:** [`FVLDetectionQuality`](#fvldetectionquality)
### fvl_face_bounding_box
```c
FVLBoundingBox fvl_face_bounding_box(const FVLFace* face);
```
Returns the bounding box of the face.
| Parameter | Type | Description |
|-----------|------|-------------|
| face | `const` [`FVLFace`](#fvlface)`*` | Face instance |
**Returns:** [`FVLBoundingBox`](#fvlboundingbox)
### fvl_face_confidence
```c
float fvl_face_confidence(const FVLFace* face);
```
Returns the confidence value of the face.
| Parameter | Type | Description |
|-----------|------|-------------|
| face | `const` [`FVLFace`](#fvlface)`*` | Face instance |
**Returns:** `float` — detection confidence.
### fvl_face_landmarks
```c
FVLPoint2dArray* fvl_face_landmarks(const FVLFace* face);
```
Returns the landmarks of the face.
| Parameter | Type | Description |
|-----------|------|-------------|
| face | `const` [`FVLFace`](#fvlface)`*` | Face instance |
**Returns:** [`FVLPoint2dArray`](#fvlpoint2darray)`*` — landmark array. **Caller must `free()` the returned array.**
---
## Data Types
### FVLPoint2d
```c
typedef struct FVLPoint2d {
float x;
float y;
} FVLPoint2d;
```
| Field | Type | Description |
|-------|------|-------------|
| x | `float` | X coordinate of the point |
| y | `float` | Y coordinate of the point |
### FVLPoint2dArray
```c
typedef struct FVLPoint2dArray {
int count;
FVLPoint2d* points;
} FVLPoint2dArray;
```
| Field | Type | Description |
|-------|------|-------------|
| count | `int` | Number of points |
| points | [`FVLPoint2d`](#fvlpoint2d)`*` | Pointer to the array of points |
### FVLBoundingBox
```c
typedef struct FVLBoundingBox {
int x;
int y;
int width;
int height;
} FVLBoundingBox;
```
| Field | Type | Description |
|-------|------|-------------|
| x | `int` | X coordinate of the top-left corner |
| y | `int` | Y coordinate of the top-left corner |
| width | `int` | Width in pixels |
| height | `int` | Height in pixels |
### FVLImageHeader
```c
typedef struct FVLImageHeader {
const uint8_t* data;
int width;
int height;
int stride;
FVLImageFormat format;
} FVLImageHeader;
```
| Field | Type | Description |
|-------|------|-------------|
| data | `const uint8_t*` | Pointer to the byte array of the image |
| width | `int` | Width of the image in pixels |
| height | `int` | Height of the image in pixels |
| stride | `int` | Length of one row of pixels in bytes (e.g., `3*width + padding`) |
| format | [`FVLImageFormat`](#fvlimageformat) | Image pixel format |
### FVLMatch
```c
typedef struct FVLMatch {
float similarity;
} FVLMatch;
```
| Field | Type | Description |
|-------|------|-------------|
| similarity | `float` | Similarity score between the two faces |
### FVLVersion
```c
typedef struct FVLVersion {
int major;
int minor;
int patch;
} FVLVersion;
```
| Field | Type | Description |
|-------|------|-------------|
| major | `int` | Major version number |
| minor | `int` | Minor version number |
| patch | `int` | Patch version number |
### FVLFaceArray
```c
typedef struct FVLFaceArray {
int count;
FVLFace** faces;
} FVLFaceArray;
```
| Field | Type | Description |
|-------|------|-------------|
| count | `int` | Number of faces |
| faces | [`FVLFace`](#fvlface)`**` | Pointer to the array of face pointers |
### FVLFloatArray
```c
typedef struct FVLFloatArray {
int count;
float* data;
} FVLFloatArray;
```
| Field | Type | Description |
|-------|------|-------------|
| count | `int` | Number of floats |
| data | `float*` | Pointer to the array of floats |
---
## Enumerations
### FVLImageFormat
```c
typedef enum FVLImageFormat {
FVLImageFormatGrayscale = 0,
FVLImageFormatRGB = 1,
FVLImageFormatRGBA = 2,
FVLImageFormatBGR = 3,
FVLImageFormatBGRA = 4,
} FVLImageFormat;
```
| Value | Description |
|-------|-------------|
| `FVLImageFormatGrayscale` | 8-bit grayscale |
| `FVLImageFormatRGB` | 24-bit RGB |
| `FVLImageFormatRGBA` | 32-bit RGBA or RGB with padding |
| `FVLImageFormatBGR` | 24-bit BGR |
| `FVLImageFormatBGRA` | 32-bit BGRA or BGR with padding |
### FVLDetectionQuality
```c
typedef enum FVLDetectionQuality {
FVLDetectionQualityGood = 0,
FVLDetectionQualityBadQuality = 1,
FVLDetectionQualityMaybeRolled = 2,
} FVLDetectionQuality;
```
| Value | Description |
|-------|-------------|
| `FVLDetectionQualityGood` | No issues detected |
| `FVLDetectionQualityBadQuality` | Bad quality detected |
| `FVLDetectionQualityMaybeRolled` | Face may be rolled; embeddings could be incorrect |
---
## Callback Types
### FVLDetectFacesCallback
```c
typedef void (*FVLDetectFacesCallback)(void* user_data, FVLFaceArray* faces, const char* error_msg);
```
Callback for face detection results.
| Parameter | Type | Description |
|-----------|------|-------------|
| user_data | `void*` | User data passed to the detection function |
| faces | [`FVLFaceArray`](#fvlfacearray)`*` | Array of detected faces. Valid only during the callback. |
| error_msg | `const char*` | Error message if failed, `NULL` on success. Valid only during the callback. |
### FVLEmbedFaceCallback
```c
typedef void (*FVLEmbedFaceCallback)(void* user_data, FVLFloatArray* embedding, const char* error_msg);
```
Callback for face embedding results.
| Parameter | Type | Description |
|-----------|------|-------------|
| user_data | `void*` | User data passed to the embedding function |
| embedding | [`FVLFloatArray`](#fvlfloatarray)`*` | Embedding vector. Valid only during the callback. |
| error_msg | `const char*` | Error message if failed, `NULL` on success. Valid only during the callback. |
**Important:** The `faces`/`embedding` and `error_msg` parameters are only valid during the callback execution. Copy any data you need to retain before the callback returns.
---
## Memory Management Summary
| Function Returns | Must Free? | How |
|------------------|------------|-----|
| [`fvl_face_verifier_new()`](#fvl_face_verifier_new) | Yes | [`fvl_face_verifier_free()`](#fvl_face_verifier_free) |
| [`fvl_face_new()`](#fvl_face_new) | Yes | [`fvl_face_free()`](#fvl_face_free) |
| [`fvl_face_copy()`](#fvl_face_copy) | Yes | [`fvl_face_free()`](#fvl_face_free) |
| [`fvl_face_landmarks()`](#fvl_face_landmarks) | Yes | `free()` |
| [`fvl_face_verifier_get_model_name()`](#fvl_face_verifier_get_model_name) | Yes | `free()` |
| [`fvl_face_verifier_get_sdk_version_string()`](#fvl_face_verifier_get_sdk_version_string) | Yes | `free()` |
| `errorMessage` output parameter | Yes | `free()` |
| Callback parameters | No | Valid only during callback |
Cpp
https://verifeye-docs.realeyes.ai/native-sdk/face-verification/api-reference/cpp/
# C++ API Reference
## Namespace
`fvl`
---
## Classes
### FaceVerifier
The main entry point for face detection, embedding, and verification operations.
#### Constructor
```cpp
FaceVerifier(const std::string& modelFile, int maxConcurrency = 0);
```
Loads the model file and sets up processing.
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| modelFile | `const std::string&` | Path to the `.realZ` model file | — |
| maxConcurrency | `int` | Maximum allowed concurrency. 0 means automatic (using all cores) | `0` |
#### Destructor
```cpp
~FaceVerifier();
```
#### Methods
##### detectFaces (Future)
```cpp
std::future> detectFaces(const fvl::ImageHeader& imageHeader);
```
Detects the faces on an image. Returns a future that resolves with the detected faces.
| Parameter | Type | Description |
|-----------|------|-------------|
| imageHeader | `const` [`ImageHeader`](#imageheader)`&` | Image descriptor |
**Returns:** `std::future>` — the detected faces.
The given [`ImageHeader`](#imageheader) doesn't own the image data; it is safe to delete the data after the call — a copy is made internally.
This call is non-blocking. You can call it again with the next image without waiting for the result. See [`getConcurrentCalculations()`](#getconcurrentcalculations).
##### detectFaces (Callback)
```cpp
void detectFaces(const fvl::ImageHeader& imageHeader,
std::function>)> callback);
```
Detects the faces on an image and invokes the callback with the result.
| Parameter | Type | Description |
|-----------|------|-------------|
| imageHeader | `const` [`ImageHeader`](#imageheader)`&` | Image descriptor |
| callback | `std::function>)>` | Callback invoked with the result |
##### embedFace (Future)
```cpp
std::future> embedFace(const fvl::Face& face);
```
Returns the embedding of a detected face.
| Parameter | Type | Description |
|-----------|------|-------------|
| face | `const` [`Face`](#face)`&` | The previously detected face to embed |
**Returns:** `std::future>` — the face embedding vector.
This call is non-blocking.
##### embedFace (Callback)
```cpp
void embedFace(const fvl::Face& face,
std::function>)> callback);
```
Returns the embedding of a detected face via callback.
| Parameter | Type | Description |
|-----------|------|-------------|
| face | `const` [`Face`](#face)`&` | The previously detected face to embed |
| callback | `std::function>)>` | Callback invoked with the result |
##### compareFaces
```cpp
fvl::Match compareFaces(const std::vector& embedding1,
const std::vector& embedding2);
```
Compares two face embeddings.
| Parameter | Type | Description |
|-----------|------|-------------|
| embedding1 | `const std::vector&` | Embedding of the first face |
| embedding2 | `const std::vector&` | Embedding of the second face |
**Returns:** [`Match`](#match) — match result with the similarity metric.
##### getConcurrentCalculations
```cpp
int getConcurrentCalculations() const;
```
Returns the approximate number of calculations currently in-flight. Use this to limit the number of concurrent calculations.
**Returns:** `int` — the number of concurrent calculations.
##### getModelName
```cpp
std::string getModelName() const;
```
Returns the name (version, etc.) of the loaded model.
**Returns:** `std::string` — name of the model.
##### getSDKVersion
```cpp
static fvl::Version getSDKVersion();
```
Returns the version of the SDK (not the model).
**Returns:** [`Version`](#version) — SDK version.
##### getSDKVersionString
```cpp
static std::string getSDKVersionString();
```
Returns the version of the SDK as a string.
**Returns:** `std::string` — SDK version string.
---
### Face
Represents a detected face with landmarks, bounding box, and quality information.
#### Constructor
```cpp
Face(const fvl::ImageHeader& imageHeader,
const std::vector& landmarks,
const fvl::BoundingBox& bbox = fvl::BoundingBox(),
float confidence = 0.0f);
```
Creates a Face object to support 3rd party face detectors.
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| imageHeader | `const` [`ImageHeader`](#imageheader)`&` | Image containing the face | — |
| landmarks | `const std::vector<`[`Point2d`](#point2d)`>&` | Face landmarks (5 points) | — |
| bbox | `const` [`BoundingBox`](#boundingbox)`&` | Bounding box of the face | `BoundingBox()` |
| confidence | `float` | Detection confidence score | `0.0f` |
#### Methods
##### detectionQuality
```cpp
DetectionQuality detectionQuality() const;
```
**Returns:** [`DetectionQuality`](#detectionquality) — the detection quality of the face.
##### boundingBox
```cpp
BoundingBox boundingBox() const;
```
**Returns:** [`BoundingBox`](#boundingbox) — the bounding box of the face.
##### confidence
```cpp
float confidence() const;
```
**Returns:** `float` — the detection confidence score.
##### landmarks
```cpp
std::vector landmarks() const;
```
**Returns:** `std::vector<`[`Point2d`](#point2d)`>` — the 5 facial landmarks. See [landmarks specification](https://verifeye-docs.realeyes.ai/../overview.md#results).
---
## Types
### ImageHeader
Descriptor for image data (non-owning).
```cpp
struct ImageHeader {
const uint8_t* data;
int width;
int height;
int stride;
fvl::ImageFormat format;
};
```
| Field | Type | Description |
|-------|------|-------------|
| data | `const uint8_t*` | Pointer to the byte array of the image |
| width | `int` | Width of the image in pixels |
| height | `int` | Height of the image in pixels |
| stride | `int` | Length of one row of pixels in bytes (e.g., `3*width + padding`) |
| format | [`ImageFormat`](#imageformat) | Image pixel format |
### Point2d
2D point for landmark coordinates.
```cpp
struct Point2d {
float x;
float y;
};
```
| Field | Type | Description |
|-------|------|-------------|
| x | `float` | X coordinate of the point |
| y | `float` | Y coordinate of the point |
### BoundingBox
Bounding box for detected faces.
```cpp
struct BoundingBox {
int x;
int y;
int width;
int height;
};
```
| Field | Type | Description |
|-------|------|-------------|
| x | `int` | X coordinate of the top-left corner |
| y | `int` | Y coordinate of the top-left corner |
| width | `int` | Width in pixels |
| height | `int` | Height in pixels |
### Match
Result of face comparison.
```cpp
struct Match {
float similarity;
};
```
| Field | Type | Description |
|-------|------|-------------|
| similarity | `float` | Similarity score between the two faces |
### Version
Semantic version number for the SDK.
```cpp
struct Version {
int major;
int minor;
int patch;
};
```
| Field | Type | Description |
|-------|------|-------------|
| major | `int` | Major version number |
| minor | `int` | Minor version number |
| patch | `int` | Patch version number |
### ErrorType
Error information for the callback interface.
```cpp
struct ErrorType {
std::string errorString;
};
```
| Field | Type | Description |
|-------|------|-------------|
| errorString | `std::string` | Human-readable description of the error |
### ResultOrError
Type representing the result or the error in the callback interface.
```cpp
template
using ResultOrError = std::variant;
```
Use `std::get_if` or `std::visit` to extract the result or error:
```cpp
if (auto* value = std::get_if(&result)) {
// success
} else {
auto& error = std::get(result);
// handle error
}
```
---
## Enums
### ImageFormat
```cpp
enum class ImageFormat {
Grayscale = 0,
RGB = 1,
RGBA = 2,
BGR = 3,
BGRA = 4,
};
```
| Value | Description |
|-------|-------------|
| `Grayscale` | 8-bit grayscale |
| `RGB` | 24-bit RGB |
| `RGBA` | 32-bit RGBA or RGB with padding |
| `BGR` | 24-bit BGR |
| `BGRA` | 32-bit BGRA or BGR with padding |
### DetectionQuality
```cpp
enum class DetectionQuality {
Good = 0,
BadQuality = 1,
MaybeRolled = 2,
};
```
| Value | Description |
|-------|-------------|
| `Good` | No issues detected |
| `BadQuality` | Bad quality detected |
| `MaybeRolled` | Face may be rolled; embeddings could be incorrect |
---
## Thread Safety
- [`FaceVerifier`](#faceverifier) methods can be called concurrently from multiple threads.
- [`detectFaces()`](#detectfaces-future) and [`embedFace()`](#embedface-future) calls can execute concurrently.
- Use [`getConcurrentCalculations()`](#getconcurrentcalculations) to monitor and limit concurrency.
Dotnet
https://verifeye-docs.realeyes.ai/native-sdk/face-verification/api-reference/dotnet/
# .NET API Reference
## Namespace
`Realeyes.FaceVerification`
---
## Classes
### FaceVerifier
Main entry point for face detection, embedding, and verification operations. Implements `IDisposable`.
#### Constructor
```csharp
public FaceVerifier(string modelPath, int maxConcurrency = 0)
```
Creates a new FaceVerifier instance.
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| modelPath | `string` | Path to the `.realZ` model file | — |
| maxConcurrency | `int` | Maximum concurrency. 0 for automatic (all cores) | `0` |
**Throws:**
- `ArgumentNullException` — when `modelPath` is null
- [`FaceVerificationException`](#faceverificationexception) — when model loading fails
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| ConcurrentCalculations | `int` | Number of calculations currently running concurrently (read-only) |
| ModelName | `string` | Name/version of the loaded model (read-only) |
| SdkVersion | [`Version`](#version) | SDK version (read-only, static) |
| SdkVersionString | `string` | SDK version as a string (read-only, static) |
#### Methods
##### DetectFacesAsync
```csharp
public Task DetectFacesAsync(ImageHeader imageHeader)
```
Detects faces in an image asynchronously.
| Parameter | Type | Description |
|-----------|------|-------------|
| imageHeader | [`ImageHeader`](#imageheader) | Image to process |
**Returns:** `Task<`[`FaceList`](#facelist)`>` — disposable collection of detected faces.
**Throws:** [`FaceVerificationException`](#faceverificationexception) — when detection fails.
##### EmbedFaceAsync
```csharp
public Task EmbedFaceAsync(Face face)
```
Computes the embedding vector for a detected face asynchronously.
| Parameter | Type | Description |
|-----------|------|-------------|
| face | [`Face`](#face) | Previously detected face |
**Returns:** `Task` — embedding vector.
**Throws:**
- `ArgumentNullException` — when `face` is null
- [`FaceVerificationException`](#faceverificationexception) — when embedding fails
##### CompareFaces
```csharp
public Match CompareFaces(float[] embedding1, float[] embedding2)
```
Compares two face embeddings and returns a similarity score.
| Parameter | Type | Description |
|-----------|------|-------------|
| embedding1 | `float[]` | First face embedding |
| embedding2 | `float[]` | Second face embedding |
**Returns:** [`Match`](#match) — match result with similarity score.
**Throws:**
- `ArgumentNullException` — when either embedding is null
- `ArgumentException` — when embeddings have different lengths
##### Dispose
```csharp
public void Dispose()
```
Disposes the FaceVerifier and releases native resources.
---
### FaceList
A disposable collection of [`Face`](#face) objects that automatically disposes all faces when disposed. Inherits from `List` and implements `IDisposable` and `IAsyncDisposable`.
#### Methods
##### Dispose
```csharp
public void Dispose()
```
Disposes all Face objects in the collection synchronously.
##### DisposeAsync
```csharp
public ValueTask DisposeAsync()
```
Disposes all Face objects in the collection asynchronously.
---
### Face
Represents a detected face with landmarks, bounding box, and quality information. Implements `IDisposable`.
#### Constructor
```csharp
public Face(ImageHeader imageHeader, Point2d[] landmarks, BoundingBox boundingBox, float confidence)
```
Creates a Face object from a third-party face detector.
| Parameter | Type | Description |
|-----------|------|-------------|
| imageHeader | [`ImageHeader`](#imageheader) | Image containing the face |
| landmarks | [`Point2d`](#point2d)`[]` | Face landmarks (exactly 5 points) |
| boundingBox | [`BoundingBox`](#boundingbox) | Bounding box of the face |
| confidence | `float` | Detection confidence score |
**Throws:**
- `ArgumentNullException` — when `imageHeader` or `landmarks` is null
- `ArgumentException` — when landmarks count is not exactly 5
- [`FaceVerificationException`](#faceverificationexception) — when face creation fails
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| DetectionQuality | [`DetectionQuality`](#detectionquality) | Detection quality of this face (read-only) |
| BoundingBox | [`BoundingBox`](#boundingbox) | Bounding box of this face (read-only) |
| Confidence | `float` | Detection confidence score (read-only) |
#### Methods
##### GetLandmarks
```csharp
public Point2d[] GetLandmarks()
```
Gets the facial landmarks.
**Returns:** [`Point2d`](#point2d)`[]` — array of 5 landmark points.
##### Clone
```csharp
public Face Clone()
```
Creates a copy of this face.
**Returns:** [`Face`](#face) — a new Face instance with the same data.
##### Dispose
```csharp
public void Dispose()
```
Disposes the face and releases native resources.
---
## Data Types
### ImageHeader
Image descriptor for passing image data to the Face Verification Library. (`readonly record struct`)
#### Constructor
```csharp
public ImageHeader(byte[] Data, int Width, int Height, int Stride, ImageFormat Format)
```
| Parameter | Type | Description |
|-----------|------|-------------|
| Data | `byte[]` | Image data bytes |
| Width | `int` | Width in pixels |
| Height | `int` | Height in pixels |
| Stride | `int` | Length of one row in bytes (e.g., `3 * width + padding`) |
| Format | [`ImageFormat`](#imageformat) | Pixel format |
**Throws:**
- `ArgumentNullException` — when `Data` is null
- `ArgumentOutOfRangeException` — when `Width`, `Height`, or `Stride` is not positive
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| Data | `byte[]` | Image data bytes (read-only) |
| Width | `int` | Width of the image in pixels (read-only) |
| Height | `int` | Height of the image in pixels (read-only) |
| Stride | `int` | Length of one row of pixels in bytes (read-only) |
| Format | [`ImageFormat`](#imageformat) | Image pixel format (read-only) |
### BoundingBox
Bounding box representing a rectangular region. (`readonly record struct`)
#### Constructor
```csharp
public BoundingBox(int X, int Y, int Width, int Height)
```
| Parameter | Type | Description |
|-----------|------|-------------|
| X | `int` | X coordinate of the top-left corner |
| Y | `int` | Y coordinate of the top-left corner |
| Width | `int` | Width of the bounding box |
| Height | `int` | Height of the bounding box |
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| X | `int` | X coordinate of the top-left corner (read-only) |
| Y | `int` | Y coordinate of the top-left corner (read-only) |
| Width | `int` | Width of the bounding box (read-only) |
| Height | `int` | Height of the bounding box (read-only) |
| Right | `int` | Right edge X coordinate (`X + Width`) (read-only) |
| Bottom | `int` | Bottom edge Y coordinate (`Y + Height`) (read-only) |
| Area | `int` | Area of the bounding box (`Width * Height`) (read-only) |
### Point2d
2D point representing a landmark coordinate. (`readonly record struct`)
#### Constructor
```csharp
public Point2d(float X, float Y)
```
| Parameter | Type | Description |
|-----------|------|-------------|
| X | `float` | X coordinate |
| Y | `float` | Y coordinate |
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| X | `float` | X coordinate (read-only) |
| Y | `float` | Y coordinate (read-only) |
### Match
Result of face comparison indicating similarity. (`readonly record struct`)
#### Constructor
```csharp
public Match(float Similarity)
```
| Parameter | Type | Description |
|-----------|------|-------------|
| Similarity | `float` | Similarity score |
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| Similarity | `float` | Similarity score (read-only) |
#### Methods
##### ExceedsThreshold
```csharp
public bool ExceedsThreshold(float threshold)
```
Checks if the similarity score exceeds a threshold.
| Parameter | Type | Description |
|-----------|------|-------------|
| threshold | `float` | Similarity threshold |
**Returns:** `bool` — `true` if `Similarity >= threshold`.
### Version
Semantic version number. (`readonly record struct`)
#### Constructor
```csharp
public Version(int Major, int Minor, int Patch)
```
| Parameter | Type | Description |
|-----------|------|-------------|
| Major | `int` | Major version number |
| Minor | `int` | Minor version number |
| Patch | `int` | Patch version number |
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| Major | `int` | Major version number (read-only) |
| Minor | `int` | Minor version number (read-only) |
| Patch | `int` | Patch version number (read-only) |
#### Methods
##### ToString
```csharp
public override string ToString()
```
**Returns:** `string` — version in `"Major.Minor.Patch"` format.
---
## Enumerations
### ImageFormat
Image pixel format.
| Value | Int | Description |
|-------|-----|-------------|
| `Grayscale` | 0 | 8-bit grayscale |
| `RGB` | 1 | 24-bit RGB |
| `RGBA` | 2 | 32-bit RGBA or RGB with padding |
| `BGR` | 3 | 24-bit BGR |
| `BGRA` | 4 | 32-bit BGRA or BGR with padding |
### DetectionQuality
Detection quality indicator.
| Value | Int | Description |
|-------|-----|-------------|
| `Good` | 0 | No issues detected |
| `BadQuality` | 1 | Bad quality detected |
| `MaybeRolled` | 2 | Face may be rolled; embeddings could be incorrect |
---
## Exceptions
### FaceVerificationException
Exception thrown when Face Verification Library operations fail. Inherits from `Exception`.
#### Constructors
```csharp
public FaceVerificationException()
public FaceVerificationException(string message)
public FaceVerificationException(string message, Exception innerException)
```
| Parameter | Type | Description |
|-----------|------|-------------|
| message | `string` | Error message |
| innerException | `Exception` | Inner exception |
Python
https://verifeye-docs.realeyes.ai/native-sdk/face-verification/api-reference/python/
# Python API Reference
## Module
```python
import realeyes.face_verification
```
---
## Classes
### FaceVerifier
The main entry point for face detection, embedding, and verification operations.
#### Constructor
```python
FaceVerifier(model_file: str, max_concurrency: int = 0)
```
Loads the model file and sets up processing.
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| model_file | `str` | Path to the `.realZ` model file | — |
| max_concurrency | `int` | Maximum allowed concurrency. 0 means automatic (all cores) | `0` |
#### Methods
##### detect_faces
```python
def detect_faces(self, image: numpy.ndarray[numpy.uint8]) -> list[Face]
```
Detects faces on an image.
| Parameter | Type | Description |
|-----------|------|-------------|
| image | `numpy.ndarray[numpy.uint8]` | Image in RGB format, shape `(height, width, channels)` |
**Returns:** `list[`[`Face`](#face)`]` — the detected faces.
##### embed_face
```python
def embed_face(self, face: Face) -> list[float]
```
Returns the embedding vector of a detected face.
| Parameter | Type | Description |
|-----------|------|-------------|
| face | [`Face`](#face) | The previously detected face |
**Returns:** `list[float]` — the face embedding vector.
##### compare_faces
```python
def compare_faces(self, embedding1: list[float], embedding2: list[float]) -> Match
```
Compares two face embeddings.
| Parameter | Type | Description |
|-----------|------|-------------|
| embedding1 | `list[float]` | Embedding of the first face |
| embedding2 | `list[float]` | Embedding of the second face |
**Returns:** [`Match`](#match) — match result with similarity score.
##### get_model_name
```python
def get_model_name(self) -> str
```
Returns the name (version, etc.) of the loaded model.
**Returns:** `str` — model name.
---
## Module Functions
### get_sdk_version_string
```python
def get_sdk_version_string() -> str
```
Returns the version string of the SDK (not the model version).
**Returns:** `str` — SDK version string.
---
## Result Classes
### Face
Represents a detected face with landmarks, bounding box, and quality information.
#### Constructor
```python
Face(image: numpy.ndarray[numpy.uint8],
landmarks: list[Point2d],
bbox: BoundingBox = BoundingBox(x=0, y=0, width=0, height=0),
confidence: float = 0.0)
```
Creates a Face object to support 3rd party face detectors.
| Parameter | Type | Description | Default |
|-----------|------|-----------------------------------------------------------------------------------|---------|
| image | `numpy.ndarray[numpy.uint8]` | Image of the face (RGB format) | — |
| landmarks | `list[`[`Point2d`](#point2d)`]` | Face landmarks (5 points). See [landmarks specification](https://verifeye-docs.realeyes.ai/../overview.md#results). | — |
| bbox | [`BoundingBox`](#boundingbox) | Bounding box of the face | `BoundingBox(x=0, y=0, width=0, height=0)` |
| confidence | `float` | Detection confidence score | `0.0` |
#### Methods
##### bounding_box
```python
def bounding_box(self) -> BoundingBox
```
**Returns:** [`BoundingBox`](#boundingbox) — the bounding box of the detected face.
##### confidence
```python
def confidence(self) -> float
```
**Returns:** `float` — the detection confidence score.
##### detection_quality
```python
def detection_quality(self) -> DetectionQuality
```
**Returns:** [`DetectionQuality`](#detectionquality) — the detection quality of the face.
##### landmarks
```python
def landmarks(self) -> list[Point2d]
```
**Returns:** `list[`[`Point2d`](#point2d)`]` — the 5 facial landmarks.
---
### Point2d
2D point for landmark coordinates.
```python
Point2d(x: float, y: float)
```
| Attribute | Type | Description |
|-----------|------|-------------|
| x | `float` | X coordinate of the point |
| y | `float` | Y coordinate of the point |
### BoundingBox
Bounding box for detected faces.
```python
BoundingBox(x: int, y: int, width: int, height: int)
```
| Attribute | Type | Description |
|-----------|------|-------------|
| x | `int` | X coordinate of the top-left corner |
| y | `int` | Y coordinate of the top-left corner |
| width | `int` | Width of the bounding box in pixels |
| height | `int` | Height of the bounding box in pixels |
### Match
Result of face comparison.
| Attribute | Type | Description |
|-----------|------|-------------|
| similarity | `float` | Similarity score between the two faces |
---
## Enums
### DetectionQuality
Detection quality indicator.
| Value | Description |
|-------|-------------|
| `DetectionQuality.Good` | No issues detected |
| `DetectionQuality.BadQuality` | Bad quality detected |
| `DetectionQuality.MaybeRolled` | Face may be rolled; embeddings could be incorrect |
C
https://verifeye-docs.realeyes.ai/native-sdk/face-verification/getting-started/c/
# Getting Started with C API
## Prerequisites
- C99 compatible compiler
- The Face Verification Library shared library (`.so` / `.dylib` / `.dll`)
## Installation
Extract the SDK contents, include `faceverifier_c.h` from the `include` folder and link `libFaceVerificationLibrary` to your C project.
## Quick Start Example
```c
#include "faceverifier_c.h"
#include
#include
/* Callback for face detection */
void on_faces_detected(void* user_data, FVLFaceArray* faces, const char* error_msg) {
if (error_msg) {
fprintf(stderr, "Detection error: %s\n", error_msg);
return;
}
printf("Detected %d face(s)\n", faces->count);
/* Process each face... */
for (int i = 0; i < faces->count; i++) {
FVLBoundingBox bbox = fvl_face_bounding_box(faces->faces[i]);
printf(" Face %d: (%d, %d, %d, %d)\n", i, bbox.x, bbox.y, bbox.width, bbox.height);
}
}
int main() {
char* error = NULL;
/* Create verifier */
FVLFaceVerifier* verifier = fvl_face_verifier_new("model/model.realZ", 0, &error);
if (!verifier) {
fprintf(stderr, "Failed to create verifier: %s\n", error);
free(error);
return 1;
}
/* Detect faces (async with callback) */
FVLImageHeader header = {image_data, width, height, stride, FVLImageFormatRGB};
fvl_face_verifier_detect_faces(verifier, &header, on_faces_detected, NULL);
/* Clean up */
fvl_face_verifier_free(verifier);
return 0;
}
```
## Common Patterns
### Error Handling
Functions that can fail accept a `char** errorMessage` output parameter. On failure, the function returns `NULL` and sets the error message. The caller must free the error string:
```c
char* error = NULL;
FVLFaceVerifier* verifier = fvl_face_verifier_new("model.realZ", 0, &error);
if (!verifier) {
fprintf(stderr, "Error: %s\n", error);
free(error);
}
```
Pass `NULL` for `errorMessage` if you don't need the error details.
### Memory Management
| Function Returns | Must Free? | How |
|------------------|------------|-----|
| `fvl_face_verifier_new()` | Yes | `fvl_face_verifier_free()` |
| `fvl_face_new()` | Yes | `fvl_face_free()` |
| `fvl_face_copy()` | Yes | `fvl_face_free()` |
| `fvl_face_landmarks()` | Yes | `free()` |
| `fvl_face_verifier_get_model_name()` | Yes | `free()` |
| `fvl_face_verifier_get_sdk_version_string()` | Yes | `free()` |
| `errorMessage` output parameter | Yes | `free()` |
| Callback parameters (`faces`, `embedding`, `error_msg`) | No | Valid only during callback |
### Callbacks
Async operations use callbacks. The `result` and `error_msg` parameters are only valid during the callback — copy any data you need to retain:
```c
void on_embedding(void* user_data, FVLFloatArray* embedding, const char* error_msg) {
if (error_msg) {
/* handle error */
return;
}
/* Copy embedding data if needed beyond callback lifetime */
float* my_embedding = malloc(embedding->count * sizeof(float));
memcpy(my_embedding, embedding->data, embedding->count * sizeof(float));
}
```
## Next Steps
- [C API Reference](https://verifeye-docs.realeyes.ai/../api-reference/c.md)
Cpp
https://verifeye-docs.realeyes.ai/native-sdk/face-verification/getting-started/cpp/
# Getting Started with C++ API
## Prerequisites
- C++17 compatible compiler
- CMake 3.23+
- Conan package manager
## Installation
Extract the SDK contents, include the headers from the `include` folder and link `libFaceVerificationLibrary` to your C++ project.
## Quick Start Example
```cpp
#include "faceverifier.h"
#include
#include
#include
int main()
{
fvl::FaceVerifier verifier("model/model.realZ");
cv::Mat image1 = cv::imread("image1.jpg");
cv::Mat image2 = cv::imread("image2.jpg");
// Detect faces
auto faces1 = verifier.detectFaces({image1.ptr(), image1.cols, image1.rows,
static_cast(image1.step1()), fvl::ImageFormat::BGR}).get();
auto faces2 = verifier.detectFaces({image2.ptr(), image2.cols, image2.rows,
static_cast(image2.step1()), fvl::ImageFormat::BGR}).get();
// Compute embeddings
std::vector> embeddings1, embeddings2;
for (const auto& face : faces1)
embeddings1.push_back(verifier.embedFace(face).get());
for (const auto& face : faces2)
embeddings2.push_back(verifier.embedFace(face).get());
// Compare
for (size_t i = 0; i < embeddings1.size(); ++i)
for (size_t j = 0; j < embeddings2.size(); ++j)
if (verifier.compareFaces(embeddings1[i], embeddings2[j]).similarity > 0.3)
std::cout << "Match found!" << std::endl;
return 0;
}
```
## Common Patterns
### Async Operations
Both `detectFaces()` and `embedFace()` are non-blocking. Each has two overloads:
**std::future API** — returns a `std::future` you can `.get()` on:
```cpp
std::future> result = verifier.detectFaces(imageHeader);
auto faces = result.get(); // blocks until complete
```
**Callback API** — invokes a callback when complete:
```cpp
verifier.detectFaces(imageHeader, [](fvl::ResultOrError> result) {
if (auto* faces = std::get_if>(&result)) {
// process faces
} else {
auto& error = std::get(result);
// handle error
}
});
```
You can submit multiple frames without waiting for prior results. Use `getConcurrentCalculations()` to monitor in-flight work.
### Image Data
Construct an [`ImageHeader`](https://verifeye-docs.realeyes.ai/../api-reference/cpp.md#imageheader) to describe your frame data. The `ImageHeader` is a non-owning view — the underlying data must remain valid during the `detectFaces()` call, but is copied internally so it can be freed immediately after.
### Error Handling
The callback API uses [`ResultOrError`](https://verifeye-docs.realeyes.ai/../api-reference/cpp.md#resultorerror) (`std::variant`) to represent success or failure.
## Next Steps
- [C++ API Reference](https://verifeye-docs.realeyes.ai/../api-reference/cpp.md)
Dotnet
https://verifeye-docs.realeyes.ai/native-sdk/face-verification/getting-started/dotnet/
# Getting Started with .NET API
## Prerequisites
- .NET 8.0+
## Installation
```bash
dotnet add package Realeyes.FaceVerification
```
## Quick Start Example
```csharp
using Realeyes.FaceVerification;
using OpenCvSharp;
using var verifier = new FaceVerifier("model/model.realZ");
using var image1 = Cv2.ImRead("image1.jpg");
using var image2 = Cv2.ImRead("image2.jpg");
var imageData1 = image1.ToBytes();
var imageData2 = image2.ToBytes();
var header1 = new ImageHeader(imageData1, image1.Width, image1.Height,
image1.Width * image1.Channels(), ImageFormat.BGR);
var header2 = new ImageHeader(imageData2, image2.Width, image2.Height,
image2.Width * image2.Channels(), ImageFormat.BGR);
// Detect faces in parallel
using var faces1 = await verifier.DetectFacesAsync(header1);
using var faces2 = await verifier.DetectFacesAsync(header2);
// Embed all faces
var embeddings1 = new List();
foreach (var face in faces1)
embeddings1.Add(await verifier.EmbedFaceAsync(face));
var embeddings2 = new List();
foreach (var face in faces2)
embeddings2.Add(await verifier.EmbedFaceAsync(face));
// Compare embeddings
for (int i = 0; i < embeddings1.Count; i++)
for (int j = 0; j < embeddings2.Count; j++)
if (verifier.CompareFaces(embeddings1[i], embeddings2[j]).Similarity > 0.3f)
Console.WriteLine("Match found!");
```
## Common Patterns
### Async/Await
Face detection and embedding are asynchronous. Use `await` to get results:
```csharp
using var faces = await verifier.DetectFacesAsync(header);
var embedding = await verifier.EmbedFaceAsync(faces[0]);
```
### Resource Management
[`FaceVerifier`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#faceverifier), [`Face`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#face), and [`FaceList`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#facelist) implement `IDisposable`. Always use `using` statements to ensure native resources are released:
```csharp
using var verifier = new FaceVerifier("model.realZ");
using var faces = await verifier.DetectFacesAsync(header);
```
`FaceList` also implements `IAsyncDisposable`:
```csharp
await using var faces = await verifier.DetectFacesAsync(header);
```
### Error Handling
Operations throw [`FaceVerificationException`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#faceverificationexception) on failure:
```csharp
try
{
using var verifier = new FaceVerifier("model.realZ");
using var faces = await verifier.DetectFacesAsync(header);
}
catch (FaceVerificationException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
```
Standard .NET exceptions are also thrown for invalid arguments:
- `ArgumentNullException` — null parameters
- `ArgumentException` — invalid values (e.g., mismatched embedding lengths)
- `ArgumentOutOfRangeException` — non-positive image dimensions
- `ObjectDisposedException` — accessing disposed objects
### 3rd Party Face Detector
Create a [`Face`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#face) from an external detector by specifying image, landmarks, bounding box, and confidence:
```csharp
var landmarks = new Point2d[]
{
new(100f, 120f), // left eye
new(160f, 120f), // right eye
new(130f, 155f), // nose tip
new(105f, 180f), // left mouth corner
new(155f, 180f), // right mouth corner
};
using var face = new Face(header, landmarks, new BoundingBox(80, 90, 100, 120), 0.95f);
var embedding = await verifier.EmbedFaceAsync(face);
```
## Next Steps
- [.NET API Reference](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md)
Python
https://verifeye-docs.realeyes.ai/native-sdk/face-verification/getting-started/python/
# Getting Started with Python API
## Prerequisites
- Python >= 3.10
- NumPy
## Installation
```bash
pip install realeyes.face_verification
```
## Quick Start Example
```python
import realeyes.face_verification as fvl
import cv2
verifier = fvl.FaceVerifier('model/model.realZ')
image1 = cv2.imread('image1.jpg')[:, :, ::-1] # OpenCV reads BGR, we need RGB
image2 = cv2.imread('image2.jpg')[:, :, ::-1]
faces1 = verifier.detect_faces(image1)
faces2 = verifier.detect_faces(image2)
embeddings1 = [verifier.embed_face(face) for face in faces1]
embeddings2 = [verifier.embed_face(face) for face in faces2]
for i, e1 in enumerate(embeddings1):
for j, e2 in enumerate(embeddings2):
if verifier.compare_faces(e1, e2).similarity > 0.3:
print(f'{faces1[i]} from image 1 and {faces2[j]} from image 2 are the same person!')
```
## Common Patterns
### Image Format
The Python API expects images as NumPy arrays (`numpy.ndarray` of `uint8`) in **RGB** format with shape `(height, width, channels)`. If you use OpenCV (which loads BGR), convert with:
```python
rgb_image = cv2.imread('photo.jpg')[:, :, ::-1]
```
### Concurrent processing
You can safely use a single FaceVerifier instance from multiple threads to improve throughput and better utilize available CPU cores. The example below uses Python’s standard [ThreadPoolExecutor](https://docs.python.org/3/library/concurrent.futures.html#threadpoolexecutor).
```python
from collections import deque
from concurrent.futures import Future, ThreadPoolExecutor
from pathlib import Path
import numpy as np
from PIL import Image
from realeyes.face_verification import FaceVerifier
def process_images(images: list[Path],
face_verifier: FaceVerifier,
concurrent_inferences: int) -> list[list[float] | None]:
def process_image(image_path: Path) -> list[float] | None:
img = Image.open(image_path)
faces = face_verifier.detect_faces(np.array(img))
if len(faces) == 0:
return None
return face_verifier.embed_face(faces[0])
if concurrent_inferences == 1:
return [process_image(image) for image in images]
embeddings: list[list[float] | None] = [None] * len(images)
with ThreadPoolExecutor(max_workers=concurrent_inferences) as executor:
futures: deque[tuple[int, Future[list[float] | None]]] = deque()
for idx, image in enumerate(images):
# Manage futures queue to avoid memory buildup
if len(futures) >= 2 * concurrent_inferences:
processed_idx, future = futures.popleft()
embeddings[processed_idx] = future.result()
future = executor.submit(process_image, image)
futures.append((idx, future))
# Process remaining futures
while futures:
processed_idx, future = futures.popleft()
embeddings[processed_idx] = future.result()
return embeddings
```
### 3rd Party Face Detector
You can create [`Face`](https://verifeye-docs.realeyes.ai/../api-reference/python.md#face) objects from a 3rd party face detector by providing the image and landmarks:
```python
face = fvl.Face(
image=rgb_image,
landmarks=[
fvl.Point2d(x=100.0, y=120.0), # left eye
fvl.Point2d(x=160.0, y=120.0), # right eye
fvl.Point2d(x=130.0, y=155.0), # nose tip
fvl.Point2d(x=105.0, y=180.0), # left mouth corner
fvl.Point2d(x=155.0, y=180.0), # right mouth corner
],
bbox=fvl.BoundingBox(x=80, y=90, width=100, height=120),
confidence=0.95
)
embedding = verifier.embed_face(face)
```
### Detection Quality
Check the quality of a detection before embedding:
```python
for face in faces:
if face.detection_quality() == fvl.DetectionQuality.Good:
embedding = verifier.embed_face(face)
```
## Next Steps
- [Python API Reference](https://verifeye-docs.realeyes.ai/../api-reference/python.md)
Index
https://verifeye-docs.realeyes.ai/native-sdk/face-verification/
# Face Verification Library
Welcome to the Face Verification Library documentation!
## Contents:
- [Overview](https://verifeye-docs.realeyes.ai/overview.md)
- [C++ API](https://verifeye-docs.realeyes.ai/api-reference/cpp.md)
- [C API](https://verifeye-docs.realeyes.ai/api-reference/c.md)
- [Python API](https://verifeye-docs.realeyes.ai/api-reference/python.md)
- [.NET API](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md)
Overview
https://verifeye-docs.realeyes.ai/native-sdk/face-verification/overview/
# Face Verification Library
## Introduction
The Face Verification Library is a portable C++ library for face verification, designed for real-time processing on client devices (mobile and desktop).
The SDK provides wrappers in the following languages:
- C
- Python
- C# (.NET)
## Features
- Face detection
- Face embedding extraction for verification
- Embedding comparison with similarity scoring
- Async API with both `std::future` and callback interfaces
- Configurable concurrency
- Support for 3rd party face detectors
- Cross-platform (desktop, mobile)
## Supported Platforms
### Hardware Requirements
- **CPU:** Any modern 64-bit capable CPU (x86-64 with AVX, ARM8)
- **GPU:** No special requirement
- **RAM:** 2 GB of available RAM required
- **Camera:** Minimum resolution: 640x480
### Software Requirements
The SDK is regularly tested on the following operating systems:
| Platform | Version |
|----------|---------|
| Windows | 11 |
| Linux | Ubuntu 24.04 |
| macOS | 15 Sequoia |
| iOS | 18 |
| Android | 27 |
### Platform / Architecture Support
| Platform | Architecture | Status |
|----------|-------------|--------|
| Linux | x86_64, ARM64 | Supported |
| Windows | x86_64 | Supported |
| macOS | ARM64 | Supported |
| iOS | ARM64 | Supported |
| Android | ARM64 | Supported |
## Available APIs
- **C++** - Core native API
- **C** - C-compatible API for FFI integration
- **Python** - Python bindings via pybind11
- **.NET** - C# bindings with async/await support
## API Comparison
**Create verifier**
- C++: [`FaceVerifier()`](https://verifeye-docs.realeyes.ai/api-reference/cpp.md#faceverifier)
- C: [`fvl_face_verifier_new()`](https://verifeye-docs.realeyes.ai/api-reference/c.md#fvl_face_verifier_new)
- Python: [`FaceVerifier()`](https://verifeye-docs.realeyes.ai/api-reference/python.md#faceverifier)
- .NET: [`FaceVerifier()`](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md#faceverifier)
**Detect faces**
- C++: [`detectFaces()`](https://verifeye-docs.realeyes.ai/api-reference/cpp.md#detectfaces-future)
- C: [`fvl_face_verifier_detect_faces()`](https://verifeye-docs.realeyes.ai/api-reference/c.md#fvl_face_verifier_detect_faces)
- Python: [`detect_faces()`](https://verifeye-docs.realeyes.ai/api-reference/python.md#detect_faces)
- .NET: [`DetectFacesAsync()`](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md#detectfacesasync)
**Embed face**
- C++: [`embedFace()`](https://verifeye-docs.realeyes.ai/api-reference/cpp.md#embedface-future)
- C: [`fvl_face_verifier_embed_face()`](https://verifeye-docs.realeyes.ai/api-reference/c.md#fvl_face_verifier_embed_face)
- Python: [`embed_face()`](https://verifeye-docs.realeyes.ai/api-reference/python.md#embed_face)
- .NET: [`EmbedFaceAsync()`](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md#embedfaceasync)
**Compare faces**
- C++: [`compareFaces()`](https://verifeye-docs.realeyes.ai/api-reference/cpp.md#comparefaces)
- C: [`fvl_face_verifier_compare_faces()`](https://verifeye-docs.realeyes.ai/api-reference/c.md#fvl_face_verifier_compare_faces)
- Python: [`compare_faces()`](https://verifeye-docs.realeyes.ai/api-reference/python.md#compare_faces)
- .NET: [`CompareFaces()`](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md#comparefaces)
**Get model name**
- C++: [`getModelName()`](https://verifeye-docs.realeyes.ai/api-reference/cpp.md#getmodelname)
- C: [`fvl_face_verifier_get_model_name()`](https://verifeye-docs.realeyes.ai/api-reference/c.md#fvl_face_verifier_get_model_name)
- Python: [`get_model_name()`](https://verifeye-docs.realeyes.ai/api-reference/python.md#get_model_name)
- .NET: [`ModelName`](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md#properties)
**Get SDK version**
- C++: [`getSDKVersion()`](https://verifeye-docs.realeyes.ai/api-reference/cpp.md#getsdkversion)
- C: [`fvl_face_verifier_get_sdk_version()`](https://verifeye-docs.realeyes.ai/api-reference/c.md#fvl_face_verifier_get_sdk_version)
- Python: [`get_sdk_version_string()`](https://verifeye-docs.realeyes.ai/api-reference/python.md#get_sdk_version_string)
- .NET: [`SdkVersion`](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md#properties)
## Quick Links
### Getting Started
- [C++ Getting Started](https://verifeye-docs.realeyes.ai/getting-started/cpp.md)
- [C Getting Started](https://verifeye-docs.realeyes.ai/getting-started/c.md)
- [Python Getting Started](https://verifeye-docs.realeyes.ai/getting-started/python.md)
- [.NET Getting Started](https://verifeye-docs.realeyes.ai/getting-started/dotnet.md)
### API Reference
- [C++ API Reference](https://verifeye-docs.realeyes.ai/api-reference/cpp.md)
- [C API Reference](https://verifeye-docs.realeyes.ai/api-reference/c.md)
- [Python API Reference](https://verifeye-docs.realeyes.ai/api-reference/python.md)
- [.NET API Reference](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md)
## Quick Examples
### C++
```cpp
#include "faceverifier.h"
#include
#include
#include
int main()
{
fvl::FaceVerifier verifier("model/model.realZ");
cv::Mat image1 = cv::imread("image1.jpg");
cv::Mat image2 = cv::imread("image2.jpg");
std::vector faces1 = verifier.detectFaces({image1.ptr(), image1.cols, image1.rows, static_cast(image1.step1()), fvl::ImageFormat::BGR}).get();
std::vector faces2 = verifier.detectFaces({image2.ptr(), image2.cols, image2.rows, static_cast(image2.step1()), fvl::ImageFormat::BGR}).get();
std::vector> embeddings1, embeddings2;
for (const Face& face: faces1)
embeddings1.push_back(verifier.embedFace(face).get());
for (const Face& face: faces2)
embeddings2.push_back(verifier.embedFace(face).get());
for (size_t i = 0; i < embeddings1.size(); ++i)
for (size_t j = 0; j < embeddings2.size(); ++j)
if (verifier.compare_faces(embeddings1[i], embeddings2[j]).similarity > 0.3) {
fvl::BoundingBox bbox1 = faces1[i].bounding_box();
fvl::BoundingBox bbox2 = faces2[j].bounding_box();
std::cout << "(" << bbox1.x << ", " << bbox1.y << ", " << bbox1.width << ", " << bbox1.height << ") from image 1 and";
std::cout << "(" << bbox2.x << ", " << bbox2.y << ", " << bbox2.width << ", " << bbox2.height << ") from image 2 are the same people";
std::cout << std::endl;
}
return 0;
}
```
### Python
```python
import realeyes.face_verification as fvl
import cv2
verifier = fvl.FaceVerifier('model/model.realZ')
image1 = cv2.imread('image1.jpg')[:, :, ::-1] # opencv reads BGR we need RGB
image2 = cv2.imread('image2.jpg')[:, :, ::-1] # opencv reads BGR we need RGB
faces1 = verifier.detect_faces(image1)
faces2 = verifier.detect_faces(image2)
embeddings1 = [verifier.embed_face(face) for face in faces1]
embeddings2 = [verifier.embed_face(face) for face in faces2]
for i, e1 in enumerate(embeddings1):
for j, e2 in enumerate(embeddings2):
if verifier.compare_faces(e1, e2).similarity > 0.3:
print(f'{faces1[i]} from image 1 and {faces2[j]} from image 2 are the same person!')
```
### C#
```csharp
using Realeyes.FaceVerification;
using OpenCvSharp;
using var verifier = new FaceVerifier("model/model.realZ");
using var image1 = Cv2.ImRead("image1.jpg");
using var image2 = Cv2.ImRead("image2.jpg");
// Convert OpenCV Mat to byte array
var imageData1 = image1.ToBytes();
var imageData2 = image2.ToBytes();
var header1 = new ImageHeader(imageData1, image1.Width, image1.Height,
image1.Width * image1.Channels(), ImageFormat.BGR);
var header2 = new ImageHeader(imageData2, image2.Width, image2.Height,
image2.Width * image2.Channels(), ImageFormat.BGR);
// Detect faces in parallel
var detectTask1 = verifier.DetectFacesAsync(header1);
var detectTask2 = verifier.DetectFacesAsync(header2);
using var faces1 = await detectTask1;
using var faces2 = await detectTask2;
// Embed all faces in parallel
var embeddingTasks = new List>();
foreach (var face in faces1)
embeddingTasks.Add(verifier.EmbedFaceAsync(face));
foreach (var face in faces2)
embeddingTasks.Add(verifier.EmbedFaceAsync(face));
var allEmbeddings = await Task.WhenAll(embeddingTasks);
var embeddings1 = allEmbeddings.Take(faces1.Count).ToArray();
var embeddings2 = allEmbeddings.Skip(faces1.Count).ToArray();
// Compare embeddings
for (int i = 0; i < embeddings1.Length; i++)
{
for (int j = 0; j < embeddings2.Length; j++)
{
var match = verifier.CompareFaces(embeddings1[i], embeddings2[j]);
if (match.Similarity > 0.3f)
{
var bbox1 = faces1[i].BoundingBox;
var bbox2 = faces2[j].BoundingBox;
Console.WriteLine($"({bbox1.X}, {bbox1.Y}, {bbox1.Width}, {bbox1.Height}) from image 1 and " +
$"({bbox2.X}, {bbox2.Y}, {bbox2.Width}, {bbox2.Height}) from image 2 are the same person!");
}
}
}
```
## Results
The **Face** objects consist of the following members:
- **bounding_box:** Bounding box of the detected face (left, top, width, height).
- **confidence:** Confidence of the detection ([0,1] — higher is better).
- **landmarks:** 5 landmarks from the face:
1. Left eye
2. Right eye
3. Nose (tip)
4. Left mouth corner
5. Right mouth corner

## 3rd Party Face Detector
It is possible to calculate the embedding of a face which was detected with a different library. You can create a **Face** object by specifying the source image and the landmarks.
## Dependencies
The public C++ API hides all the implementation details from the user, and it only depends on the C++17 Standard Library. It also provides a binary compatible interface, making it possible to change the underlying implementation without the need of recompilation of the user code.
## Release Notes
- **Version 1.5.0 (15 Dec 2025)**
- Improved performance on ARM CPUs
- Cleaner .NET API
- New public C API
- **Version 1.4.0 (7 Feb 2024)**
- Experimental .NET support
- **Version 1.3.0 (9 Jun 2023)**
- Add model config version 2 support
- **Version 1.2.0 (9 Jun 2023)**
- Add support for AES encryption
- **Version 1.1.0 (3 Apr 2023)**
- Add support for 3rd party face detectors
- **Version 1.0.0 (1 Mar 2023)**
- Initial release
## 3rd Party Licenses
While the SDK is released under a proprietary license, the following open-source projects were used in it with their respective licenses:
| Library | License |
|---------|---------|
| [OpenCV](https://opencv.org/license/) | 3-clause BSD |
| [TensorFlow](https://github.com/tensorflow/tensorflow/blob/master/LICENSE) | Apache License 2.0 |
| [Protobuf](https://github.com/protocolbuffers/protobuf/blob/master/LICENSE) | 3-clause BSD |
| [zlib](https://www.zlib.net/zlib_license.html) | zlib License |
| [minizip-ng](https://github.com/zlib-ng/minizip-ng/blob/master/LICENSE) | zlib License |
| [stlab](https://github.com/stlab/libraries/blob/main/LICENSE) | Boost Software License 1.0 |
| [docopt.cpp](https://github.com/docopt/docopt.cpp/blob/master/LICENSE-MIT) | MIT License |
| [pybind11](https://github.com/pybind/pybind11/blob/master/LICENSE) | 3-clause BSD |
| [fmtlib](https://github.com/fmtlib/fmt/blob/master/LICENSE.rst) | MIT License |
## License
Proprietary - Realeyes Data Services Ltd.
Index
https://verifeye-docs.realeyes.ai/native-sdk/
# Native SDK
High-performance native libraries for cross-platform application development across Windows, Linux, macOS, iOS, and Android.
## Overview
The VerifEye Native SDK provides C++ libraries for building high-performance biometric verification applications. Our SDK is optimized for speed, accuracy, and cross-platform compatibility.
## Available Features
- **Face Verification** - Face detection, embedding extraction, and face comparison
- **Liveness Detection** - Detect live faces and prevent spoofing attacks
- **Demographic Estimation** - Age and gender estimation from facial images
- **Face Recognition** - Face recognition and duplicate detection
---
## Key Features
- **Native Performance** - Optimized C++ code for maximum speed
- **Cross-Platform** - Windows, Linux, macOS, iOS, Android
- **Offline Capable** - Works without internet connection
- **Low Latency** - Sub-100ms processing times
- **Small Footprint** - Minimal memory and storage requirements
- **Thread-Safe** - Concurrent processing support
---
## Supported Platforms
| Platform | Architecture | Minimum Version |
|----------|-------------|-----------------|
| **Windows** | x64, ARM64 | Windows 10+ |
| **Linux** | x64, ARM64 | Ubuntu 18.04+, CentOS 7+ |
| **macOS** | x64, ARM64 (M1/M2) | macOS 10.15+ |
| **iOS** | ARM64 | iOS 12.0+ |
| **Android** | ARM64, ARMv7 | Android 6.0+ (API 23+) |
---
## Prerequisites
- C++17 compatible compiler
- CMake 3.15 or higher
- OpenCV 4.x (optional, for image processing)
- Platform-specific build tools
---
## Installation
The Native SDK is available for download from the [VerifEye Developer Console](https://verifeye-console.realeyes.ai/).
### Steps to Get the SDK:
1. Log in to the [VerifEye Developer Console](https://verifeye-console.realeyes.ai/)
2. Navigate to the **SDKs** or **Model Downloads** section
3. Request access to the Native SDK (if not already enabled)
4. Download the SDK package for your platform
5. Follow the platform-specific installation instructions included in the package
---
## Documentation
For detailed documentation, API reference, and code examples, please refer to the documentation included with the SDK package.
---
*Last updated: 2026-01-27*
C
https://verifeye-docs.realeyes.ai/native-sdk/liveness-detection/api-reference/c/
# C API Reference
The C API provides a stable ABI for FFI (Foreign Function Interface) integration with other languages.
## Header
```c
#include
```
---
## Opaque Types
```c
typedef struct LLLivenessChecker LLLivenessChecker;
typedef struct LLFace LLFace;
```
These are opaque handles. Use the provided functions to interact with them.
---
## Enums
### LLDetectionQuality
```c
typedef enum LLDetectionQuality {
LLDetectionQualityGood = 0, // No issues detected
LLDetectionQualityBadQuality = 1, // Bad quality
LLDetectionQualityMaybeRolled = 2 // Face maybe rolled
} LLDetectionQuality;
```
### LLImageFormat
```c
typedef enum LLImageFormat {
LLImageFormatGrayscale = 0, // 8-bit grayscale
LLImageFormatRGB = 1, // 24-bit RGB
LLImageFormatRGBA = 2, // 32-bit RGBA
LLImageFormatBGR = 3, // 24-bit BGR
LLImageFormatBGRA = 4 // 32-bit BGRA
} LLImageFormat;
```
---
## Structs
### LLPoint2d
```c
typedef struct LLPoint2d {
float x; // X coordinate
float y; // Y coordinate
} LLPoint2d;
```
### LLPoint2dArray
```c
typedef struct LLPoint2dArray {
int count; // Number of points
LLPoint2d* points; // Array of points
} LLPoint2dArray;
```
### LLBoundingBox
```c
typedef struct LLBoundingBox {
int x; // Left edge
int y; // Top edge
int width; // Width in pixels
int height; // Height in pixels
} LLBoundingBox;
```
### LLImageHeader
```c
typedef struct LLImageHeader {
const uint8_t* data; // Pointer to pixel data (non-owning)
int width; // Width in pixels
int height; // Height in pixels
int stride; // Bytes per row
LLImageFormat format; // Pixel format
} LLImageHeader;
```
### LLCheckResult
```c
typedef struct LLCheckResult {
float score; // Liveness score (0.0-1.0)
bool is_live; // true if classified as live
} LLCheckResult;
```
### LLVersion
```c
typedef struct LLVersion {
int major;
int minor;
int patch;
} LLVersion;
```
### LLFaceArray
```c
typedef struct LLFaceArray {
int count; // Number of faces
LLFace** faces; // Array of face pointers
} LLFaceArray;
```
---
## Callback Types
### LLDetectFacesCallback
```c
typedef void (*LLDetectFacesCallback)(
void* user_data,
LLFaceArray* faces,
const char* error_msg
);
```
Called when face detection completes.
| Parameter | Description |
|-----------|-------------|
| `user_data` | User data passed to detection function |
| `faces` | Detected faces (valid only during callback) |
| `error_msg` | Error message if failed, NULL on success (valid only during callback, no need to free) |
**Important:** The `faces` array, its contents, and `error_msg` are only valid during the callback. Copy any data you need to retain.
### LLCheckImageCallback
```c
typedef void (*LLCheckImageCallback)(
void* user_data,
LLCheckResult* result,
const char* error_msg
);
```
Called when liveness check completes.
| Parameter | Description |
|-----------|-------------|
| `user_data` | User data passed to check function |
| `result` | Liveness result (valid only during callback) |
| `error_msg` | Error message if failed, NULL on success (valid only during callback, no need to free) |
**Important:** The `result` struct and `error_msg` are only valid during the callback. Copy any data you need to retain.
---
## LivenessChecker Functions
### ll_liveness_checker_new
```c
LLLivenessChecker* ll_liveness_checker_new(
const char* model_file,
int max_concurrency,
char** errorMessage
);
```
Creates a new LivenessChecker instance.
| Parameter | Type | Description |
|-----------|------|-------------|
| `model_file` | `const char*` | Path to `.realZ` model file |
| `max_concurrency` | `int` | Max concurrent operations (0 = auto) |
| `errorMessage` | `char**` | Output: error message on failure |
**Returns:** Pointer to new instance, or NULL on failure
**Memory:** Caller must free `*errorMessage` with `free()` if set
---
### ll_liveness_checker_free
```c
void ll_liveness_checker_free(LLLivenessChecker* checker);
```
Frees a LivenessChecker instance.
| Parameter | Type | Description |
|-----------|------|-------------|
| `checker` | `LLLivenessChecker*` | Instance to free |
---
### ll_liveness_checker_detect_faces
```c
void ll_liveness_checker_detect_faces(
LLLivenessChecker* checker,
const LLImageHeader* image_header,
LLDetectFacesCallback callback,
void* user_data
);
```
Detects faces in an image asynchronously.
| Parameter | Type | Description |
|-----------|------|-------------|
| `checker` | [`LLLivenessChecker`](#opaque-types)`*` | LivenessChecker instance |
| `image_header` | `const `[`LLImageHeader`](#llimageheader)`*` | Image descriptor |
| `callback` | [`LLDetectFacesCallback`](#lldetectfacescallback) | Callback function |
| `user_data` | `void*` | User data passed to callback |
**Notes:**
- Non-blocking; callback is invoked when complete
- Image data is copied internally
---
### ll_liveness_checker_check_image
```c
void ll_liveness_checker_check_image(
LLLivenessChecker* checker,
const LLFace* face,
LLCheckImageCallback callback,
void* user_data
);
```
Performs liveness check on a face asynchronously.
| Parameter | Type | Description |
|-----------|------|-------------|
| `checker` | [`LLLivenessChecker`](#opaque-types)`*` | LivenessChecker instance |
| `face` | `const `[`LLFace`](#opaque-types)`*` | Face to check |
| `callback` | [`LLCheckImageCallback`](#llcheckimagecallback) | Callback function |
| `user_data` | `void*` | User data passed to callback |
---
### ll_liveness_checker_get_concurrent_calculations
```c
int ll_liveness_checker_get_concurrent_calculations(
const LLLivenessChecker* checker
);
```
**Returns:** Approximate number of operations in flight
---
### ll_liveness_checker_get_model_name
```c
char* ll_liveness_checker_get_model_name(
const LLLivenessChecker* checker
);
```
**Returns:** Model name string (caller must `free()`)
---
### ll_liveness_checker_get_sdk_version
```c
LLVersion ll_liveness_checker_get_sdk_version(void);
```
**Returns:** SDK version as [`LLVersion`](#llversion) struct
---
### ll_liveness_checker_get_sdk_version_string
```c
char* ll_liveness_checker_get_sdk_version_string(void);
```
**Returns:** SDK version string (caller must `free()`)
---
## Face Functions
### ll_face_new
```c
LLFace* ll_face_new(
const LLImageHeader* image_header,
const LLPoint2d* landmarks,
int num_landmarks,
const LLBoundingBox* bbox,
float confidence,
char** errorMessage
);
```
Creates a Face from external detection results.
| Parameter | Type | Description |
|-----------|------|-------------|
| `image_header` | `const `[`LLImageHeader`](#llimageheader)`*` | Image containing face |
| `landmarks` | `const `[`LLPoint2d`](#llpoint2d)`*` | Array of landmarks |
| `num_landmarks` | `int` | Number of landmarks (typically 5) |
| `bbox` | `const `[`LLBoundingBox`](#llboundingbox)`*` | Face bounding box |
| `confidence` | `float` | Detection confidence |
| `errorMessage` | `char**` | Output: error message on failure |
**Returns:** Pointer to new [`LLFace`](#opaque-types), or NULL on failure
**Landmark Order:**
1. Left eye center
2. Right eye center
3. Nose tip
4. Left mouth corner
5. Right mouth corner
---
### ll_face_copy
```c
LLFace* ll_face_copy(const LLFace* other);
```
Creates a copy of a Face.
| Parameter | Type | Description |
|-----------|------|-------------|
| `other` | `const LLFace*` | Face to copy |
**Returns:** Pointer to new [`LLFace`](#opaque-types) copy, or NULL on failure
**Important:** Use this to retain faces from detection callbacks (see [`LLDetectFacesCallback`](#lldetectfacescallback)).
---
### ll_face_free
```c
void ll_face_free(LLFace* face);
```
Frees a Face instance.
| Parameter | Type | Description |
|-----------|------|-------------|
| `face` | `LLFace*` | Face to free |
---
### ll_face_detection_quality
```c
LLDetectionQuality ll_face_detection_quality(const LLFace* face);
```
**Returns:** [`LLDetectionQuality`](#lldetectionquality) - Detection quality of the face
---
### ll_face_bounding_box
```c
LLBoundingBox ll_face_bounding_box(const LLFace* face);
```
**Returns:** [`LLBoundingBox`](#llboundingbox) - Bounding box of the face
---
### ll_face_confidence
```c
float ll_face_confidence(const LLFace* face);
```
**Returns:** Detection confidence (0.0-1.0)
---
### ll_face_landmarks
```c
LLPoint2dArray* ll_face_landmarks(const LLFace* face);
```
**Returns:** Pointer to [`LLPoint2dArray`](#llpoint2darray) landmarks array (caller must `free()`)
---
## Memory Management Summary
| Function Returns | Must Free? | How |
|------------------|------------|-----|
| [`ll_liveness_checker_new()`](#ll_liveness_checker_new) | Yes | [`ll_liveness_checker_free()`](#ll_liveness_checker_free) |
| [`ll_face_new()`](#ll_face_new) | Yes | [`ll_face_free()`](#ll_face_free) |
| [`ll_face_copy()`](#ll_face_copy) | Yes | [`ll_face_free()`](#ll_face_free) |
| [`ll_liveness_checker_get_model_name()`](#ll_liveness_checker_get_model_name) | Yes | `free()` |
| [`ll_liveness_checker_get_sdk_version_string()`](#ll_liveness_checker_get_sdk_version_string) | Yes | `free()` |
| [`ll_face_landmarks()`](#ll_face_landmarks) | Yes | `free()` |
| `errorMessage` output parameter | Yes | `free()` |
| Callback `faces` parameter | No | Valid only during callback |
| Callback `result` parameter | No | Valid only during callback |
| Callback `error_msg` parameter | No | Valid only during callback |
Cpp
https://verifeye-docs.realeyes.ai/native-sdk/liveness-detection/api-reference/cpp/
# C++ API Reference
## Namespace
```cpp
namespace ll { ... }
```
All public types are in the `ll` namespace.
## Headers
```cpp
#include // Main API (includes types.h)
#include // Data types only
```
---
## Classes
### LivenessChecker
Main entry point for face detection and liveness checking operations.
#### Constructor
```cpp
LivenessChecker(const std::string& modelFile, int maxConcurrency = 0);
```
Creates a new LivenessChecker instance.
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `modelFile` | `const std::string&` | Path to the `.realZ` model file | Required |
| `maxConcurrency` | `int` | Maximum concurrent operations (0 = auto) | `0` |
**Throws:** `std::runtime_error` - If model file cannot be loaded
#### Destructor
```cpp
~LivenessChecker();
```
Releases all resources. Waits for pending operations to complete.
---
#### detectFaces (Future)
```cpp
std::future> detectFaces(const ImageHeader& imageHeader);
```
Detects faces in an image asynchronously.
| Parameter | Type | Description |
|-----------|------|-------------|
| `imageHeader` | `const `[`ImageHeader`](#imageheader)`&` | Image descriptor |
**Returns:** `std::future>` - Future resolving to detected faces
**Notes:**
- Non-blocking; multiple calls can overlap
- Image data is copied internally; safe to release after call returns
---
#### detectFaces (Callback)
```cpp
void detectFaces(const ImageHeader& imageHeader,
std::function>)> callback);
```
Detects faces with callback notification.
| Parameter | Type | Description |
|-----------|------|-------------|
| `imageHeader` | `const `[`ImageHeader`](#imageheader)`&` | Image descriptor |
| `callback` | `std::function>)>` | Callback function |
---
#### checkImage (Future)
```cpp
std::future checkImage(const Face& face);
```
Performs liveness check on a detected face.
| Parameter | Type | Description |
|-----------|------|-------------|
| `face` | `const `[`Face`](#face)`&` | Face to check |
**Returns:** `std::future<`[`CheckResult`](#checkresult)`>` - Future resolving to liveness result
---
#### checkImage (Callback)
```cpp
void checkImage(const Face& face,
std::function)> callback);
```
Performs liveness check with callback notification.
| Parameter | Type | Description |
|-----------|------|-------------|
| `face` | `const `[`Face`](#face)`&` | Face to check |
| `callback` | `std::function)>` | Callback function |
---
#### getConcurrentCalculations
```cpp
int getConcurrentCalculations() const;
```
**Returns:** Approximate number of operations currently in flight
---
#### getModelName
```cpp
std::string getModelName() const;
```
**Returns:** Name/version string of the loaded model
---
#### getSDKVersion (Static)
```cpp
static Version getSDKVersion();
```
**Returns:** SDK version as a [`Version`](#version) struct
---
#### getSDKVersionString (Static)
```cpp
static std::string getSDKVersionString();
```
**Returns:** SDK version as a formatted string (e.g., "1.0.0")
---
### Face
Represents a detected face with image data, landmarks, and metadata.
#### Constructor
```cpp
Face(const ImageHeader& imageHeader,
const std::vector& landmarks,
const BoundingBox& bbox,
float confidence = 0.0f);
```
Creates a Face from external detection results (e.g., third-party detector).
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `imageHeader` | `const `[`ImageHeader`](#imageheader)`&` | Image containing the face | Required |
| `landmarks` | `const std::vector<`[`Point2d`](#point2d)`>&` | 5 facial landmarks | Required |
| `bbox` | `const `[`BoundingBox`](#boundingbox)`&` | Face bounding box | Required |
| `confidence` | `float` | Detection confidence (0.0-1.0) | `0.0f` |
**Landmark Order:**
1. Left eye center
2. Right eye center
3. Nose tip
4. Left mouth corner
5. Right mouth corner
#### Destructor
```cpp
~Face();
```
---
#### detectionQuality
```cpp
DetectionQuality detectionQuality() const;
```
**Returns:** [`DetectionQuality`](#detectionquality) - Quality assessment of the detection
---
#### boundingBox
```cpp
BoundingBox boundingBox() const;
```
**Returns:** [`BoundingBox`](#boundingbox) - Bounding box of the face
---
#### confidence
```cpp
float confidence() const;
```
**Returns:** Detection confidence score (0.0-1.0)
---
#### landmarks
```cpp
std::vector landmarks() const;
```
**Returns:** Vector of 5 [`Point2d`](#point2d) facial landmark points
---
## Types
### ImageHeader
```cpp
struct ImageHeader {
const uint8_t* data; // Pointer to pixel data (non-owning)
int width; // Width in pixels
int height; // Height in pixels
int stride; // Bytes per row
ImageFormat format; // Pixel format
};
```
**Notes:**
- `data` is a non-owning pointer; caller must ensure data remains valid
- `stride` may be greater than `width * bytesPerPixel` due to padding
---
### ImageFormat
```cpp
enum class ImageFormat {
Grayscale = 0, // 8-bit grayscale (1 byte/pixel)
RGB = 1, // 24-bit RGB (3 bytes/pixel)
RGBA = 2, // 32-bit RGBA (4 bytes/pixel)
BGR = 3, // 24-bit BGR (3 bytes/pixel)
BGRA = 4 // 32-bit BGRA (4 bytes/pixel)
};
```
---
### Point2d
```cpp
struct Point2d {
float x; // X coordinate
float y; // Y coordinate
};
```
---
### BoundingBox
```cpp
struct BoundingBox {
int x; // Left edge (pixels)
int y; // Top edge (pixels)
int width; // Width (pixels)
int height; // Height (pixels)
};
```
---
### CheckResult
```cpp
struct CheckResult {
float score; // Liveness score (0.0-1.0)
bool is_live; // true if classified as live
};
```
---
### Version
```cpp
struct Version {
int major;
int minor;
int patch;
};
```
---
### DetectionQuality
```cpp
enum class DetectionQuality {
Good = 0, // High-quality detection
BadQuality = 1, // Low-quality (blurry, partial, etc.)
MaybeRolled = 2 // Face may be significantly rotated
};
```
---
### ErrorType
```cpp
struct ErrorType {
std::string errorString; // Human-readable error description
};
```
---
### ResultOrError
```cpp
template
using ResultOrError = std::variant;
```
Type representing either a successful result or an [`ErrorType`](#errortype) in callback interfaces.
**Usage:**
```cpp
void handleResult(ResultOrError result) {
if (auto* checkResult = std::get_if(&result)) {
// Success
std::cout << "Score: " << checkResult->score << std::endl;
} else {
// Error
auto& error = std::get(result);
std::cerr << "Error: " << error.errorString << std::endl;
}
}
```
---
## Thread Safety
- [`LivenessChecker`](#livenesschecker) is thread-safe for all methods
- Multiple [`detectFaces()`](#detectfaces-future) and [`checkImage()`](#checkimage-future) calls can execute concurrently
- [`Face`](#face) objects can be used from any thread but are not internally synchronized
- Image data referenced by [`ImageHeader`](#imageheader) must remain valid for async operations
---
## Exception Safety
| Method | Exceptions |
|--------|------------|
| [`LivenessChecker()`](#livenesschecker) | `std::runtime_error` on model load failure |
| [`detectFaces()`](#detectfaces-future) | None (errors via future/callback) |
| [`checkImage()`](#checkimage-future) | None (errors via future/callback) |
Future-based methods may throw when calling `.get()` if an error occurred.
Dotnet
https://verifeye-docs.realeyes.ai/native-sdk/liveness-detection/api-reference/dotnet/
# .NET API Reference
## Namespace
```csharp
using Realeyes.Liveness;
```
---
## Classes
### LivenessChecker
Main entry point for face detection and liveness checking operations.
**Implements:** `IDisposable`
#### Constructors
```csharp
public LivenessChecker(string modelPath, int maxConcurrency = 0)
```
Creates a new LivenessChecker instance.
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `modelPath` | `string` | Path to `.realZ` model file | Required |
| `maxConcurrency` | `int` | Max concurrent operations (0 = auto) | `0` |
**Throws:**
- `ArgumentNullException` - If `modelPath` is null or empty
- [`LivenessException`](#livenessexception) - If model loading fails
---
#### DetectFacesAsync
```csharp
public Task DetectFacesAsync(ImageHeader imageHeader)
```
Detects faces in an image asynchronously.
| Parameter | Type | Description |
|-----------|------|-------------|
| `imageHeader` | [`ImageHeader`](#imageheader) | Image to process |
**Returns:** `Task<`[`FaceList`](#facelist)`>` - Disposable collection of detected faces
**Throws:** [`LivenessException`](#livenessexception) - If detection fails
---
#### CheckImageAsync
```csharp
public Task CheckImageAsync(Face face)
```
Performs liveness check on a detected face asynchronously.
| Parameter | Type | Description |
|-----------|------|-------------|
| `face` | [`Face`](#face) | Face to check |
**Returns:** `Task<`[`CheckResult`](#checkresult)`>` - Liveness check result
**Throws:**
- `ArgumentNullException` - If `face` is null
- [`LivenessException`](#livenessexception) - If liveness check fails
---
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| `ConcurrentCalculations` | `int` | Number of operations currently in flight |
| `ModelName` | `string` | Name/version of loaded model |
#### Static Properties
| Property | Type | Description |
|----------|------|-------------|
| `SdkVersion` | [`Version`](#version) | SDK version as struct |
| `SdkVersionString` | `string` | SDK version as formatted string |
---
#### Dispose
```csharp
public void Dispose()
```
Releases all resources. Call when done with the checker.
---
### Face
Represents a detected face with landmarks, bounding box, and quality information.
**Implements:** `IDisposable`
#### Constructors
```csharp
public Face(
ImageHeader imageHeader,
Point2d[] landmarks,
BoundingBox boundingBox,
float confidence = 0.0f
)
```
Creates a Face from third-party face detector results.
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `imageHeader` | [`ImageHeader`](#imageheader) | Image containing the face | Required |
| `landmarks` | [`Point2d`](#point2d)`[]` | 5 facial landmarks | Required |
| `boundingBox` | [`BoundingBox`](#boundingbox) | Face bounding box | Required |
| `confidence` | `float` | Detection confidence | `0.0f` |
**Landmark Order:**
1. Left eye center
2. Right eye center
3. Nose tip
4. Left mouth corner
5. Right mouth corner
**Throws:**
- `ArgumentNullException` - If `landmarks` is null
- [`LivenessException`](#livenessexception) - If face creation fails
---
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| `DetectionQuality` | [`DetectionQuality`](#detectionquality) | Quality assessment |
| `BoundingBox` | [`BoundingBox`](#boundingbox) | Face bounding box |
| `Confidence` | `float` | Detection confidence (0.0-1.0) |
---
#### GetLandmarks
```csharp
public Point2d[] GetLandmarks()
```
**Returns:** Array of 5 [`Point2d`](#point2d) facial landmark points
---
#### Clone
```csharp
public Face Clone()
```
Creates a copy of this face.
**Returns:** New [`Face`](#face) instance with same data
---
#### Dispose
```csharp
public void Dispose()
```
Releases native resources.
---
### FaceList
Disposable collection of [`Face`](#face) objects.
**Inherits:** `List`
**Implements:** `IDisposable`, `IAsyncDisposable`
#### Dispose
```csharp
public void Dispose()
```
Disposes all [`Face`](#face) objects in the collection.
#### DisposeAsync
```csharp
public ValueTask DisposeAsync()
```
Disposes all [`Face`](#face) objects asynchronously.
---
### LivenessException
Exception thrown when Liveness Library operations fail.
**Inherits:** `Exception`
#### Constructors
```csharp
public LivenessException()
public LivenessException(string message)
public LivenessException(string message, Exception innerException)
```
---
## Enums
### DetectionQuality
```csharp
public enum DetectionQuality
{
Good = 0, // No issues detected
BadQuality = 1, // Bad quality detected
MaybeRolled = 2 // Face maybe rolled, results may be incorrect
}
```
### ImageFormat
```csharp
public enum ImageFormat
{
Grayscale = 0, // 8-bit grayscale
RGB = 1, // 24-bit RGB
RGBA = 2, // 32-bit RGBA
BGR = 3, // 24-bit BGR
BGRA = 4 // 32-bit BGRA
}
```
---
## Record Structs
### Point2d
```csharp
public readonly record struct Point2d(float X, float Y);
```
2D point for landmark coordinates.
### BoundingBox
```csharp
public readonly record struct BoundingBox(int X, int Y, int Width, int Height)
{
public int Right => X + Width;
public int Bottom => Y + Height;
public int Area => Width * Height;
}
```
Bounding box for face region.
### ImageHeader
```csharp
public readonly record struct ImageHeader
{
public ImageHeader(byte[] data, int width, int height, int stride, ImageFormat format);
public byte[] Data { get; init; }
public int Width { get; init; }
public int Height { get; init; }
public int Stride { get; init; }
public ImageFormat Format { get; init; }
}
```
Image descriptor for passing image data.
**Throws:** `ArgumentNullException`, `ArgumentOutOfRangeException` on invalid parameters
### CheckResult
```csharp
public readonly record struct CheckResult(float Score, bool IsLive);
```
Result of liveness check.
### Version
```csharp
public readonly record struct Version(int Major, int Minor, int Patch)
{
public override string ToString() => $"{Major}.{Minor}.{Patch}";
}
```
Semantic version number.
---
## Usage Examples
### Basic Usage
```csharp
using Realeyes.Liveness;
// Create checker
using var checker = new LivenessChecker("model.realZ");
Console.WriteLine($"SDK: {LivenessChecker.SdkVersionString}");
// Prepare image
var imageData = File.ReadAllBytes("photo.rgb");
var header = new ImageHeader(imageData, 640, 480, 640 * 3, ImageFormat.RGB);
// Detect and check
using var faces = await checker.DetectFacesAsync(header);
foreach (var face in faces)
{
if (face.DetectionQuality == DetectionQuality.Good)
{
var result = await checker.CheckImageAsync(face);
Console.WriteLine($"Live: {result.IsLive}, Score: {result.Score:F3}");
}
}
```
### Third-Party Face Detector
```csharp
var landmarks = new Point2d[]
{
new(100f, 120f), // left eye
new(150f, 120f), // right eye
new(125f, 150f), // nose
new(105f, 180f), // left mouth
new(145f, 180f) // right mouth
};
var bbox = new BoundingBox(80, 100, 100, 120);
using var face = new Face(imageHeader, landmarks, bbox, 0.95f);
var result = await checker.CheckImageAsync(face);
```
### Error Handling
```csharp
try
{
using var checker = new LivenessChecker("invalid.realZ");
}
catch (LivenessException ex)
{
Console.WriteLine($"Failed: {ex.Message}");
}
```
### Parallel Processing
```csharp
using var checker = new LivenessChecker("model.realZ", maxConcurrency: 4);
var tasks = images.Select(async img =>
{
using var faces = await checker.DetectFacesAsync(img);
return faces.Where(f => f.DetectionQuality == DetectionQuality.Good)
.Select(f => checker.CheckImageAsync(f));
});
await Task.WhenAll(tasks.SelectMany(t => t.Result));
```
---
## Thread Safety
- [`LivenessChecker`](#livenesschecker) is thread-safe for all async methods
- Multiple [`DetectFacesAsync`](#detectfacesasync) and [`CheckImageAsync`](#checkimageasync) calls can execute concurrently
- [`Face`](#face) objects should not be shared across threads without synchronization
- Always dispose [`FaceList`](#facelist) and [`Face`](#face) objects when done
Python
https://verifeye-docs.realeyes.ai/native-sdk/liveness-detection/api-reference/python/
# Python API Reference
## Module
```python
from realeyes.liveness import (
LivenessChecker,
Face,
CheckResult,
BoundingBox,
Point2d,
DetectionQuality,
get_sdk_version_string
)
```
---
## Classes
### LivenessChecker
Main entry point for face detection and liveness checking.
#### Constructor
```python
LivenessChecker(model_file: str, max_concurrency: int = 0) -> None
```
Creates a new LivenessChecker instance.
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `model_file` | `str` | Path to `.realZ` model file | Required |
| `max_concurrency` | `int` | Max concurrent operations (0 = auto) | `0` |
**Raises:** `RuntimeError` - If model file cannot be loaded
---
#### detect_faces
```python
def detect_faces(self, image: numpy.ndarray[numpy.uint8]) -> List[Face]
```
Detects faces in an image.
| Parameter | Type | Description |
|-----------|------|-------------|
| `image` | `numpy.ndarray[uint8]` | Image in RGB format `[H x W x C]` |
**Returns:** `List[`[`Face`](#face)`]` - List of detected faces
**Notes:**
- Image must be RGB format with shape `(height, width, 3)`
- Image must be C-contiguous (`numpy.ascontiguousarray()` if needed)
---
#### check_image
```python
def check_image(self, face: Face) -> CheckResult
```
Performs liveness check on a detected face.
| Parameter | Type | Description |
|-----------|------|-------------|
| `face` | [`Face`](#face) | Face to check |
**Returns:** [`CheckResult`](#checkresult) - Liveness check result
---
#### get_model_name
```python
def get_model_name(self) -> str
```
**Returns:** Name/version string of the loaded model
---
### Face
Represents a detected face with image data, landmarks, and metadata.
#### Constructor
```python
Face(
image: numpy.ndarray[numpy.uint8],
landmarks: List[Point2d],
bbox: BoundingBox = BoundingBox(0, 0, 0, 0),
confidence: float = 0.0
) -> None
```
Creates a Face from external detection results.
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `image` | `numpy.ndarray[uint8]` | Image in RGB format | Required |
| `landmarks` | `List[`[`Point2d`](#point2d)`]` | 5 facial landmarks | Required |
| `bbox` | [`BoundingBox`](#boundingbox) | Face bounding box | `BoundingBox(0,0,0,0)` |
| `confidence` | `float` | Detection confidence | `0.0` |
**Landmark Order:**
1. Left eye center
2. Right eye center
3. Nose tip
4. Left mouth corner
5. Right mouth corner
---
#### detection_quality
```python
def detection_quality(self) -> DetectionQuality
```
**Returns:** [`DetectionQuality`](#detectionquality) - Quality assessment of the detection
---
#### bounding_box
```python
def bounding_box(self) -> BoundingBox
```
**Returns:** [`BoundingBox`](#boundingbox) - Bounding box of the face
---
#### confidence
```python
def confidence(self) -> float
```
**Returns:** Detection confidence (0.0-1.0)
---
#### landmarks
```python
def landmarks(self) -> List[Point2d]
```
**Returns:** List of 5 [`Point2d`](#point2d) facial landmark points
---
### CheckResult
Result of liveness check (read-only).
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| `score` | `float` | Raw liveness score (0.0-1.0) |
| `is_live` | `bool` | True if classified as live |
---
### BoundingBox
Bounding box for face region.
#### Constructor
```python
BoundingBox(x: int, y: int, width: int, height: int) -> None
```
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| `x` | `int` | Left edge (pixels) |
| `y` | `int` | Top edge (pixels) |
| `width` | `int` | Width (pixels) |
| `height` | `int` | Height (pixels) |
---
### Point2d
2D point for landmark coordinates.
#### Constructor
```python
Point2d(x: float, y: float) -> None
```
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| `x` | `float` | X coordinate |
| `y` | `float` | Y coordinate |
---
## Enums
### DetectionQuality
```python
class DetectionQuality(Enum):
Good = 0 # High-quality detection
BadQuality = 1 # Low-quality (blurry, partial, etc.)
MaybeRolled = 2 # Face may be significantly rotated
```
---
## Functions
### get_sdk_version_string
```python
def get_sdk_version_string() -> str
```
**Returns:** SDK version as formatted string (e.g., "1.0.0")
---
## Module Attributes
### __version__
```python
__version__: str # SDK version string
```
---
## Usage Examples
### Basic Detection and Liveness Check
```python
from realeyes.liveness import LivenessChecker, DetectionQuality
import numpy as np
from PIL import Image
# Load image
image = np.array(Image.open("photo.jpg").convert("RGB"))
# Create checker and process
checker = LivenessChecker("model.realZ")
faces = checker.detect_faces(image)
for face in faces:
if face.detection_quality() == DetectionQuality.Good:
result = checker.check_image(face)
print(f"Score: {result.score:.3f}, Live: {result.is_live}")
```
### Using OpenCV Images
```python
import cv2
import numpy as np
from realeyes.liveness import LivenessChecker
checker = LivenessChecker("model.realZ")
# OpenCV reads as BGR, convert to RGB
bgr_image = cv2.imread("photo.jpg")
rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB)
# Ensure contiguous array
rgb_image = np.ascontiguousarray(rgb_image)
faces = checker.detect_faces(rgb_image)
```
### Third-Party Face Detector
```python
from realeyes.liveness import LivenessChecker, Face, Point2d, BoundingBox
import numpy as np
checker = LivenessChecker("model.realZ")
# Your detector results
landmarks = [
Point2d(100.0, 120.0), # left eye
Point2d(150.0, 120.0), # right eye
Point2d(125.0, 150.0), # nose
Point2d(105.0, 180.0), # left mouth
Point2d(145.0, 180.0), # right mouth
]
bbox = BoundingBox(80, 100, 100, 120)
face = Face(rgb_image, landmarks, bbox, confidence=0.95)
result = checker.check_image(face)
```
---
## Error Handling
```python
from realeyes.liveness import LivenessChecker
try:
checker = LivenessChecker("invalid.realZ")
except RuntimeError as e:
print(f"Failed to load model: {e}")
```
---
## Thread Safety
- [`LivenessChecker`](#livenesschecker) releases the GIL during blocking operations
- Safe to use from multiple threads
- Each thread should ideally use its own [`LivenessChecker`](#livenesschecker) instance for best performance
C
https://verifeye-docs.realeyes.ai/native-sdk/liveness-detection/getting-started/c/
# Getting Started with C API
## Prerequisites
- C99 compatible compiler
- The Liveness Library shared library for your platform
## Installation
### Using Pre-built Package
1. Download the Liveness Library package for your platform.
2. Extract the package:
```
liveness-library/
├── include/
│ └── livenesschecker_c.h
└── lib/
├── libLivenessLibrary.so (Linux)
├── LivenessLibrary.dll (Windows)
└── libLivenessLibrary.dylib (macOS)
```
3. Include the header and link the library.
## Quick Start Example
```c
#include
#include
#include
#include
// Callback context structure
typedef struct {
int completed;
LLFace** faces;
int face_count;
char* error;
} DetectContext;
typedef struct {
int completed;
LLCheckResult result;
char* error;
} CheckContext;
// Detection callback
void on_faces_detected(void* user_data, LLFaceArray* faces, const char* error_msg) {
DetectContext* ctx = (DetectContext*)user_data;
if (error_msg) {
ctx->error = strdup(error_msg);
ctx->completed = 1;
return;
}
// Copy faces (they're only valid during callback)
ctx->face_count = faces->count;
ctx->faces = malloc(sizeof(LLFace*) * faces->count);
for (int i = 0; i < faces->count; i++) {
ctx->faces[i] = ll_face_copy(faces->faces[i]);
}
ctx->completed = 1;
}
// Liveness check callback
void on_liveness_checked(void* user_data, LLCheckResult* result, const char* error_msg) {
CheckContext* ctx = (CheckContext*)user_data;
if (error_msg) {
ctx->error = strdup(error_msg);
ctx->completed = 1;
return;
}
ctx->result = *result;
ctx->completed = 1;
}
int main(int argc, char* argv[]) {
char* error_msg = NULL;
// 1. Create LivenessChecker
LLLivenessChecker* checker = ll_liveness_checker_new("model.realZ", 0, &error_msg);
if (!checker) {
fprintf(stderr, "Failed to create checker: %s\n", error_msg ? error_msg : "Unknown error");
free(error_msg);
return 1;
}
// Print SDK version
char* version = ll_liveness_checker_get_sdk_version_string();
printf("SDK Version: %s\n", version);
free(version);
// 2. Prepare image data
int width = 640;
int height = 480;
int stride = width * 3;
uint8_t* image_data = malloc(stride * height);
// ... fill image_data with actual pixels ...
LLImageHeader header = {
.data = image_data,
.width = width,
.height = height,
.stride = stride,
.format = LLImageFormatRGB
};
// 3. Detect faces
DetectContext detect_ctx = {0};
ll_liveness_checker_detect_faces(checker, &header, on_faces_detected, &detect_ctx);
// Wait for completion (in real code, use proper synchronization)
while (!detect_ctx.completed) {
// Simple busy wait - use condition variables in production
}
if (detect_ctx.error) {
fprintf(stderr, "Detection failed: %s\n", detect_ctx.error);
free(detect_ctx.error);
ll_liveness_checker_free(checker);
free(image_data);
return 1;
}
printf("Detected %d face(s)\n", detect_ctx.face_count);
// 4. Check liveness for each face
for (int i = 0; i < detect_ctx.face_count; i++) {
LLFace* face = detect_ctx.faces[i];
// Get face info
LLDetectionQuality quality = ll_face_detection_quality(face);
if (quality != LLDetectionQualityGood) {
printf("Skipping low-quality detection\n");
ll_face_free(face);
continue;
}
LLBoundingBox bbox = ll_face_bounding_box(face);
printf("Face at (%d, %d) %dx%d\n", bbox.x, bbox.y, bbox.width, bbox.height);
// Check liveness
CheckContext check_ctx = {0};
ll_liveness_checker_check_image(checker, face, on_liveness_checked, &check_ctx);
while (!check_ctx.completed) {
// Wait for completion
}
if (check_ctx.error) {
fprintf(stderr, "Liveness check failed: %s\n", check_ctx.error);
free(check_ctx.error);
} else {
printf("Liveness score: %.3f\n", check_ctx.result.score);
printf("Is live: %s\n", check_ctx.result.is_live ? "Yes" : "No");
}
ll_face_free(face);
}
// 5. Cleanup
free(detect_ctx.faces);
free(image_data);
ll_liveness_checker_free(checker);
return 0;
}
```
## Common Patterns
### Error Handling
The C API uses error output parameters and NULL returns. See [`ll_liveness_checker_new()`](https://verifeye-docs.realeyes.ai/../api-reference/c.md#ll_liveness_checker_new) for details:
```c
char* error_msg = NULL;
LLLivenessChecker* checker = ll_liveness_checker_new("model.realZ", 0, &error_msg);
if (!checker) {
fprintf(stderr, "Error: %s\n", error_msg ? error_msg : "Unknown error");
free(error_msg); // Caller must free error string
return 1;
}
```
### Memory Management
- Always call `*_free()` functions to release resources (e.g., [`ll_liveness_checker_free()`](https://verifeye-docs.realeyes.ai/../api-reference/c.md#ll_liveness_checker_free), [`ll_face_free()`](https://verifeye-docs.realeyes.ai/../api-reference/c.md#ll_face_free))
- Strings returned by the API must be freed with `free()`
- Face objects from callbacks must be copied with [`ll_face_copy()`](https://verifeye-docs.realeyes.ai/../api-reference/c.md#ll_face_copy) if needed beyond the callback
```c
// Free resources
ll_face_free(face);
ll_liveness_checker_free(checker);
// Free returned strings
char* model_name = ll_liveness_checker_get_model_name(checker);
printf("Model: %s\n", model_name);
free(model_name);
// Copy face from callback
void callback(void* data, LLFaceArray* faces, const char* error) {
if (faces && faces->count > 0) {
// Face is only valid during callback - copy it
LLFace* my_face = ll_face_copy(faces->faces[0]);
// ... use my_face later ...
ll_face_free(my_face);
}
}
```
### Using Third-Party Face Detectors
Create an [`LLFace`](https://verifeye-docs.realeyes.ai/../api-reference/c.md#opaque-types) from your own detector results using [`ll_face_new()`](https://verifeye-docs.realeyes.ai/../api-reference/c.md#ll_face_new):
```c
LLPoint2d landmarks[5] = {
{100.0f, 120.0f}, // left eye
{150.0f, 120.0f}, // right eye
{125.0f, 150.0f}, // nose
{105.0f, 180.0f}, // left mouth
{145.0f, 180.0f} // right mouth
};
LLBoundingBox bbox = {80, 100, 100, 120};
char* error_msg = NULL;
LLFace* face = ll_face_new(&header, landmarks, 5, &bbox, 0.95f, &error_msg);
if (!face) {
fprintf(stderr, "Failed to create face: %s\n", error_msg);
free(error_msg);
return;
}
// Use face for liveness check...
ll_face_free(face);
```
### Concurrency Monitoring
```c
int in_flight = ll_liveness_checker_get_concurrent_calculations(checker);
printf("Operations in flight: %d\n", in_flight);
```
## Next Step
- [C API Reference](https://verifeye-docs.realeyes.ai/../api-reference/c.md) - Complete API documentation for [`LLLivenessChecker`](https://verifeye-docs.realeyes.ai/../api-reference/c.md#opaque-types), [`LLFace`](https://verifeye-docs.realeyes.ai/../api-reference/c.md#opaque-types), [`LLImageHeader`](https://verifeye-docs.realeyes.ai/../api-reference/c.md#llimageheader), and more
Cpp
https://verifeye-docs.realeyes.ai/native-sdk/liveness-detection/getting-started/cpp/
# Getting Started with C++ API
## Prerequisites
- C++17 compatible compiler (GCC 7+, Clang 5+, MSVC 2019+)
- CMake 3.15+
## Installation
### Using Pre-built Package
1. Download the Liveness Library package for your platform from the distribution channel.
2. Extract the package to your preferred location:
```
liveness-library/
├── include/
│ ├── livenesschecker.h
│ ├── livenesschecker_c.h
│ └── types.h
└── lib/
├── libLivenessLibrary.so (Linux)
├── LivenessLibrary.dll (Windows)
└── libLivenessLibrary.dylib (macOS)
```
3. Add the include directory and the library to your project.
## Quick Start Example
```cpp
#include
#include
#include
int main() {
try {
// 1. Create LivenessChecker with model file
ll::LivenessChecker checker("model.realZ");
std::cout << "SDK Version: " << ll::LivenessChecker::getSDKVersionString() << std::endl;
std::cout << "Model: " << checker.getModelName() << std::endl;
// 2. Prepare your image data
// (In real code, load from file or camera)
int width = 640;
int height = 480;
int stride = width * 3; // RGB: 3 bytes per pixel
std::vector imageData(stride * height);
// ... fill imageData with actual image pixels ...
ll::ImageHeader header{
imageData.data(),
width,
height,
stride,
ll::ImageFormat::RGB
};
// 3. Detect faces (async with future)
auto detectFuture = checker.detectFaces(header);
std::vector faces = detectFuture.get();
std::cout << "Detected " << faces.size() << " face(s)" << std::endl;
// 4. Check liveness for each face
for (const auto& face : faces) {
// Check detection quality first
if (face.detectionQuality() != ll::DetectionQuality::Good) {
std::cout << "Skipping low-quality detection" << std::endl;
continue;
}
// Get face info
auto bbox = face.boundingBox();
std::cout << "Face at (" << bbox.x << ", " << bbox.y << ") "
<< bbox.width << "x" << bbox.height << std::endl;
// Perform liveness check
auto checkFuture = checker.checkImage(face);
ll::CheckResult result = checkFuture.get();
std::cout << "Liveness score: " << result.score << std::endl;
std::cout << "Is live: " << (result.is_live ? "Yes" : "No") << std::endl;
}
return 0;
}
catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
}
```
## Common Patterns
### Async Operations with Futures
The library provides non-blocking async APIs using [`std::future`](https://en.cppreference.com/w/cpp/thread/future):
```cpp
// Start multiple detections without waiting
auto future1 = checker.detectFaces(image1);
auto future2 = checker.detectFaces(image2);
// Do other work...
// Get results when needed
auto faces1 = future1.get();
auto faces2 = future2.get();
```
### Async Operations with Callbacks
For event-driven architectures, use the callback API with [`ResultOrError`](https://verifeye-docs.realeyes.ai/../api-reference/cpp.md#resultorerror):
```cpp
checker.detectFaces(header, [](ll::ResultOrError> result) {
if (auto* faces = std::get_if>(&result)) {
// Success - process faces
for (const auto& face : *faces) {
std::cout << "Face confidence: " << face.confidence() << std::endl;
}
} else {
// Error
auto& error = std::get(result);
std::cerr << "Detection failed: " << error.errorString << std::endl;
}
});
```
### Using Third-Party Face Detectors
If you have your own face detector, create [`Face`](https://verifeye-docs.realeyes.ai/../api-reference/cpp.md#face) objects manually:
```cpp
// Your detection results
std::vector landmarks = {
{100.0f, 120.0f}, // left eye
{150.0f, 120.0f}, // right eye
{125.0f, 150.0f}, // nose tip
{105.0f, 180.0f}, // left mouth corner
{145.0f, 180.0f} // right mouth corner
};
ll::BoundingBox bbox{80, 100, 100, 120};
float confidence = 0.95f;
// Create Face for liveness checking
ll::Face face(header, landmarks, bbox, confidence);
auto result = checker.checkImage(face).get();
```
### Concurrency Control
Monitor and limit concurrent operations:
```cpp
// Check current in-flight operations
int inFlight = checker.getConcurrentCalculations();
// Implement backpressure
const int maxConcurrent = 4;
while (checker.getConcurrentCalculations() >= maxConcurrent) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
checker.detectFaces(nextFrame);
```
### Error Handling
```cpp
try {
ll::LivenessChecker checker("invalid_model.realZ");
} catch (const std::runtime_error& e) {
std::cerr << "Failed to load model: " << e.what() << std::endl;
}
```
## Next Steps
- [C++ API Reference](https://verifeye-docs.realeyes.ai/../api-reference/cpp.md) - Complete API documentation for [`LivenessChecker`](https://verifeye-docs.realeyes.ai/../api-reference/cpp.md#livenesschecker), [`Face`](https://verifeye-docs.realeyes.ai/../api-reference/cpp.md#face), [`ImageHeader`](https://verifeye-docs.realeyes.ai/../api-reference/cpp.md#imageheader), and more
Dotnet
https://verifeye-docs.realeyes.ai/native-sdk/liveness-detection/getting-started/dotnet/
# Getting Started with .NET API
## Prerequisites
- .NET 8.0+
- Native Liveness Library for your platform
## Installation
### NuGet Package
```bash
dotnet add package Realeyes.Liveness
```
## Quick Start Example
```csharp
using System;
using System.Threading.Tasks;
using Realeyes.Liveness;
class Program
{
static async Task Main(string[] args)
{
// Print SDK version
Console.WriteLine($"SDK Version: {LivenessChecker.SdkVersionString}");
// 1. Create LivenessChecker with model file
using var checker = new LivenessChecker("model.realZ");
Console.WriteLine($"Model: {checker.ModelName}");
// 2. Prepare image data
// Example: Load from file using System.Drawing or ImageSharp
byte[] imageData = LoadImageAsRgbBytes("photo.jpg", out int width, out int height);
int stride = width * 3; // RGB: 3 bytes per pixel
var imageHeader = new ImageHeader(imageData, width, height, stride, ImageFormat.RGB);
// 3. Detect faces asynchronously
using var faces = await checker.DetectFacesAsync(imageHeader);
Console.WriteLine($"Detected {faces.Count} face(s)");
// 4. Check liveness for each face
foreach (var face in faces)
{
// Check detection quality first
if (face.DetectionQuality != DetectionQuality.Good)
{
Console.WriteLine("Skipping low-quality detection");
continue;
}
// Get face info
var bbox = face.BoundingBox;
Console.WriteLine($"Face at ({bbox.X}, {bbox.Y}) {bbox.Width}x{bbox.Height}");
Console.WriteLine($"Confidence: {face.Confidence:F3}");
// Perform liveness check
var result = await checker.CheckImageAsync(face);
Console.WriteLine($"Liveness score: {result.Score:F3}");
Console.WriteLine($"Is live: {result.IsLive}");
}
}
static byte[] LoadImageAsRgbBytes(string path, out int width, out int height)
{
// Example using System.Drawing (Windows) or ImageSharp (cross-platform)
// This is a placeholder - implement based on your image library
throw new NotImplementedException("Implement image loading");
}
}
```
## Common Patterns
### Async/Await
All detection and checking operations are async:
```csharp
using var checker = new LivenessChecker("model.realZ");
// Detect faces
using var faces = await checker.DetectFacesAsync(imageHeader);
// Check liveness
var result = await checker.CheckImageAsync(face);
```
### Resource Management
Use `using` statements or explicitly call [`Dispose()`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#dispose). Both [`LivenessChecker`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#livenesschecker) and [`FaceList`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#facelist) implement `IDisposable`:
```csharp
// Preferred: using statement
using var checker = new LivenessChecker("model.realZ");
using var faces = await checker.DetectFacesAsync(imageHeader);
// Alternative: explicit disposal
var checker = new LivenessChecker("model.realZ");
try
{
var faces = await checker.DetectFacesAsync(imageHeader);
try
{
// Process faces...
}
finally
{
faces.Dispose(); // Disposes all Face objects in the list
}
}
finally
{
checker.Dispose();
}
```
### Error Handling
Handle [`LivenessException`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#livenessexception) for library errors:
```csharp
try
{
using var checker = new LivenessChecker("invalid_model.realZ");
}
catch (LivenessException ex)
{
Console.WriteLine($"Failed to load model: {ex.Message}");
}
catch (ArgumentNullException ex)
{
Console.WriteLine($"Invalid argument: {ex.Message}");
}
```
### Using Third-Party Face Detectors
Create a [`Face`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#face) from your own detector results using [`Point2d`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#point2d) and [`BoundingBox`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#boundingbox):
```csharp
using var checker = new LivenessChecker("model.realZ");
// Your face detector results
var landmarks = new Point2d[]
{
new(100.0f, 120.0f), // left eye
new(150.0f, 120.0f), // right eye
new(125.0f, 150.0f), // nose
new(105.0f, 180.0f), // left mouth
new(145.0f, 180.0f), // right mouth
};
var bbox = new BoundingBox(80, 100, 100, 120);
float confidence = 0.95f;
// Create Face object for liveness checking
using var face = new Face(imageHeader, landmarks, bbox, confidence);
var result = await checker.CheckImageAsync(face);
Console.WriteLine($"Is live: {result.IsLive}");
```
### Processing Video Frames
```csharp
using var checker = new LivenessChecker("model.realZ");
// Process frames from video capture
while (await videoCapture.ReadFrameAsync() is byte[] frameData)
{
var header = new ImageHeader(frameData, width, height, stride, ImageFormat.RGB);
using var faces = await checker.DetectFacesAsync(header);
foreach (var face in faces)
{
if (face.DetectionQuality == DetectionQuality.Good)
{
var result = await checker.CheckImageAsync(face);
// Update UI or process result
await UpdateLivenessDisplay(face.BoundingBox, result);
}
}
}
```
### Concurrency Monitoring
```csharp
// Check operations in flight
int inFlight = checker.ConcurrentCalculations;
Console.WriteLine($"Operations in flight: {inFlight}");
// Implement backpressure
const int maxConcurrent = 4;
while (checker.ConcurrentCalculations >= maxConcurrent)
{
await Task.Delay(10);
}
```
### Parallel Processing
```csharp
using var checker = new LivenessChecker("model.realZ", maxConcurrency: 4);
var imagePaths = Directory.GetFiles("images", "*.jpg");
var tasks = imagePaths.Select(async path =>
{
var imageData = await File.ReadAllBytesAsync(path);
// Assume LoadImage converts to RGB and returns dimensions
var (data, width, height) = LoadImage(imageData);
var header = new ImageHeader(data, width, height, width * 3, ImageFormat.RGB);
using var faces = await checker.DetectFacesAsync(header);
return faces.Where(f => f.DetectionQuality == DetectionQuality.Good)
.Select(async f => new
{
Path = path,
Result = await checker.CheckImageAsync(f)
});
});
var results = await Task.WhenAll(tasks);
```
## Next Steps
- [.NET API Reference](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md) - Complete API documentation for [`LivenessChecker`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#livenesschecker), [`Face`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#face), [`ImageHeader`](https://verifeye-docs.realeyes.ai/../api-reference/dotnet.md#imageheader), and more
Python
https://verifeye-docs.realeyes.ai/native-sdk/liveness-detection/getting-started/python/
# Getting Started with Python API
## Prerequisites
- Python 3.10+
- NumPy
## Installation
```bash
pip install realeyes-liveness
```
Or install from a wheel file:
```bash
pip install realeyes_liveness-1.0.0-cp310-cp310-linux_x86_64.whl
```
## Quick Start Example
```python
from realeyes.liveness import (
LivenessChecker,
DetectionQuality,
get_sdk_version_string
)
import numpy as np
# Print SDK version
print(f"SDK Version: {get_sdk_version_string()}")
# 1. Create LivenessChecker with model file
checker = LivenessChecker("model.realZ")
print(f"Model: {checker.get_model_name()}")
# 2. Load your image as NumPy array
# Image must be RGB format with shape [height, width, channels]
# Example using PIL/Pillow:
from PIL import Image
image = np.array(Image.open("photo.jpg").convert("RGB"))
# Or using OpenCV (convert BGR to RGB):
# import cv2
# image = cv2.cvtColor(cv2.imread("photo.jpg"), cv2.COLOR_BGR2RGB)
# 3. Detect faces
faces = checker.detect_faces(image)
print(f"Detected {len(faces)} face(s)")
# 4. Check liveness for each face
for face in faces:
# Check detection quality first
if face.detection_quality() != DetectionQuality.Good:
print("Skipping low-quality detection")
continue
# Get face info
bbox = face.bounding_box()
print(f"Face at ({bbox.x}, {bbox.y}) {bbox.width}x{bbox.height}")
print(f"Confidence: {face.confidence():.3f}")
# Perform liveness check
result = checker.check_image(face)
print(f"Liveness score: {result.score:.3f}")
print(f"Is live: {result.is_live}")
```
## Common Patterns
### Processing Video Frames
```python
import cv2
from realeyes.liveness import LivenessChecker, DetectionQuality
checker = LivenessChecker("model.realZ")
cap = cv2.VideoCapture(0) # Webcam
while True:
ret, frame = cap.read()
if not ret:
break
# Convert BGR to RGB
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Detect and check faces
faces = checker.detect_faces(rgb_frame)
for face in faces:
if face.detection_quality() == DetectionQuality.Good:
result = checker.check_image(face)
# Draw result on frame
bbox = face.bounding_box()
color = (0, 255, 0) if result.is_live else (0, 0, 255)
cv2.rectangle(frame,
(bbox.x, bbox.y),
(bbox.x + bbox.width, bbox.y + bbox.height),
color, 2)
label = f"Live: {result.score:.2f}" if result.is_live else f"Spoof: {result.score:.2f}"
cv2.putText(frame, label, (bbox.x, bbox.y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
cv2.imshow("Liveness", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
```
### Using Third-Party Face Detectors
Create a [`Face`](https://verifeye-docs.realeyes.ai/../api-reference/python.md#face) from your own detector results using [`Point2d`](https://verifeye-docs.realeyes.ai/../api-reference/python.md#point2d) and [`BoundingBox`](https://verifeye-docs.realeyes.ai/../api-reference/python.md#boundingbox):
```python
from realeyes.liveness import LivenessChecker, Face, Point2d, BoundingBox
checker = LivenessChecker("model.realZ")
# Your face detector results
landmarks = [
Point2d(100.0, 120.0), # left eye
Point2d(150.0, 120.0), # right eye
Point2d(125.0, 150.0), # nose
Point2d(105.0, 180.0), # left mouth
Point2d(145.0, 180.0), # right mouth
]
bbox = BoundingBox(x=80, y=100, width=100, height=120)
confidence = 0.95
# Create Face object for liveness checking
face = Face(image, landmarks, bbox, confidence)
result = checker.check_image(face)
print(f"Is live: {result.is_live}")
```
### Batch Processing
```python
from pathlib import Path
from PIL import Image
import numpy as np
from realeyes.liveness import LivenessChecker, DetectionQuality
checker = LivenessChecker("model.realZ")
image_dir = Path("images")
results = []
for image_path in image_dir.glob("*.jpg"):
image = np.array(Image.open(image_path).convert("RGB"))
faces = checker.detect_faces(image)
for i, face in enumerate(faces):
if face.detection_quality() == DetectionQuality.Good:
result = checker.check_image(face)
results.append({
"file": image_path.name,
"face_index": i,
"score": result.score,
"is_live": result.is_live
})
# Print results
for r in results:
status = "LIVE" if r["is_live"] else "SPOOF"
print(f"{r['file']} face {r['face_index']}: {status} (score: {r['score']:.3f})")
```
### Error Handling
```python
from realeyes.liveness import LivenessChecker
try:
checker = LivenessChecker("invalid_model.realZ")
except RuntimeError as e:
print(f"Failed to load model: {e}")
```
## Next Steps
- [Python API Reference](https://verifeye-docs.realeyes.ai/../api-reference/python.md) - Complete API documentation for [`LivenessChecker`](https://verifeye-docs.realeyes.ai/../api-reference/python.md#livenesschecker), [`Face`](https://verifeye-docs.realeyes.ai/../api-reference/python.md#face), [`CheckResult`](https://verifeye-docs.realeyes.ai/../api-reference/python.md#checkresult), and more
Index
https://verifeye-docs.realeyes.ai/native-sdk/liveness-detection/
# Liveness Detection Library
Welcome to the Liveness Detection Library documentation!
## Contents:
- [Overview](https://verifeye-docs.realeyes.ai/overview.md)
- [C++ API](https://verifeye-docs.realeyes.ai/api-reference/cpp.md)
- [C API](https://verifeye-docs.realeyes.ai/api-reference/c.md)
- [Python API](https://verifeye-docs.realeyes.ai/api-reference/python.md)
- [.NET API](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md)
Overview
https://verifeye-docs.realeyes.ai/native-sdk/liveness-detection/overview/
# Liveness Library
## Introduction
Liveness Library (LL) is a native C++17 library for real-time face detection and liveness verification on mobile and desktop platforms.
The library detects faces in images and determines whether a detected face is "live" (a real person) or a spoof attempt (photo, video playback, mask, etc.).
## Features
- Real-time face detection
- Liveness detection to prevent spoofing attacks
- Cross-platform support (Windows, Linux, macOS, mobile)
- Thread-safe async APIs with futures and callbacks
- Language bindings for Python and .NET
- Configurable concurrency with automatic tuning
## Supported Platforms
| Platform | Architecture | Status |
|----------|------------------|-----------|
| Linux | x86_64, ARM64 | Supported |
| Windows | x86_64 | Supported |
| macOS | x86_64, ARM64 | Supported |
| iOS | ARM64 | Supported |
| Android | ARM64, ARMv7 | Supported |
## Available APIs
- **C++** - Core native API with async support via `std::future` and callbacks
- **C** - C-compatible API for FFI (Foreign Function Interface)
- **Python** - Python bindings via pybind11
- **.NET** - .NET bindings via P/Invoke
## API Comparison
| Operation | C++ | C | Python | .NET |
|-----------|-----|---|--------|------|
| Create checker | [`LivenessChecker(path)`](https://verifeye-docs.realeyes.ai/api-reference/cpp.md#livenesschecker) | [`ll_liveness_checker_new()`](https://verifeye-docs.realeyes.ai/api-reference/c.md#ll_liveness_checker_new) | [`LivenessChecker(path)`](https://verifeye-docs.realeyes.ai/api-reference/python.md#livenesschecker) | [`new LivenessChecker(path)`](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md#livenesschecker) |
| Detect faces | [`detectFaces(image)`](https://verifeye-docs.realeyes.ai/api-reference/cpp.md#detectfaces-future) | [`ll_liveness_checker_detect_faces()`](https://verifeye-docs.realeyes.ai/api-reference/c.md#ll_liveness_checker_detect_faces) | [`detect_faces(image)`](https://verifeye-docs.realeyes.ai/api-reference/python.md#detect_faces) | [`DetectFacesAsync()`](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md#detectfacesasync) |
| Check liveness | [`checkImage(face)`](https://verifeye-docs.realeyes.ai/api-reference/cpp.md#checkimage-future) | [`ll_liveness_checker_check_image()`](https://verifeye-docs.realeyes.ai/api-reference/c.md#ll_liveness_checker_check_image) | [`check_image(face)`](https://verifeye-docs.realeyes.ai/api-reference/python.md#check_image) | [`CheckImageAsync()`](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md#checkimageasync) |
| Get SDK version | [`getSDKVersionString()`](https://verifeye-docs.realeyes.ai/api-reference/cpp.md#getsdkversionstring-static) | [`ll_liveness_checker_get_sdk_version_string()`](https://verifeye-docs.realeyes.ai/api-reference/c.md#ll_liveness_checker_get_sdk_version_string) | [`get_sdk_version_string()`](https://verifeye-docs.realeyes.ai/api-reference/python.md#get_sdk_version_string) | [`SdkVersionString`](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md#static-properties) |
| Cleanup | Destructor | [`ll_liveness_checker_free()`](https://verifeye-docs.realeyes.ai/api-reference/c.md#ll_liveness_checker_free) | Automatic | [`Dispose()`](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md#dispose) |
## Quick Links
### Getting Started
- [C++ Getting Started](https://verifeye-docs.realeyes.ai/getting-started/cpp.md)
- [C Getting Started](https://verifeye-docs.realeyes.ai/getting-started/c.md)
- [Python Getting Started](https://verifeye-docs.realeyes.ai/getting-started/python.md)
- [.NET Getting Started](https://verifeye-docs.realeyes.ai/getting-started/dotnet.md)
### API Reference
- [C++ API Reference](https://verifeye-docs.realeyes.ai/api-reference/cpp.md)
- [C API Reference](https://verifeye-docs.realeyes.ai/api-reference/c.md)
- [Python API Reference](https://verifeye-docs.realeyes.ai/api-reference/python.md)
- [.NET API Reference](https://verifeye-docs.realeyes.ai/api-reference/dotnet.md)
## Quick Example
### C++
```cpp
#include
ll::LivenessChecker checker("model.realZ");
// Create image header from your image data
ll::ImageHeader header{imageData, width, height, stride, ll::ImageFormat::BGR};
// Detect faces asynchronously
auto faces = checker.detectFaces(header).get();
// Check liveness for each face
for (const auto& face : faces) {
auto result = checker.checkImage(face).get();
if (result.is_live) {
std::cout << "Face is live with score: " << result.score << std::endl;
}
}
```
### Python
```python
from realeyes.liveness import LivenessChecker
import numpy as np
checker = LivenessChecker("model.realZ")
image = np.array(...) # Your image as NumPy array
faces = checker.detect_faces(image)
for face in faces:
result = checker.check_image(face)
print(f"Is live: {result.is_live}, Score: {result.score}")
```
### .NET
```csharp
using RealEyes.Liveness;
using var checker = new LivenessChecker("model.realZ");
var header = new ImageHeader(imageData, width, height, stride, ImageFormat.BGR);
using var faces = await checker.DetectFacesAsync(header);
foreach (var face in faces) {
var result = await checker.CheckImageAsync(face);
Console.WriteLine($"Is live: {result.IsLive}, Score: {result.Score}");
}
```
## License
Proprietary. Copyright Realeyes OU 2012-2026. All rights reserved.
Api C
https://verifeye-docs.realeyes.ai/native-sdk/native-emotions/api-c/
# C API Documentation
The C API provides a C interface to the Native Emotions Library, allowing integration with C projects and other languages that support C bindings.
## Module Functions
### nel_tracker_get_sdk_version
```c
NELVersion nel_tracker_get_sdk_version();
```
Returns the version of the SDK (and not the model)
**Returns:** version of the SDK
### nel_tracker_get_sdk_version_string
```c
char* nel_tracker_get_sdk_version_string();
```
Returns the version string of the SDK (and not the model)
**Returns:** version string of the SDK. The caller is responsible for freeing the returned string using free().
## Tracker Functions
### Constructor/Destructor
#### nel_tracker_new
```c
NELTracker* nel_tracker_new(const char* model_file, int max_concurrency, char** error_message);
```
Tracker constructor: loads model file, sets up the processing.
**Parameters:**
- `model_file` - path for the used model
- `max_concurrency` - maximum allowed concurrency, 0 means automatic (using all cores), default: 0
- `error_message` - pointer to a char* that will be set to an error message string on failure, or NULL on success. The caller is responsible for freeing the string using free(). If error_message is a NULL pointer, no error message will be returned.
**Returns:** pointer to the new Tracker instance, or NULL on failure
#### nel_tracker_free
```c
void nel_tracker_free(NELTracker* tracker);
```
Destructor
**Parameters:**
- `tracker` - pointer to the Tracker instance to free
### Tracking
#### nel_tracker_track
```c
void nel_tracker_track(NELTracker* tracker, const NELImageHeader* image_header,
int64_t timestamp_ms, NELTrackCallback callback, void* user_data);
```
Tracks the given frame asynchronously with a callback API.
**Note:** The given ImageHeader doesn't own the image data, and it is safe to delete the data after the call, a copy is happening internally. See NELImageHeader for details.
**Note:** Calling this function is non-blocking, so calling it again with the next frame without waiting for the result is possible. Also see nel_tracker_get_concurrent_calculations().
**Note:** This API is not thread-safe. Do not call any tracker functions from multiple threads simultaneously.
**Parameters:**
- `tracker` - pointer to the Tracker instance
- `image_header` - image descriptor
- `timestamp_ms` - timestamp of the image in milliseconds
- `callback` - callback to call with the result
- `user_data` - user data to pass to the callback
#### NELTrackCallback
```c
typedef void (*NELTrackCallback)(void* user_data, NELResultType* result, const char* error_msg);
```
Callback for track function
**Parameters:**
- `user_data` - user data passed to the function
- `result` - tracked landmarks and emotions. The result and its contents are owned by the library and are valid only during the callback.
- `error_msg` - error message if any, otherwise NULL
### Query Functions
#### nel_tracker_get_emotion_ids
```c
NELEmotionIDArray* nel_tracker_get_emotion_ids(const NELTracker* tracker);
```
Returns the emotion IDs provided by the loaded model. The order is the same as in the NELEmotionResults.
**See also:** NELEmotionResults
**Parameters:**
- `tracker` - pointer to the Tracker instance
**Returns:** pointer to NELEmotionIDArray. The caller is responsible for freeing the returned array using free().
#### nel_tracker_get_emotion_names
```c
NELStringArray* nel_tracker_get_emotion_names(const NELTracker* tracker);
```
Returns the emotion names provided by the loaded model. The order is the same as in the NELEmotionResults.
**See also:** NELEmotionResults
**Parameters:**
- `tracker` - pointer to the Tracker instance
**Returns:** pointer to NELStringArray. The caller is responsible for freeing the returned array using free().
#### nel_tracker_get_model_name
```c
char* nel_tracker_get_model_name(const NELTracker* tracker);
```
Returns the name (version etc) of the loaded model.
**Parameters:**
- `tracker` - pointer to the Tracker instance
**Returns:** name of the model. The caller is responsible for freeing the returned string using free().
#### nel_tracker_get_concurrent_calculations
```c
uint16_t nel_tracker_get_concurrent_calculations(const NELTracker* tracker);
```
Returns the value of the atomic counter for the number of calculations currently running concurrently. You can use this to limit the number of concurrent calculations.
**Parameters:**
- `tracker` - pointer to the Tracker instance
**Returns:** The (approximate) number of calculations currently in-flight.
### Configuration
#### nel_tracker_is_emotion_enabled
```c
bool nel_tracker_is_emotion_enabled(const NELTracker* tracker, NELEmotionID emotion_id);
```
Returns wether the specified emotion is enabled
**Parameters:**
- `tracker` - pointer to the Tracker instance
- `emotion_id` - emotion to query
**Returns:** true if enabled, false otherwise
#### nel_tracker_set_emotion_enabled
```c
void nel_tracker_set_emotion_enabled(NELTracker* tracker, NELEmotionID emotion_id, bool enable);
```
Sets the specified emotion to enabled or disabled
**Parameters:**
- `tracker` - pointer to the Tracker instance
- `emotion_id` - emotion to set
- `enable` - boolean to set to
#### nel_tracker_is_face_tracking_enabled
```c
bool nel_tracker_is_face_tracking_enabled(const NELTracker* tracker);
```
Returns wether the face tracker is enabled
**Parameters:**
- `tracker` - pointer to the Tracker instance
**Returns:** true if enabled, false otherwise
#### nel_tracker_set_face_tracking_enabled
```c
void nel_tracker_set_face_tracking_enabled(NELTracker* tracker, bool enable);
```
Sets the face tracker to be enabled or disabled
**Parameters:**
- `tracker` - pointer to the Tracker instance
- `enable` - boolean to set to
#### nel_tracker_get_minimum_face_ratio
```c
float nel_tracker_get_minimum_face_ratio(const NELTracker* tracker);
```
Gets the current minimum face ratio
**See also:** nel_tracker_set_minimum_face_ratio
**Parameters:**
- `tracker` - pointer to the Tracker instance
**Returns:** current minimum face size as a ratio of the smaller image dimension
#### nel_tracker_set_minimum_face_ratio
```c
void nel_tracker_set_minimum_face_ratio(NELTracker* tracker, float minimum_face_ratio);
```
Sets the minimum face ratio
The minimum face ratio defines the minimum face size the algorithm is looking for. The actual size is calculated from the smaller image dimension multiplied by the set minimum face ratio. If the value is 1/4.8, then in case of VGA resolution input (640x480), the minimum face size is 100x100.
**Warning:** The shape alignment and classifier performance can degrade in case of low resolution, tracking faces smaller than 75x75 is ill advised.
**Parameters:**
- `tracker` - pointer to the Tracker instance
- `minimum_face_ratio` - new minimum face size as a ratio of the smaller image dimension
#### nel_tracker_reset_tracking
```c
void nel_tracker_reset_tracking(NELTracker* tracker);
```
Resets the internal tracking state. Should be called when a new video sequence starts.
**Parameters:**
- `tracker` - pointer to the Tracker instance
## Data Types
### Enumerations
#### NELImageFormat
```c
typedef enum NELImageFormat {
NELImageFormatGrayscale = 0,
NELImageFormatRGB = 1,
NELImageFormatRGBA = 2,
NELImageFormatBGR = 3,
NELImageFormatBGRA = 4,
} NELImageFormat;
```
Image format enum
**Values:**
- `NELImageFormatGrayscale = 0` - 8-bit grayscale
- `NELImageFormatRGB = 1` - 24-bit RGB
- `NELImageFormatRGBA = 2` - 32-bit RGBA or 32-bit RGB_
- `NELImageFormatBGR = 3` - 24-bit BGR
- `NELImageFormatBGRA = 4` - 32-bit BGRA or 32-bit BGR_
#### NELEmotionID
```c
typedef enum NELEmotionID {
NELEmotionIDConfusion = 0,
NELEmotionIDContempt = 1,
NELEmotionIDDisgust = 2,
NELEmotionIDFear = 3,
NELEmotionIDHappy = 4,
NELEmotionIDEmpathy = 5,
NELEmotionIDSurprise = 6,
NELEmotionIDAttention = 100,
NELEmotionIDPresence = 101,
NELEmotionIDEyesOnScreen = 102,
NELEmotionIDFaceDetection = 103,
} NELEmotionID;
```
IDs for the supported emotions/behaviours
**Values:**
- `NELEmotionIDConfusion = 0`
- `NELEmotionIDContempt = 1`
- `NELEmotionIDDisgust = 2`
- `NELEmotionIDFear = 3`
- `NELEmotionIDHappy = 4`
- `NELEmotionIDEmpathy = 5`
- `NELEmotionIDSurprise = 6`
- `NELEmotionIDAttention = 100`
- `NELEmotionIDPresence = 101`
- `NELEmotionIDEyesOnScreen = 102`
- `NELEmotionIDFaceDetection = 103`
### Structures
#### Version
##### NELVersion
```c
typedef struct NELVersion {
int major;
int minor;
int patch;
} NELVersion;
```
Semantic version number for the SDK
**Members:**
- `int major`
- `int minor`
- `int patch`
#### Image
##### NELImageHeader
```c
typedef struct NELImageHeader {
const uint8_t* data;
int width;
int height;
int stride;
NELImageFormat format;
} NELImageHeader;
```
Descriptor class for image data (non-owning)
**Members:**
- `const uint8_t* data` - pointer to the byte array of the image
- `int width` - width of the image in pixels
- `int height` - height of the image in pixels
- `int stride` - length of one row of pixels in bytes (e.g: 3*width + padding)
- `NELImageFormat format` - image format
#### Points
##### NELPoint2d
```c
typedef struct NELPoint2d {
double x;
double y;
} NELPoint2d;
```
Point2d struct
**Members:**
- `double x` - x coordinate
- `double y` - y coordinate
##### NELPoint3d
```c
typedef struct NELPoint3d {
double x;
double y;
double z;
} NELPoint3d;
```
Point3d struct
**Members:**
- `double x` - x coordinate
- `double y` - y coordinate
- `double z` - z coordinate
##### NELPoint2dArray
```c
typedef struct NELPoint2dArray {
int count;
NELPoint2d* points;
} NELPoint2dArray;
```
Array of Point2d
**Members:**
- `int count` - number of points
- `NELPoint2d* points` - pointer to the array of points
##### NELPoint3dArray
```c
typedef struct NELPoint3dArray {
int count;
NELPoint3d* points;
} NELPoint3dArray;
```
Array of Point3d
**Members:**
- `int count` - number of points
- `NELPoint3d* points` - pointer to the array of points
#### Results
##### NELResultType
```c
typedef struct NELResultType {
NELLandmarkData* landmarks;
NELEmotionResults* emotions;
} NELResultType;
```
Result type for the track function
**Members:**
- `NELLandmarkData* landmarks` - pointer to landmark data, or NULL if no face was detected
- `NELEmotionResults* emotions` - pointer to emotion results, or NULL if no face was detected
##### NELLandmarkData
```c
typedef struct NELLandmarkData {
double scale;
double roll;
double yaw;
double pitch;
NELPoint2d translate;
NELPoint2dArray* landmarks2d;
NELPoint3dArray* landmarks3d;
bool isGood;
} NELLandmarkData;
```
Landmark data for a tracked face
**Members:**
- `double scale` - scale of the face
- `double roll` - roll angle in radians
- `double yaw` - yaw angle in radians
- `double pitch` - pitch angle in radians
- `NELPoint2d translate` - translation of the face
- `NELPoint2dArray* landmarks2d` - pointer to 2D landmarks array
- `NELPoint3dArray* landmarks3d` - pointer to 3D landmarks array
- `bool isGood` - whether the tracking is good
##### NELEmotionData
```c
typedef struct NELEmotionData {
double probability;
bool isActive;
bool isDetectionSuccessful;
NELEmotionID emotionID;
} NELEmotionData;
```
Emotion data for a single emotion
**Members:**
- `double probability` - probability of the emotion
- `bool isActive` - whether the emotion is active
- `bool isDetectionSuccessful` - whether the detection was successful
- `NELEmotionID emotionID` - ID of the emotion
##### NELEmotionResults
```c
typedef struct NELEmotionResults {
int count;
NELEmotionData* emotions;
} NELEmotionResults;
```
Array of emotion results
**Members:**
- `int count` - number of emotions
- `NELEmotionData* emotions` - pointer to the array of emotion data
#### Arrays
##### NELEmotionIDArray
```c
typedef struct NELEmotionIDArray {
int count;
NELEmotionID* ids;
} NELEmotionIDArray;
```
Array of emotion IDs
**Members:**
- `int count` - number of emotion IDs
- `NELEmotionID* ids` - pointer to the array of emotion IDs
##### NELStringArray
```c
typedef struct NELStringArray {
int count;
char** strings;
} NELStringArray;
```
Array of strings
**Members:**
- `int count` - number of strings
- `char** strings` - pointer to the array of string pointers
### Opaque Types
#### NELTracker
```c
typedef struct NELTracker NELTracker;
```
Opaque type for the Tracker instance
Api Cpp
https://verifeye-docs.realeyes.ai/native-sdk/native-emotions/api-cpp/
# C++ API Documentation
## Tracker class
### class nel::Tracker
The Emotion Tracker class
#### Constructor
```cpp
Tracker(const std::string& modelFile, int max_concurrency = 0)
```
Tracker constructor: loads model file, sets up the processing.
**Parameters:**
- `modelFile` - path for the used model
- `max_concurrency` - maximum allowed concurrency, 0 means automatic (using all cores), default: 0
#### Destructor
```cpp
~Tracker()
```
Destructor
#### track (std::future version)
```cpp
std::future track(const nel::ImageHeader& imageHeader, std::chrono::milliseconds timestamp)
```
Tracks the given frame asynchronously with the std::future API.
**Note:** The given ImageHeader doesn't own the image data, and it is safe to delete the data after the call, a copy is happening internally. See nel::ImageHeader for details.
**Note:** Calling this function is non-blocking, so calling it again with the next frame without waiting for the result is possible. Also see get_concurrent_calculations().
**Note:** This is the std::future based API, for callback API see nel::Tracker::track(const nel::ImageHeader&, std::chrono::milliseconds, std::function).
**Parameters:**
- `imageHeader` - image descriptor
- `timestamp` - timestamp of the image
#### track (callback version)
```cpp
void track(const nel::ImageHeader& imageHeader, std::chrono::milliseconds timestamp,
std::function callback)
```
Tracks the given frame asynchronously with a callback API.
**Note:** The given ImageHeader doesn't own the image data, and it is safe to delete the data after the call, a copy is happening internally. See nel::ImageHeader for details.
**Note:** Calling this function is non-blocking, so calling it again with the next frame without waiting for the result is possible. Also see get_concurrent_calculations().
**Note:** This is the callback based API, for std::future API see nel::Tracker::track(const nel::ImageHeader&, std::chrono::milliseconds).
**Parameters:**
- `imageHeader` - image descriptor
- `timestamp` - timestamp of the image
- `callback` - callback to call with the result
**Returns:** tracked landmarks and emotions
#### resetTracking
```cpp
void resetTracking()
```
Resets the internal tracking state. Should be called when a new video sequence starts.
#### get_emotion_IDs
```cpp
const std::vector& get_emotion_IDs() const
```
Returns the emotion IDs provided by the loaded model. The order is the same as in the nel::EmotionResults.
**See also:** nel::EmotionResults
**Returns:** A vector of emotion IDs.
#### get_emotion_names
```cpp
const std::vector& get_emotion_names() const
```
Returns the emotion names provided by the loaded model. The order is the same as in the nel::EmotionResults.
**See also:** nel::EmotionResults
**Returns:** A vector of emotion names.
#### get_concurrent_calculations
```cpp
uint16_t get_concurrent_calculations() const
```
Returns the value of the atomic counter for the number of calculations currently running concurrently. You can use this to limit the number of concurrent calculations.
**Returns:** The (approximate) number of calculations currently in-flight.
#### is_emotion_enabled
```cpp
bool is_emotion_enabled(nel::EmotionID emoID) const
```
Returns wether the specified emotion is enabled
**Parameters:**
- `emoID` - emotion to query
#### set_emotion_enabled
```cpp
void set_emotion_enabled(nel::EmotionID emoID, bool enable)
```
Sets the specified emotion to enabled or disabled
**Parameters:**
- `emoID` - emotion to set
- `enable` - boolean to set to
#### is_face_tracking_enabled
```cpp
bool is_face_tracking_enabled() const
```
Returns wether the face tracker is enabled
#### set_face_tracking_enabled
```cpp
void set_face_tracking_enabled(bool enable)
```
Sets the face tracker to be enabled or disabled
**Parameters:**
#### get_minimum_face_ratio
```cpp
float get_minimum_face_ratio() const
```
Gets the current minimum face ratio
**See also:** set_minimum_face_ratio
**Returns:** current minimum face size as a ratio of the smaller image dimension
#### set_minimum_face_ratio
```cpp
void set_minimum_face_ratio(float minimumFaceRatio)
```
Sets the minimum face ratio
The minimum face ratio defines the minimum face size the algorithm is looking for. The actual size is calculated from the smaller image dimension multiplied by the set minimum face ratio. If the value is 1/4.8, then in case of VGA resolution input (640x480), the minimum face size is 100x100.
**Warning:** The shape alignment and classifier performance can degrade in case of low resolution, tracking faces smaller than 75x75 is ill advised.
**Parameters:**
- `minimumFaceRatio` - new minimum face size as a ratio of the smaller image dimension
#### get_sdk_version
```cpp
static nel::Version get_sdk_version()
```
Returns the version of the SDK (and not the model)
**Returns:** version of the SDK
#### get_sdk_version_string
```cpp
static std::string get_sdk_version_string()
```
Returns the version string of the SDK (and not the model)
**Returns:** version string of the SDK
## Image header class
### struct nel::ImageHeader
Descriptor class for image data (non-owning)
**Members:**
- `const uint8_t* data` - pointer to the byte array of the image
- `int width` - width of the image in pixels
- `int height` - height of the image in pixels
- `int stride` - length of one row of pixels in bytes (e.g: 3*width + padding)
- `nel::ImageFormat format` - image format
### enum class nel::ImageFormat
Image format enum
**Values:**
- `Grayscale = 0` - 8-bit grayscale
- `RGB = 1` - 24-bit RGB
- `RGBA = 2` - 32-bit RGBA or 32-bit RGB_
- `BGR = 3` - 24-bit BGR
- `BGRA = 4` - 32-bit BGRA or 32-bit BGR_
## Result classes
### enum class nel::EmotionID
IDs for the supported emotions/behaviours
**Values:**
- `CONFUSION = 0`
- `CONTEMPT = 1`
- `DISGUST = 2`
- `FEAR = 3`
- `HAPPY = 4`
- `EMPATHY = 5`
- `SURPRISE = 6`
- `ATTENTION = 100`
- `PRESENCE = 101`
- `EYES_ON_SCREEN = 102`
- `FACE_DETECTION = 103`
### struct nel::Tracker::ResultType
The ResultType struct
**Members:**
- `nel::LandmarkData landmarks` - Tracked landmarks
- `nel::EmotionResults emotions` - Detected emotions
### struct nel::LandmarkData
The LandmarkData struct
**Members:**
- `double scale` - scale of the face
- `double roll` - roll pose angle
- `double yaw` - yaw pose angle
- `double pitch` - pitch pose angle
- `nel::Point2d translate` - position of the head center in image coordinates
- `std::vector landmarks2d` - position of the 49 landmarks, in image coordinates
- `std::vector landmarks3d` - position of the 49 landmarks, in an un-scaled face-centered 3D space
- `bool isGood` - whether the tracking is good quality or not
### struct nel::Point2d
Point2d struct
**Members:**
- `double x` - x coordinate
- `double y` - y coordinate
### struct nel::Point3d
Point3d struct
**Members:**
- `double x` - x coordinate
- `double y` - y coordinate
- `double z` - z coordinate
### typedef nel::EmotionResults
```cpp
typedef std::vector EmotionResults
```
EmotionResults
Vector of emotion data, the order of emotions is the same as in nel::Tracker::get_emotion_names().
**See also:** nel::Tracker::get_emotion_names().
### struct nel::EmotionData
The EmotionData struct
**Members:**
- `double probability` - probability of the emotion
- `bool isActive` - whether the probability is higher than an internal threshold
- `bool isDetectionSuccessful` - whether the tracking quality was good enough to reliable detect this emotion
- `EmotionID emotionID` - ID of the emotion
### struct nel::Version
Semantic version number for the SDK
**Members:**
- `int major`
- `int minor`
- `int patch`
```cpp
std::string get_model_name() const
```
Returns the name (version etc) of the loaded model.
**Returns:** name of the model
Api Dotnet
https://verifeye-docs.realeyes.ai/native-sdk/native-emotions/api-dotnet/
# .NET API Documentation
**Namespace:** Realeyes.EmotionTracking
## EmotionTracker class
### class EmotionTracker
The Emotion Tracker class. Implements IDisposable.
#### EmotionTracker(string modelPath, int maxConcurrency = 0)
```csharp
public EmotionTracker(string modelPath, int maxConcurrency = 0)
```
EmotionTracker constructor: loads model file, sets up the processing.
**Parameters:**
- `modelPath` (string) - Path to the tracking model file (.realZ)
- `maxConcurrency` (int) - Maximum concurrency (0 for automatic/all cores), default: 0
**Throws:**
- `ArgumentNullException` - When modelPath is null
- `EmotionTrackingException` - When model loading fails
#### TrackAsync(ImageHeader imageHeader, TimeSpan timestamp)
```csharp
public Task TrackAsync(ImageHeader imageHeader, TimeSpan timestamp)
```
Tracks emotions in an image asynchronously. Multiple images can be submitted for processing without waiting, and results can be awaited later, allowing for concurrent processing, but the frames must be submitted in chronological order.
**Parameters:**
- `imageHeader` (ImageHeader) - Image to process
- `timestamp` (TimeSpan) - Timestamp of the image
**Returns:** Task -- Tracking result with landmarks and emotions
**Throws:**
- `EmotionTrackingException` - When tracking fails
**Example:**
```csharp
var tracker = new EmotionTracker("model.realZ");
// Submit multiple images for processing
var task1 = tracker.TrackAsync(image1, TimeSpan.FromMilliseconds(0));
var task2 = tracker.TrackAsync(image2, TimeSpan.FromMilliseconds(33));
var task3 = tracker.TrackAsync(image3, TimeSpan.FromMilliseconds(66));
// Await results
var result1 = await task1;
var result2 = await task2;
var result3 = await task3;
```
#### ResetTracking()
```csharp
public void ResetTracking()
```
Resets the internal tracking state. Should be called when a new video sequence starts.
#### GetEmotionIDs()
```csharp
public EmotionID[] GetEmotionIDs()
```
Gets the emotion IDs provided by the loaded model.
**Returns:** EmotionID[] -- Array of emotion IDs
#### GetEmotionNames()
```csharp
public string[] GetEmotionNames()
```
Gets the names of emotions provided by the loaded model.
**Returns:** string[] -- Array of emotion names
#### IsEmotionEnabled(EmotionID emotionId)
```csharp
public bool IsEmotionEnabled(EmotionID emotionId)
```
Checks if a specific emotion is enabled for tracking.
**Parameters:**
- `emotionId` (EmotionID) - The emotion ID to check
**Returns:** bool -- True if enabled, false otherwise
#### SetEmotionEnabled(EmotionID emotionId, bool enabled)
```csharp
public void SetEmotionEnabled(EmotionID emotionId, bool enabled)
```
Enables or disables tracking for a specific emotion.
**Parameters:**
- `emotionId` (EmotionID) - The emotion ID to configure
- `enabled` (bool) - True to enable, false to disable
#### Dispose()
```csharp
public void Dispose()
```
Releases resources used by the tracker.
#### GetSdkVersion()
```csharp
public static Version GetSdkVersion()
```
Gets the SDK version.
**Returns:** Version -- SDK version information
#### GetSdkVersionString()
```csharp
public static string GetSdkVersionString()
```
Gets the SDK version as a string.
**Returns:** string -- SDK version string
#### ConcurrentCalculations
```csharp
public int ConcurrentCalculations { get; }
```
Gets the number of concurrent calculations.
#### IsFaceTrackingEnabled
## ImageFormat enum
### enum ImageFormat
**Values:**
- `Grayscale = 0`
- `RGB = 1`
- `RGBA = 2`
- `BGR = 3`
- `BGRA = 4`
## ImageHeader struct
### struct ImageHeader
The ImageHeader readonly record struct.
**Properties:**
- `Data` (byte[]) - Image data.
- `Width` (int) - Width of image.
- `Height` (int) - Height of image.
- `Stride` (int) - Stride of image.
- `Format` (ImageFormat) - Format of image.
## Result classes
### class EmotionTrackingException
Exception thrown when emotion tracking operations fail. Inherits from Exception.
### class TrackingResult
Contains the results after a successful tracking.
**Properties:**
- `Landmarks` (LandmarkData) - Landmark data from face tracking.
- `Emotions` (Emotions) - Detected emotion data.
### class Emotions
Record containing individual emotion detection results. Each property is nullable EmotionData.
**Properties:**
- `Confusion` (EmotionData?)
- `Contempt` (EmotionData?)
- `Disgust` (EmotionData?)
- `Fear` (EmotionData?)
- `Happy` (EmotionData?)
- `Empathy` (EmotionData?)
- `Surprise` (EmotionData?)
- `Attention` (EmotionData?)
- `Presence` (EmotionData?)
- `EyesOnScreen` (EmotionData?)
- `FaceDetection` (EmotionData?)
### class LandmarkData
Contains information about face landmarks.
**Properties:**
- `Scale` (double)
- `Roll` (double)
- `Yaw` (double)
- `Pitch` (double)
- `Translate` (Point2d)
- `Landmarks2d` (Point2d[])
- `Landmarks3d` (Point3d[])
- `IsGood` (bool)
### class EmotionData
Contains information about a specific emotion detection.
**Properties:**
- `Probability` (double)
- `IsActive` (bool)
- `IsDetectionSuccessful` (bool)
### struct Point2d
Readonly record struct representing a 2D point.
**Properties:**
- `X` (double)
- `Y` (double)
### struct Point3d
Readonly record struct representing a 3D point.
**Properties:**
- `X` (double)
- `Y` (double)
- `Z` (double)
### struct Version
Readonly record struct representing SDK version information.
**Properties:**
- `Major` (int)
- `Minor` (int)
- `Patch` (int)
## EmotionID enum
### enum EmotionID
Enum representing emotion types.
**Values:**
- `Confusion = 0`
- `Contempt = 1`
- `Disgust = 2`
- `Fear = 3`
- `Happy = 4`
- `Empathy = 5`
- `Surprise = 6`
- `Attention = 100`
- `Presence = 101`
- `EyesOnScreen = 102`
- `FaceDetection = 103`
Api Java
https://verifeye-docs.realeyes.ai/native-sdk/native-emotions/api-java/
# Java API Documentation (Experimental)
**Package:** com.realeyesit.nel
## Tracker interface
### interface Tracker
The Tracker interface
#### track(ImageHeader imageHeader, long timestamp)
```java
public TrackerResultFuture track(ImageHeader imageHeader, long timestamp)
```
Tracks the given frame asynchronously with the TrackerResultFuture API.
**Note:** Calling this function is non-blocking, so calling it again with the next frame without waiting for the result is possible. Also see get_concurrent_calculations().
**Parameters:**
- `imageHeader` - image descriptor
- `timestamp` - timestamp of the image (in ms)
#### resetTracking()
```java
public void resetTracking()
```
Resets the internal tracking state. Should be called when a new video sequence starts.
#### getEmotionIDs()
```java
public java.util.List getEmotionIDs()
```
Returns the emotion IDs provided by the loaded model. The order is the same as returned by ResultType.getEmotions().
**See also:** ResultType
#### getEmotionNames()
```java
public java.util.List getEmotionNames()
```
Returns the emotion names provided by the loaded model. The order is the same as returned by ResultType.getEmotions().
**See also:** ResultType
#### getMinimumFaceRatio()
```java
public float getMinimumFaceRatio()
```
Gets the current minimum face ratio
**See also:** setMinimumFaceRatio
#### setMinimumFaceRatio(float minimumFaceRatio)
```java
public void setMinimumFaceRatio(float minimumFaceRatio)
```
Sets the minimum face ratio
The minimum face ratio defines the minimum face size the algorithm is looking for. The actual size is calculated from the smaller image dimension multiplied by the set minimum face ratio. The default value is 1/4.8, i.e., in case of VGA resolution input (640x480), the minimum face size is 100x100.
**Warning:** The shape alignment and classifier performance can degrade in case of low resolution, tracking faces smaller than 75x75 is ill advised.
**Parameters:**
- `minimumFaceRatio` - new minimum face size as a ratio of the smaller image dimension
#### isFaceTrackingEnabled()
```java
public boolean isFaceTrackingEnabled()
```
Returns wether the face tracker is enabled
#### setFaceTrackingEnabled(boolean enable)
```java
public void setFaceTrackingEnabled(boolean enable)
```
Sets the face tracker to be enabled or disabled
**Parameters:**
- `enable` - boolean to set to
#### isEmotionEnabled(EmotionID emoID)
```java
public boolean isEmotionEnabled(EmotionID emoID)
```
Returns wether the specified emotion is enabled
**Parameters:**
- `emoID` - emotion to query
#### setEmotionEnabled(EmotionID emoID, boolean enable)
```java
public void setEmotionEnabled(EmotionID emoID, boolean enable)
```
Sets the specified emotion to enabled or disabled
**Parameters:**
- `emoID` - emotion to set
- `enable` - boolean to set to
#### getModelName()
```java
public String getModelName()
```
Returns the name (version etc) of the loaded model.
**Returns:** name of the model
#### getSdkVersion()
```java
public Version getSdkVersion()
```
Returns the version of the SDK (and not the model)
**Returns:** version of the SDK
#### getSdkVersionString()
```java
public String getSdkVersionString()
```
Returns the version string of the SDK (and not the model)
**Returns:** version string of the SDK
## NelTracker class
#### NelTracker(String modelFile, int max_concurrency)
```java
public NelTracker(String modelFile, int max_concurrency)
```
Constructor
**Parameters:**
- `modelFile` (str) - path for the used model
- `max_concurrency` (int) - maximum allowed concurrency, 0 means automatic (using all cores), default: 0
## ImageHeader class
### class ImageHeader
Descriptor class for image data (non-owning)
#### ImageHeader()
```java
public ImageHeader()
```
Constructor
#### getData()
```java
public java.nio.ByteBuffer getData()
```
**Returns:** pointer to the byte array of the image
#### setData(java.nio.ByteBuffer value)
```java
public void setData(java.nio.ByteBuffer value)
```
**Parameters:**
- `value` - pointer to the byte array of the image
#### getFormat()
```java
public ImageFormat getFormat()
```
**Returns:** image format
#### setFormat(ImageFormat value)
```java
public void setFormat(ImageFormat value)
```
**Parameters:**
- `value` - image format
#### getHeight()
```java
public int getHeight()
```
**Returns:** height of the image in pixels
#### setHeight(int value)
```java
public void setHeight(int value)
```
**Returns:** height of the image in pixels
#### getStride()
```java
public int getStride()
```
**Returns:** length of one row of pixels in bytes (e.g: 3*width + padding)
#### setStride(int value)
```java
public void setStride(int value)
```
**Parameters:**
- `value` - length of one row of pixels in bytes (e.g: 3*width + padding)
#### getWidth()
```java
public int getWidth()
```
**Returns:** width of the image in pixels
#### setWidth(int value)
```java
public void setWidth(int value)
```
**Parameters:**
- `value` - width of the image in pixels
### enum ImageFormat
**Values:**
- `BGR` - 24-bit BGR
- `BGRA` - 32-bit BGRA or 32-bit BGR_
- `Grayscale` - 8-bit grayscale
- `RGB` - 24-bit RGB
- `RGBA` - 32-bit RGBA or 32-bit RGB_
## Result classes
### enum EmotionID
IDs for the supported emotions/behaviours
**Values:**
- `ATTENTION`
- `CONFUSION`
- `CONTEMPT`
- `DISGUST`
- `EMPATHY`
- `FEAR`
- `HAPPY`
- `PRESENCE`
- `SURPRISE`
- `EYES_ON_SCREEN`
- `FACE_DETECTION`
### interface TrackerResultFuture
Simple wrapper over the C++ future class
#### get()
```java
ResultType get()
```
Blocks until the future is ready and returns the result.
### interface ResultType
The ResultType struct.
#### getEmotions()
```java
java.util.List getEmotions()
```
Detected emotions.
#### getLandmarks()
```java
LandmarkData getLandmarks()
```
Tracked landmarks.
### interface LandmarkData
#### getScale()
```java
double getScale()
```
Scale of the face.
#### getRoll()
```java
double getRoll()
```
Roll pose angle.
#### getPitch()
```java
double getPitch()
```
Pitch pose angle.
#### getYaw()
```java
double getYaw()
```
Yaw pose angle.
#### getTranslate()
```java
Point2d getTranslate()
```
Position of the head center in image coordinates.
#### getLandmarks2d()
```java
java.util.List getLandmarks2d()
```
Positions of the 49 landmarks, in image coordinates.
#### getLandmarks3d()
```java
java.util.List getLandmarks3d()
```
Positions of the 49 landmarks, in an un-scaled face-centered 3D space.
#### getIsGood()
```java
boolean getIsGood()
```
Whether the tracking is good quality or not.
### interface Point2d
#### getX()
```java
double getX()
```
#### getY()
```java
double getY()
```
### interface Point3d
#### Point3d_GetInterfaceCPtr()
```java
long Point3d_GetInterfaceCPtr()
```
#### getX()
```java
double getX()
```
#### getY()
```java
double getY()
```
#### getZ()
```java
double getZ()
```
### interface EmotionData
#### getEmotionID()
```java
EmotionID getEmotionID()
```
ID of the emotion.
#### getIsActive()
```java
boolean getIsActive()
```
Whether the probability is higher than an internal threshold.
#### getIsDetectionSuccessful()
```java
boolean getIsDetectionSuccessful()
```
Whether the tracking quality was good enough to reliable detect this emotion.
#### getProbability()
```java
double getProbability()
```
Probability of the emotion.
### interface Version
Semantic version number for the SDK
#### getMajor()
```java
int getMajor()
```
#### getMinor()
```java
int getMinor()
```
#### getPatch()
```java
int getPatch()
```
Api Python
https://verifeye-docs.realeyes.ai/native-sdk/native-emotions/api-python/
# Python API Documentation
## Module Functions
### get_sdk_version_string()
Returns the SDK version string.
**Returns:** str
## Tracker class
### class realeyes.emotion_detection.Tracker(model_file, max_concurrency=0)
The Emotion Tracker class
#### \_\_init\_\_(self, model_file, max_concurrency=0)
Tracker constructor: loads model file, sets up the processing.
**Parameters:**
- `model_file` (str) - path for the used model
- `max_concurrency` (int) - maximum allowed concurrency, 0 means automatic (using all cores), default: 0
#### track(image, timestamp_in_ms)
Tracks the given frame.
**Parameters:**
- `image` (numpy.ndarray) - frame from the video
- `timestamp_in_ms` (int) - timestamp of the frame
**Returns:** TrackingResult
#### reset_tracking()
Resets the internal tracking state. Should be called when a new video sequence starts.
#### get_emotion_ids()
Returns the emotion IDs provided by the loaded model. The order is the same as in the TrackingResult.
**Returns:** list[EmotionID]
#### get_emotion_names()
Returns the emotion names provided by the loaded model. The order is the same as in the TrackingResult.
**Returns:** list[str]
#### get_model_name()
Returns the name (version etc) of the loaded model.
**Returns:** str
#### minimum_face_ratio: float
Current minimum face size as a ratio of the smaller image dimension.
#### is_face_tracking_enabled()
Returns wether the face tracker is enabled.
**Returns:** bool
#### set_face_tracking_enabled(enable: bool)
Sets the face tracker to be enabled or disabled.
**Parameters:**
- `enable` (bool) - new value
#### is_emotion_enabled(emotion_id)
Returns wether the specified emotion is enabled.
**Parameters:**
- `emotion_id` (EmotionID) - emotion to query
**Returns:** bool
#### set_emotion_enabled(emotion_id: EmotionID, enable: bool)
Sets the specified emotion to enabled or disabled.
**Parameters:**
- `emotion_id` (EmotionID) - emotion to set
- `enable` (bool) - new value
#### \_\_repr\_\_()
Returns a string representation of the Tracker.
**Returns:** str
## Result classes
### class EmotionID
**Attributes:**
- `CONFUSION = 0`
- `CONTEMPT = 1`
- `DISGUST = 2`
- `FEAR = 3`
- `HAPPY = 4`
- `EMPATHY = 5`
- `SURPRISE = 6`
- `ATTENTION = 100`
- `PRESENCE = 101`
- `EYES_ON_SCREEN = 102`
### class TrackingResult
**Attributes:**
- `emotions` (list[EmotionData]) - Tracked emotions. See EmotionData
- `landmarks` (LandmarkData) - Tracked landmarks. See LandmarkData
#### to_json()
Converts the data to json (dicts and lists).
**Returns:** dict
#### \_\_repr\_\_()
Returns a string representation of the TrackingResult.
**Returns:** str
### class LandmarkData
**Attributes:**
- `scale` (float) - Scale of the face.
- `roll` (float) - Roll pose angle.
- `yaw` (float) - Yaw pose angle.
- `pitch` (float) - Pitch pose angle.
- `translate` (list[Point2d]) - Position of the head center in image coordinates.
- `landmarks2d` (list[Point2d]) - Positions of the 49 landmarks, in image coordinates.
- `landmarks3d` (list[Point3d]) - Positions of the 49 landmarks, in an un-scaled face-centered 3D space.
- `is_good` (bool) - Whether the tracking is good quality or not.
#### to_json()
Converts the data to json (dicts and lists).
**Returns:** dict
#### \_\_repr\_\_()
### class Point2d
**Attributes:**
- `x` (float)
- `y` (float)
#### to_json()
Converts the data to json (dicts and lists).
**Returns:** dict
#### __repr__()
Returns a string representation of the Point2d.
**Returns:** str
### class Point3d
**Attributes:**
- `x` (float)
- `y` (float)
- `z` (float)
#### to_json()
Converts the data to json (dicts and lists).
**Returns:** dict
#### __repr__()
Returns a string representation of the Point3d.
**Returns:** str
### class EmotionData
**Attributes:**
- `probability` (float) - Probability of the emotion.
- `is_active` (bool) - Whether the probability is higher than an internal threshold.
- `is_detection_successful` (bool) - Whether the tracking quality was good enough to reliable detect this emotion.
- `emotion_id` (EmotionID) - ID of the emotion. See EmotionID
#### to_json()
Converts the data to json (dicts and lists).
**Returns:** dict
#### __repr__()
Returns a string representation of the EmotionData.
**Returns:** str
Index
https://verifeye-docs.realeyes.ai/native-sdk/native-emotions/
# Native Emotions Library
Welcome to Native Emotions Library documentation!
## Contents:
- [Overview](https://verifeye-docs.realeyes.ai/overview.md)
- [C++ API](https://verifeye-docs.realeyes.ai/api-cpp.md)
- [C API](https://verifeye-docs.realeyes.ai/api-c.md)
- [Python API](https://verifeye-docs.realeyes.ai/api-python.md)
- [Java API](https://verifeye-docs.realeyes.ai/api-java.md)
- [.NET API](https://verifeye-docs.realeyes.ai/api-dotnet.md)
Overview
https://verifeye-docs.realeyes.ai/native-sdk/native-emotions/overview/
# Overview
The Native Emotions Library is a portable C++ library for real-time facial emotion tracking and analysis.
The SDK provides wrappers in the following languages:
* C++ (native)
* C
* Python
* C# / .NET
* Java (Android)
## Getting Started
### Hardware requirements
The SDK doesn't have any special hardware requirement:
- **CPU:** No special requirement, any modern 64 bit capable CPU (x86-64 with AVX, ARM8) is supported
- **GPU:** No special requirement
- **RAM:** 2 GB of available RAM required
- **Camera:** No special requirement, minimum resolution: 640x480
### Software requirements
The SDK is regularly tested on the following Operating Systems:
- Windows 10+
- Ubuntu 24.04+
- macOS 15+
- iOS 18+
- Android 23+
### 3rd Party Licenses
While the SDK is released under a proprietary license, the following Open-Source projects were used in it with their respective licenses:
- OpenCV - [3 clause BSD](https://opencv.org/license/)
- Tensorflow - [Apache License 2.0](https://github.com/tensorflow/tensorflow/blob/master/LICENSE)
- Protobuf - [3 clause BSD](https://github.com/protocolbuffers/protobuf/blob/master/LICENSE)
- zlib - [zlib license](https://www.zlib.net/zlib_license.html)
- minizip-ng - [zlib license](https://github.com/zlib-ng/minizip-ng/blob/master/LICENSE)
- stlab - [Boost Software License 1.0](https://github.com/stlab/libraries/blob/main/LICENSE)
- pybind11 - [3 clause BSD](https://github.com/pybind/pybind11/blob/master/LICENSE)
- fmtlib - [MIT License](https://github.com/fmtlib/fmt/blob/master/LICENSE.rst)
### Installation
#### C++
Extract the SDK contents, include the headers from the `include` folder and link `libNativeEmotionsLibrary` to your C++ project.
#### C
Extract the SDK contents, include `tracker_c.h` from the `include` folder and link `libNativeEmotionsLibrary` to your C project.
#### Python
The python version of the SDK can be installed with pip:
```bash
$ pip install realeyes.emotion-detection
```
#### C# / .NET
The .NET version of the SDK can be installed via NuGet:
```bash
$ dotnet add package Realeyes.EmotionTracking
```
#### Java
For Android projects, add the library to your `build.gradle` dependencies.
## Usage
### C++
The main entry point of this library is the `nel::Tracker` class.
After a **tracker** object is constructed, the user can call the `nel::Tracker::track()` function to process
a frame from a video or other frame source.
The `nel::Tracker::track()` function has two versions, both are non-blocking async calls: one returns
`std::future`, the other accepts a callback that will be called on completion. After one call,
a subsequent call is possible without waiting for the result.
For the frame data, the user must construct a `nel::ImageHeader` object. The frame data must outlive
this object since it is a non-owning view, but it only needs to be valid during the `nel::Tracker::track()`
call - the library will copy the frame data internally.
The following example shows the basic usage of the library using OpenCV for loading images and feeding them to the tracker:
```cpp
#include "tracker.h"
#include
#include
#include
#include
int main()
{
nel::Tracker tracker("model/model.realZ");
cv::VideoCapture video("video.mp4");
cv::Mat frame;
while (video.read(frame)) {
nel::ImageHeader header{
frame.ptr(),
frame.cols,
frame.rows,
static_cast(frame.step1()),
nel::ImageFormat::BGR
};
int64_t timestamp_in_ms = video.get(cv2::CAP_PROP_POS_MSEC);
// Track asynchronously using std::future
auto future = tracker.track(header, std::chrono::milliseconds(timestamp_in_ms));
auto result = future.get();
// Process results
std::cout << "Face tracking: " << (result.landmarks.isGood ? "good" : "failed") << std::endl;
for (const auto& emotion : result.emotions) {
std::cout << " Probability: " << emotion.probability
<< " Active: " << emotion.isActive << std::endl;
}
}
return 0;
}
```
### C
The main entry point is the `NELTracker` opaque pointer type with associated functions.
After creating a tracker with `nel_tracker_new()`, you can track frames by calling `nel_tracker_track()`
with a callback function. The callback will be called asynchronously when tracking completes.
The following example shows basic usage:
```c
#include "tracker_c.h"
#include
#include
void track_callback(void* user_data, NELResultType* result, const char* error_msg) {
if (error_msg != NULL) {
printf("Error: %s\n", error_msg);
return;
}
printf("Face tracking: %s\n", result->landmarks->isGood ? "good" : "failed");
for (int i = 0; i < result->emotions->count; i++) {
printf(" Emotion %d - Probability: %f, Active: %d\n",
result->emotions->emotions[i].emotionID,
result->emotions->emotions[i].probability,
result->emotions->emotions[i].isActive);
}
}
int main() {
char* error_msg = NULL;
NELTracker* tracker = nel_tracker_new("model/model.realZ", 0, &error_msg);
if (tracker == NULL) {
printf("Failed to load model: %s\n", error_msg);
free(error_msg);
return 1;
}
// Prepare image data (example with dummy data)
uint8_t image_data[640 * 480 * 3]; // RGB image
NELImageHeader header = {
.data = image_data,
.width = 640,
.height = 480,
.stride = 640 * 3,
.format = NELImageFormatRGB
};
nel_tracker_track(tracker, &header, 0, track_callback, NULL);
// Clean up
nel_tracker_free(tracker);
return 0;
}
```
### Python
The main entry point of this library is the `realeyes.emotion_detection.Tracker` class.
After a **tracker** object is constructed, the user can call the `realeyes.emotion_detection.Tracker.track()`
function to process frames from a video or other frame source.
The following example shows the basic usage of the library using OpenCV for loading images:
```python
import realeyes.emotion_detection as nel
import cv2
# Initialize the tracker
tracker = nel.Tracker('model/model.realZ')
# Open video
video = cv2.VideoCapture('video.mp4')
while True:
ret, frame = video.read()
if not ret:
break
# Convert BGR to RGB (OpenCV uses BGR)
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Track emotions (timestamp in milliseconds)
result = tracker.track(frame_rgb, 0)
# Process results
print(f"Face tracking: {'good' if result.landmarks.is_good else 'failed'}")
for emotion in result.emotions:
print(f" Emotion ID {emotion.emotion_id}: "
f"Probability={emotion.probability:.3f}, "
f"Active={emotion.is_active}")
video.release()
```
### C# / .NET
The main entry point is the `EmotionTracker` class.
After an **tracker** object is constructed, you can call the `TrackAsync()` method to track faces
in a frame. The method returns a `Task` allowing for asynchronous, non-blocking operation.
Both the constructor and tracking method support concurrent execution - you can start multiple operations
in parallel without waiting for results.
The following example demonstrates processing a video frame:
```csharp
using Realeyes.EmotionTracking;
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
// Create tracker with model file
using var tracker = new EmotionTracker("model/model.realZ");
// Prepare image data (example with dummy RGB data)
byte[] imageData = new byte[640 * 480 * 3];
var imageHeader = new ImageHeader
{
Data = imageData,
Width = 640,
Height = 480,
Stride = 640 * 3,
Format = ImageFormat.RGB
};
// Track emotions asynchronously
var result = await tracker.TrackAsync(imageHeader, TimeSpan.Zero);
// Process results
Console.WriteLine($"Face tracking: {(result.LandmarkData?.IsGood ?? false ? "good" : "failed")}");
if (result.Emotions.Happy is { } happy)
Console.WriteLine($"Happy: {happy.Probability:P2}, Active: {happy.IsActive}");
if (result.Emotions.Confusion is { } confusion)
Console.WriteLine($"Confusion: {confusion.Probability:P2}, Active: {confusion.IsActive}");
}
}
```
### Java
The main entry point is the `Tracker` interface.
After creating a **tracker** object, you can call the `track()` method to process frames.
The method returns a `TrackerResultFuture` for asynchronous result retrieval.
The following example shows basic usage:
```java
import com.realeyesit.nel.*;
public class Example {
public static void main(String[] args) {
// Create tracker with model file
Tracker tracker = Emotion.createTracker("model/model.realZ", 0);
// Prepare image data (example with dummy RGB data)
byte[] imageData = new byte[640 * 480 * 3];
ImageHeader header = new ImageHeader();
header.setData(imageData);
header.setWidth(640);
header.setHeight(480);
header.setStride(640 * 3);
header.setFormat(ImageFormat.RGB);
// Track emotions asynchronously
TrackerResultFuture future = tracker.track(header, 0);
ResultType result = future.get();
// Process results
System.out.println("Face tracking: " +
(result.getLandmarks().getIsGood() ? "good" : "failed"));
for (EmotionData emotion : result.getEmotions()) {
System.out.println(" Emotion: " + emotion.getEmotionID() +
" Probability: " + emotion.getProbability() +
" Active: " + emotion.getIsActive());
}
}
}
```
## Results
The result of the tracking contains a `nel::LandmarkData` structure and a `nel::EmotionResults` vector.
- The `nel::LandmarkData` consists of the following members:
- **scale**, the size of the face (larger means closer the user to the camera)
- **roll**, **pitch**, **yaw**, the 3 Euler angles of the face pose
- **translate**, the position of the head center on the frame
- the **landmarks2d** vector with either 0 or 49 points,
- the **landmarks3d** vector with either 0 or 49 points,
- and the **isGood** boolean value.
The **isGood** indicates whether the tracking is deemed good enough.
**landmarks2d** and **landmarks3d** contain 0 points if the tracker failed to find a face on the image, otherwise it always contain 49 points in the following structure:

**landmarks3d** contains the 3d coordinates of the frontal face in 3D space with 0 translation and 1 scale.
- The `nel::EmotionResults` contains multiple `nel::EmotionData` elements with the following members:
- **probability**, probability of the emotion
- **isActive**, whether the probability is higher than an internal threshold
- **isDetectionSuccessful** whether the tracking quality was good enough to reliable detect this emotion
The order of the `nel::EmotionData` elements are the same as the emotions in `nel::Tracker::get_emotion_IDs()` and in `nel::Tracker::get_emotion_names()`.
## Interpretation of the classifier output
The **probability** output of the Realeyes classifier (from the `nel::EmotionData` structure) has the following properties:
- It is a continuous value from the [0,1] range
- It changes depending on type and number of facial features activated
- It typically indicates facial activity in regions of face that correspond to a given facial expression
- Strong facial wrinkles or shadows can amplify the classifier sensitivity to corresponding facial regions
- It is purposefully sensitive as the classifier is trained to capture slight expressions
- It **should not be interpreted as intensity** of a given facial expression
- It is not possible to prescribe which facial features correspond to what output levels due to the nature of the used ML models
We recommend the following interpretation of the **probability** output:
- **values close to 0**
- no or very little activity on the face with respect to a given facial expression
- **values between 0 and binary threshold**
- some facial activity was perceived, though in the view of the classifier it does not amount to a basic facial expression
- **values just below binary threshold**
- high facial activity was perceived, which under some circumstances may be interpreted as true basic facial expression, while under others not (e.g. watching ads vs. playing games)
- **values above binary threshold**
- high facial activity was perceived, which in view of the classifier amount to a basic facial expression
Demographic Estimation
https://verifeye-docs.realeyes.ai/on-prem-docker/demographic-estimation/
# Realeyes Guide for Demographic Estimation API
## Overview
This guide presents the requirements for acquiring, running and using the docker image of the Demographic Estimation API service.
---
## Changelog
**Version 1.0:** Initial version.
---
## Accessing and pulling the latest docker image
You must do the first 2 steps only once per user/computer.
### Prerequisites
It is required that you have AWS CLI installed. This command is supported using the latest version of AWS CLI version 2 or in v1.17.10 or later of AWS CLI version 1.
See how to: [Install the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
### Configure AWS credential profile
You should have previously received your access key ID and Secret Access Key from Realeyes. Please use them here:
```
aws configure --profile demographicestimation
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]:
```
### Get authorization token and pass it to docker login
```
aws ecr get-login-password --profile demographicestimation --region eu-west-1 | docker login --username AWS --password-stdin 249265253269.dkr.ecr.eu-west-1.amazonaws.com
```
The get-login-password command retrieves and displays an authentication token using the GetAuthorizationToken API -- you will use this token to authenticate to an Amazon ECR registry. You can pass the authorization token to the login command of the container client of your preference, such as the Docker CLI. After you have authenticated to an Amazon ECR registry with this command, you can use the client to pull images from that registry as long as your IAM principal has access to do so before the token expires. **NOTE:** The authorization token is valid for 12 hours.
### Pull the latest docker image
```
docker pull 249265253269.dkr.ecr.eu-west-1.amazonaws.com/verifeye/demographic-estimation-api:latest
```
---
## Running the image
The service requires an activation key.
Set:
```
ACTIVATION_KEY=
```
You need to request the activation key from Realeyes.
### Run with docker
Run the container with the following command:
```
docker run --rm -ti -p 8080:8080/tcp \
-e ACTIVATION_KEY= \
--read-only \
--pids-limit=128 \
--security-opt=no-new-privileges \
--memory=16G \
249265253269.dkr.ecr.eu-west-1.amazonaws.com/verifeye/demographic-estimation-api:latest
```
### Run with docker compose
Alternatively one can use the following docker-compose.yaml:
```yaml
services:
demographic-estimation-api:
image: 249265253269.dkr.ecr.eu-west-1.amazonaws.com/verifeye/demographic-estimation-api:latest
environment:
- ACTIVATION_KEY=
ports:
- 8080:8080
read_only: true
security_opt:
- "no-new-privileges"
deploy:
resources:
limits:
pids: 128
memory: 16G
```
---
## Interactive API Documentation (Swagger UI)
Once the service is running, you can access the interactive API documentation at:
```
http://localhost:8080/swagger/index.html
```
This Swagger UI provides a **living documentation** of the API where you can:
- Browse all available endpoints with their detailed descriptions
- View request/response schemas and example payloads
- **Try out the API directly from your browser** - send real requests and see the responses in real-time
- Explore error codes and response formats
This is the recommended way to get familiar with the API and test your integration during development.
---
## API overview
The Demographic Estimation API service provides REST API endpoints for age estimation and gender detection.
Below is the outline of the API, while a more detailed documentation is available on the Swagger UI (see above).
---
### Get Age
Estimates the age of faces detected in an image.
**Endpoint:** `POST /v1/demographic-estimation/get-age`
**Authentication:** API Key or Bearer Token
**Request Body:**
```json
{
"image": {
"bytes": "base64-encoded-image-string",
"url": null
},
"maxFaceCount": 1
}
```
**Request Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `image` | object | Yes | Image data provided as URL or Base64 encoded bytes |
| `image.url` | string (nullable) | No | URL of a JPEG or PNG image |
| `image.bytes` | string (nullable) | No | Base64 encoded binary JPEG or PNG image |
| `maxFaceCount` | integer | No | Maximum number of faces to be processed (default: 1) |
**Response Example:**
```json
{
"faces": [
{
"face": {
"confidence": 0.9987,
"boundingBox": {
"x": 120,
"y": 80,
"width": 200,
"height": 250
}
},
"age": {
"prediction": 28.5,
"uncertainty": 0.45
}
}
],
"unprocessedFaceCount": 0
}
```
**Response Fields:**
| Field Path | Type | Description |
|------------|------|-------------|
| `faces` | array (nullable) | The faces that were processed and their age estimation results |
| `faces[].face` | object | Face detection information |
| `faces[].face.confidence` | number | Face detection score with value range [0.0, 1.0] (higher is better) |
| `faces[].face.boundingBox` | object | Bounding box of the detected face |
| `faces[].face.boundingBox.x` | integer | Horizontal position of the detected face bounding box |
| `faces[].face.boundingBox.y` | integer | Vertical position of the detected face bounding box |
| `faces[].face.boundingBox.width` | integer | Width of the detected face bounding box |
| `faces[].face.boundingBox.height` | integer | Height of the detected face bounding box |
| `faces[].age` | object | Age estimation information |
| `faces[].age.prediction` | number (nullable) | Estimated age |
| `faces[].age.uncertainty` | number (nullable) | Uncertainty score of the estimation with value range [0.0, infinity], we recommend rejecting everything higher than 1.0 |
| `unprocessedFaceCount` | integer | The number of faces that were not processed due to the maximum face count limit |
**Example Request:**
```bash
curl -X POST "https://demographic-estimation-api-eu.realeyes.ai/v1/demographic-estimation/get-age" \
-H "Authorization: ApiKey API-KEY-FROM-DEV-CONSOLE" \
-H "Content-Type: application/json" \
-d '{
"image": {
"bytes": "/9j/4AAQSkZJRgABAQEAYABgAAD..."
},
"maxFaceCount": 5
}'
```
**Response Codes:**
- `200` - Success
- `400` - Bad Request - Invalid image format, missing required fields, or invalid parameters
- `401` - Unauthorized - Missing or invalid authentication
---
### Get Gender
Detects the gender of faces in an image.
**Endpoint:** `POST /v1/demographic-estimation/get-gender`
**Authentication:** API Key or Bearer Token
**Request Body:**
```json
{
"image": {
"bytes": "base64-encoded-image-string",
"url": null
},
"maxFaceCount": 1
}
```
**Request Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `image` | object | Yes | Image data provided as URL or Base64 encoded bytes |
| `image.url` | string (nullable) | No | URL of a JPEG or PNG image |
| `image.bytes` | string (nullable) | No | Base64 encoded binary JPEG or PNG image |
| `maxFaceCount` | integer | No | Maximum number of faces to be processed (default: 1) |
**Response Example:**
```json
{
"faces": [
{
"face": {
"confidence": 0.9987,
"boundingBox": {
"x": 120,
"y": 80,
"width": 200,
"height": 250
}
},
"gender": "Male"
}
],
"unprocessedFaceCount": 0
}
```
**Response Fields:**
| Field Path | Type | Description |
|------------|------|-------------|
| `faces` | array (nullable) | The faces that were processed and their gender detection results |
| `faces[].face` | object | Face detection information |
| `faces[].face.confidence` | number | Face detection score with value range [0.0, 1.0] (higher is better) |
| `faces[].face.boundingBox` | object | Bounding box of the detected face |
| `faces[].face.boundingBox.x` | integer | Horizontal position of the detected face bounding box |
| `faces[].face.boundingBox.y` | integer | Vertical position of the detected face bounding box |
| `faces[].face.boundingBox.width` | integer | Width of the detected face bounding box |
| `faces[].face.boundingBox.height` | integer | Height of the detected face bounding box |
| `faces[].gender` | string | Detected gender (Male or Female) |
| `unprocessedFaceCount` | integer | The number of faces that were not processed due to the maximum face count limit |
**Example Request:**
```bash
curl -X POST "https://demographic-estimation-api-eu.realeyes.ai/v1/demographic-estimation/get-gender" \
-H "Authorization: ApiKey API-KEY-FROM-DEV-CONSOLE" \
-H "Content-Type: application/json" \
-d '{
"image": {
"bytes": "/9j/4AAQSkZJRgABAQEAYABgAAD..."
},
"maxFaceCount": 5
}'
```
**Response Codes:**
- `200` - Success
- `400` - Bad Request - Invalid image format, missing required fields, or invalid parameters
- `401` - Unauthorized - Missing or invalid authentication
Emotion Attention
https://verifeye-docs.realeyes.ai/on-prem-docker/emotion-attention/
# Realeyes Guide for Emotion Attention API
## Overview
This guide presents the requirements for acquiring, running and using the docker image of the Emotion Attention API service.
---
## Changelog
**Version 1.0:** Initial version.
---
## Accessing and pulling the latest docker image
You must do the first 2 steps only once per user/computer.
### Prerequisites
It is required that you have AWS CLI installed. This command is supported using the latest version of AWS CLI version 2 or in v1.17.10 or later of AWS CLI version 1.
See how to: [Install the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
### Configure AWS credential profile
You should have previously received your access key ID and Secret Access Key from Realeyes. Please use them here:
```
aws configure --profile emotionattention
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]:
```
### Get authorization token and pass it to docker login
```
aws ecr get-login-password --profile emotionattention --region eu-west-1 | docker login --username AWS --password-stdin 249265253269.dkr.ecr.eu-west-1.amazonaws.com
```
The get-login-password command retrieves and displays an authentication token using the GetAuthorizationToken API -- you will use this token to authenticate to an Amazon ECR registry. You can pass the authorization token to the login command of the container client of your preference, such as the Docker CLI. After you have authenticated to an Amazon ECR registry with this command, you can use the client to pull images from that registry as long as your IAM principal has access to do so before the token expires. **NOTE:** The authorization token is valid for 12 hours.
### Pull the latest docker image
```
docker pull 249265253269.dkr.ecr.eu-west-1.amazonaws.com/verifeye/emotion-attention-api:latest
```
---
## Running the image
The service requires an activation key.
Set:
```
ACTIVATION_KEY=
```
You need to request the activation key from Realeyes.
### Run with docker
Run the container with the following command:
```
docker run --rm -ti -p 8080:8080/tcp \
-e ACTIVATION_KEY= \
--read-only \
--pids-limit=128 \
--security-opt=no-new-privileges \
--memory=16G \
249265253269.dkr.ecr.eu-west-1.amazonaws.com/verifeye/emotion-attention-api:latest
```
### Run with docker compose
Alternatively one can use the following docker-compose.yaml:
```yaml
services:
emotion-attention-api:
image: 249265253269.dkr.ecr.eu-west-1.amazonaws.com/verifeye/emotion-attention-api:latest
environment:
- ACTIVATION_KEY=
ports:
- 8080:8080
read_only: true
security_opt:
- "no-new-privileges"
deploy:
resources:
limits:
pids: 128
memory: 16G
```
---
## Interactive API Documentation (Swagger UI)
Once the service is running, you can access the interactive API documentation at:
```
http://localhost:8080/swagger/index.html
```
This Swagger UI provides a **living documentation** of the API where you can:
- Browse all available endpoints with their detailed descriptions
- View request/response schemas and example payloads
- **Try out the API directly from your browser** – send real requests and see the responses in real-time
- Explore error codes and response formats
This is the recommended way to get familiar with the API and test your integration during development.
---
## API overview
The Emotion Attention API service provides REST API endpoints for emotion and attention detection.
Below is the outline of the API, while a more detailed documentation is available on the Swagger UI (see above).
### Detect Emotions and Attention
Returns whether a face was detected and, for the dominant face in the image, the detected emotions, attention state, and facial landmarks.
**Endpoint:** `POST /v1/emotion-attention/detect`
**Authentication:** API Key or Bearer Token
**Request Body:**
```json
{
"image": {
"bytes": "base64-encoded-image-string",
"url": null
}
}
```
**Request Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `image` | object | Yes | Image data provided as URL or Base64 encoded bytes |
| `image.url` | string (nullable) | No | URL of a JPEG or PNG image |
| `image.bytes` | string (nullable) | No | Base64 encoded binary JPEG or PNG image |
**Response Example:**
```json
{
"emotionsAttention": {
"hasFace": true,
"presence": true,
"eyesOnScreen": true,
"attention": true,
"confusion": false,
"contempt": false,
"disgust": false,
"happy": true,
"empathy": false,
"surprise": false
},
"landmarks": {
"scale": 1.23,
"roll": -2.5,
"yaw": 5.3,
"pitch": -1.2,
"translate": {
"x": 320.5,
"y": 240.8
},
"landmarks2D": [
{ "x": 310.2, "y": 235.6 },
{ "x": 330.8, "y": 236.1 }
],
"landmarks3D": [
{ "x": 0.12, "y": -0.05, "z": 0.98 },
{ "x": 0.15, "y": -0.04, "z": 0.97 }
],
"isGood": true
}
}
```
**Response Fields:**
| Field Path | Type | Description |
|------------|------|-------------|
| `emotionsAttention` | object | Results of analyzing image for facial presence, attention, and emotional states |
| `emotionsAttention.hasFace` | boolean (nullable) | Whether a face is detected in the image (null means it could not be determined reliably) |
| `emotionsAttention.presence` | boolean (nullable) | Whether a person is present in the image (null means it could not be determined reliably) |
| `emotionsAttention.eyesOnScreen` | boolean (nullable) | Whether the person's eyes are on the screen (null means it could not be determined reliably) |
| `emotionsAttention.attention` | boolean (nullable) | Whether the person is attentive (null means it could not be determined reliably) |
| `emotionsAttention.confusion` | boolean (nullable) | Whether confusion emotion is detected (null means it could not be determined reliably) |
| `emotionsAttention.contempt` | boolean (nullable) | Whether contempt is detected (null means it could not be determined reliably) |
| `emotionsAttention.disgust` | boolean (nullable) | Whether disgust is detected (null means it could not be determined reliably) |
| `emotionsAttention.happy` | boolean (nullable) | Whether happiness is detected (null means it could not be determined reliably) |
| `emotionsAttention.empathy` | boolean (nullable) | Whether empathy is detected (null means it could not be determined reliably) |
| `emotionsAttention.surprise` | boolean (nullable) | Whether surprise is detected (null means it could not be determined reliably) |
| `landmarks` | object | Result of facial landmark detection, including pose, scale, and landmark positions in 2D and 3D space |
| `landmarks.scale` | number | Scale of the face |
| `landmarks.roll` | number | Roll pose angle |
| `landmarks.yaw` | number | Yaw pose angle |
| `landmarks.pitch` | number | Pitch pose angle |
| `landmarks.translate` | object | Translation coordinates in 2D space |
| `landmarks.translate.x` | number | The X axis coordinate of the head center in image space |
| `landmarks.translate.y` | number | The Y axis coordinate of the head center in image space |
| `landmarks.landmarks2D` | array (nullable) | Position of the 49 landmarks, in image coordinates |
| `landmarks.landmarks2D[].x` | number | The X axis coordinate of a landmark point in 2D space |
| `landmarks.landmarks2D[].y` | number | The Y axis coordinate of a landmark point in 2D space |
| `landmarks.landmarks3D` | array (nullable) | Position of the 49 landmarks, in an un-scaled face-centered 3D space |
| `landmarks.landmarks3D[].x` | number | The X axis coordinate of a landmark point in 3D space |
| `landmarks.landmarks3D[].y` | number | The Y axis coordinate of a landmark point in 3D space |
| `landmarks.landmarks3D[].z` | number | The Z axis coordinate of a landmark point in 3D space |
| `landmarks.isGood` | boolean | Whether the tracking is good quality or not |
**Example Request:**
```bash
curl -X POST "https://emotion-attention-api-eu.realeyes.ai/v1/emotion-attention/detect" \
-H "Authorization: ApiKey API-KEY-FROM-DEV-CONSOLE" \
-H "Content-Type: application/json" \
-d '{
"image": {
"bytes": "/9j/4AAQSkZJRgABAQEAYABgAAD..."
}
}'
```
**Response Codes:**
- `200` - Success
- `400` - Bad Request - Invalid image format, missing required fields, or invalid parameters
- `401` - Unauthorized - Missing or invalid authentication
Face Verification
https://verifeye-docs.realeyes.ai/on-prem-docker/face-verification/
# Realeyes Guide for Face Verification API
## Overview
This guide presents the requirements for acquiring, running and using the docker image of the Face Verification API service.
---
## Changelog
**Version 1.0:** Initial version.
---
## Accessing and pulling the latest docker image
You must do the first 2 steps only once per user/computer.
### Prerequisites
It is required that you have AWS CLI installed. This command is supported using the latest version of AWS CLI version 2 or in v1.17.10 or later of AWS CLI version 1.
See how to: [Install the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
### Configure AWS credential profile
You should have previously received your access key ID and Secret Access Key from Realeyes. Please use them here:
```
aws configure --profile faceverification
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]:
```
### Get authorization token and pass it to docker login
```
aws ecr get-login-password --profile faceverification --region eu-west-1 | docker login --username AWS --password-stdin 249265253269.dkr.ecr.eu-west-1.amazonaws.com
```
The get-login-password command retrieves and displays an authentication token using the GetAuthorizationToken API -- you will use this token to authenticate to an Amazon ECR registry. You can pass the authorization token to the login command of the container client of your preference, such as the Docker CLI. After you have authenticated to an Amazon ECR registry with this command, you can use the client to pull images from that registry as long as your IAM principal has access to do so before the token expires. **NOTE:** The authorization token is valid for 12 hours.
### Pull the latest docker image
```
docker pull 249265253269.dkr.ecr.eu-west-1.amazonaws.com/verifeye/face-verification-api:latest
```
---
## Running the image
The service requires an activation key.
Set:
```
ACTIVATION_KEY=
```
You need to request the activation key from Realeyes.
### Run with docker
Run the container with the following command:
```
docker run --rm -ti -p 8080:8080/tcp \
-e ACTIVATION_KEY= \
--read-only \
--pids-limit=128 \
--security-opt=no-new-privileges \
--memory=16G \
249265253269.dkr.ecr.eu-west-1.amazonaws.com/verifeye/face-verification-api:latest
```
### Run with docker compose
Alternatively one can use the following docker-compose.yaml:
```yaml
services:
face-verification-api:
image: 249265253269.dkr.ecr.eu-west-1.amazonaws.com/verifeye/face-verification-api:latest
environment:
- ACTIVATION_KEY=
ports:
- 8080:8080
read_only: true
security_opt:
- "no-new-privileges"
deploy:
resources:
limits:
pids: 128
memory: 16G
```
---
## Interactive API Documentation (Swagger UI)
Once the service is running, you can access the interactive API documentation at:
```
http://localhost:8080/swagger/index.html
```
This Swagger UI provides a **living documentation** of the API where you can:
- Browse all available endpoints with their detailed descriptions
- View request/response schemas and example payloads
- **Try out the API directly from your browser** – send real requests and see the responses in real-time
- Explore error codes and response formats
This is the recommended way to get familiar with the API and test your integration during development.
---
## API overview
The Face Verification API service provides the following REST API endpoints:
- detect-faces
- get-face-embeddings
- compare-face-embeddings
Below is the outline of the API, while a more detailed documentation is available on the Swagger UI (see above).
### Detect Faces
Returns a list of detected faces on the provided image with their respective bounding boxes.
**Endpoint:** `POST /v1/face-verification/detect-faces`
**Authentication:** API Key or Bearer Token
**Request Body:**
```json
{
"image": {
"bytes": "base64-encoded-image-string",
"url": null
},
"maxFaceCount": 10
}
```
**Request Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `image` | object | Yes | The image to process |
| `image.url` | string (nullable) | No | URL of a jpeg or png image |
| `image.bytes` | string (nullable) | No | Base 64 string encoded binary jpeg or png image |
| `maxFaceCount` | integer | No | Maximum number of faces to detect in the image |
**Response Example:**
```json
{
"faces": [
{
"confidence": 0.9876,
"boundingBox": {
"x": 120,
"y": 80,
"width": 200,
"height": 250
}
}
],
"unprocessedFaceCount": 0
}
```
**Response Fields:**
| Field Path | Type | Description |
|------------|------|-------------|
| `faces` | array (nullable) | Faces found on the image |
| `faces[].confidence` | number | Face detection score with value range [0.0, 1.0] (higher is better) |
| `faces[].boundingBox` | object | Model for the bounding box of a detected face |
| `faces[].boundingBox.x` | integer | Horizontal position of the detected face bounding box |
| `faces[].boundingBox.y` | integer | Vertical position of the detected face bounding box |
| `faces[].boundingBox.width` | integer | Width of the detected face bounding box |
| `faces[].boundingBox.height` | integer | Height of the detected face bounding box |
| `unprocessedFaceCount` | integer | Number of faces found on the image but were not returned (because the max_faces request parameter filtered them out) |
**Example Request:**
```bash
curl -X POST "https://face-verification-api-eu.realeyes.ai/v1/face-verification/detect-faces" \
-H "Authorization: ApiKey API-KEY-FROM-DEV-CONSOLE" \
-H "Content-Type: application/json" \
-d '{
"image": {
"bytes": "/9j/4AAQSkZJRgABAQEAYABgAAD..."
},
"maxFaceCount": 10
}'
```
**Response Codes:**
- `200` - Returns the detected faces results
---
### Get Face Embeddings
Returns a list of face embeddings for all the detected faces in the provided image.
**Endpoint:** `POST /v1/face-verification/get-face-embeddings`
**Authentication:** API Key or Bearer Token
**Request Body:**
```json
{
"image": {
"bytes": "base64-encoded-image-string",
"url": null
},
"maxFaceCount": 1
}
```
**Request Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `image` | object | Yes | The image to process |
| `image.url` | string (nullable) | No | URL of a jpeg or png image |
| `image.bytes` | string (nullable) | No | Base 64 string encoded binary jpeg or png image |
| `maxFaceCount` | integer | No | Maximum number of faces to get the embedding on |
**Response Example:**
```json
{
"faces": [
{
"face": {
"confidence": 0.9876,
"boundingBox": {
"x": 120,
"y": 80,
"width": 200,
"height": 250
}
},
"embedding": [0.123, -0.456, 0.789]
}
],
"unprocessedFaceCount": 0
}
```
**Response Fields:**
| Field Path | Type | Description |
|------------|------|-------------|
| `faces` | array (nullable) | Faces found on the image |
| `faces[].face` | object | Model for face detection |
| `faces[].face.confidence` | number | Face detection score with value range [0.0, 1.0] (higher is better) |
| `faces[].face.boundingBox` | object | Model for the bounding box of a detected face |
| `faces[].face.boundingBox.x` | integer | Horizontal position of the detected face bounding box |
| `faces[].face.boundingBox.y` | integer | Vertical position of the detected face bounding box |
| `faces[].face.boundingBox.width` | integer | Width of the detected face bounding box |
| `faces[].face.boundingBox.height` | integer | Height of the detected face bounding box |
| `faces[].embedding` | array (nullable) | Face verification embedding of the face |
| `unprocessedFaceCount` | integer | Number of faces found on the image but were not calculated the embedding on (because the max_faces request parameter filtered them out) |
**Example Request:**
```bash
curl -X POST "https://face-verification-api-eu.realeyes.ai/v1/face-verification/get-face-embeddings" \
-H "Authorization: ApiKey API-KEY-FROM-DEV-CONSOLE" \
-H "Content-Type: application/json" \
-d '{
"image": {
"bytes": "/9j/4AAQSkZJRgABAQEAYABgAAD..."
},
"maxFaceCount": 1
}'
```
**Response Codes:**
- `200` - Returns the face embeddings results
---
### Compare Face Embeddings
Returns the similarity between two face embeddings as an integer between 0 and 100.
**Endpoint:** `POST /v1/face-verification/compare-face-embeddings`
**Authentication:** API Key or Bearer Token
**Request Body:**
```json
{
"embedding1": [0.123, -0.456, 0.789],
"embedding2": [0.125, -0.450, 0.792]
}
```
**Request Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `embedding1` | array (nullable) | Yes | Embedding to compare |
| `embedding2` | array (nullable) | Yes | Embedding to compare with |
**Response Example:**
```json
{
"similarity": 85
}
```
**Response Fields:**
| Name | Type | Description |
|------|------|-------------|
| `similarity` | integer | Similarity between the two embeddings with value range [-1, 100] (higher is better). Reject any matches where similarity is less than 70.
**Threshold reference** (computed using extensive in-the-wild datasets):
• **95** corresponds to FPR 1e-06 (or better)
• **90** corresponds to FPR 1e-05
• **80** corresponds to FPR 1e-4
• **70** corresponds to FPR 1e-3 |
**Example Request:**
```bash
curl -X POST "https://face-verification-api-eu.realeyes.ai/v1/face-verification/compare-face-embeddings" \
-H "Authorization: ApiKey API-KEY-FROM-DEV-CONSOLE" \
-H "Content-Type: application/json" \
-d '{
"embedding1": [0.123, -0.456, 0.789],
"embedding2": [0.125, -0.450, 0.792]
}'
```
**Response Codes:**
- `200` - Returns the similarity result
Index
https://verifeye-docs.realeyes.ai/on-prem-docker/
# VerifEye On-Prem API (Docker)
This section contains documentation for running VerifEye APIs as Docker containers in your own infrastructure.
---
## Available APIs
### [Emotion Attention API](https://verifeye-docs.realeyes.ai/emotion-attention)
Guide for acquiring, running and using the docker image of the Emotion Attention API service.
### [Face Verification API](https://verifeye-docs.realeyes.ai/face-verification)
Guide for acquiring, running and using the docker image of the Face Verification API service.
### [Demographic Estimation API](https://verifeye-docs.realeyes.ai/demographic-estimation)
Guide for acquiring, running and using the docker image of the Demographic Estimation API service.
Liveness Detection
https://verifeye-docs.realeyes.ai/on-prem-docker/liveness-detection/
# Realeyes Guide for Liveness Detection API
## Overview
This guide presents the requirements for acquiring, running and using the docker image of the Liveness Detection API service.
---
## Changelog
**Version 1.0:** Initial version.
---
## Accessing and pulling the latest docker image
You must do the first 2 steps only once per user/computer.
### Prerequisites
It is required that you have AWS CLI installed. This command is supported using the latest version of AWS CLI version 2 or in v1.17.10 or later of AWS CLI version 1.
See how to: [Install the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
### Configure AWS credential profile
You should have previously received your access key ID and Secret Access Key from Realeyes. Please use them here:
```
aws configure --profile livenessdetection
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]:
```
### Get authorization token and pass it to docker login
```
aws ecr get-login-password --profile livenessdetection --region eu-west-1 | docker login --username AWS --password-stdin 249265253269.dkr.ecr.eu-west-1.amazonaws.com
```
The get-login-password command retrieves and displays an authentication token using the GetAuthorizationToken API -- you will use this token to authenticate to an Amazon ECR registry. You can pass the authorization token to the login command of the container client of your preference, such as the Docker CLI. After you have authenticated to an Amazon ECR registry with this command, you can use the client to pull images from that registry as long as your IAM principal has access to do so before the token expires. **NOTE:** The authorization token is valid for 12 hours.
### Pull the latest docker image
```
docker pull 249265253269.dkr.ecr.eu-west-1.amazonaws.com/verifeye/liveness-detection-api:latest
```
---
## Running the image
The service requires an activation key.
Set:
```
ACTIVATION_KEY=
```
You need to request the activation key from Realeyes.
### Run with docker
Run the container with the following command:
```
docker run --rm -ti -p 8080:8080/tcp \
-e ACTIVATION_KEY= \
--read-only \
--pids-limit=128 \
--security-opt=no-new-privileges \
--memory=16G \
249265253269.dkr.ecr.eu-west-1.amazonaws.com/verifeye/liveness-detection-api:latest
```
### Run with docker compose
Alternatively one can use the following docker-compose.yaml:
```yaml
services:
liveness-detection-api:
image: 249265253269.dkr.ecr.eu-west-1.amazonaws.com/verifeye/liveness-detection-api:latest
environment:
- ACTIVATION_KEY=
ports:
- 8080:8080
read_only: true
security_opt:
- "no-new-privileges"
deploy:
resources:
limits:
pids: 128
memory: 16G
```
---
## Interactive API Documentation (Swagger UI)
Once the service is running, you can access the interactive API documentation at:
```
http://localhost:8080/swagger/index.html
```
This Swagger UI provides a **living documentation** of the API where you can:
- Browse all available endpoints with their detailed descriptions
- View request/response schemas and example payloads
- **Try out the API directly from your browser** - send real requests and see the responses in real-time
- Explore error codes and response formats
This is the recommended way to get familiar with the API and test your integration during development.
---
## API overview
The Liveness Detection API service provides REST API endpoints ToDo: Finish this sentence.
Below is the outline of the API, while a more detailed documentation is available on the Swagger UI (see above).
### Check Video Liveness
Checks the liveness of a video. The video should contain a single person face. You can send base64 encoded video or a video url. The face on the video should be in an upright position. Sideways or upside-down faces are not supported. The preferred input video format is webm (VP8 codec). Maximum video length 10 seconds. Maximum video size is 2,000,000 bytes.
**Endpoint:** `POST /v1/liveness/check`
**Authentication:** API Key or Bearer Token
**Request Body:**
```json
{
"video": {
"bytes": "base64-encoded-video-string",
"url": null
},
"includeBestFrameWithFace": false
}
```
**Request Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `video` | object | Yes | The video to process |
| `video.url` | string (nullable) | No | URL of a video |
| `video.bytes` | string (nullable) | No | Base 64 string encoded binary video |
| `includeBestFrameWithFace` | boolean | No | Gets or sets a value indicating whether the best frame containing a detected face should be included in the results |
**Response Example:**
```json
{
"face": {
"confidence": 0.9987,
"boundingBox": {
"x": 120,
"y": 80,
"width": 200,
"height": 250
}
},
"hasFace": true,
"unprocessedFaceCount": 0,
"isLive": true,
"bestFrameWithFace": null
}
```
**Response Fields:**
| Field Path | Type | Description |
|------------|------|-------------|
| `face` | object | Model for face detection |
| `face.confidence` | number | Face detection score with value range [0.0, 1.0] (higher is better) |
| `face.boundingBox` | object | Model for the bounding box of a detected face |
| `face.boundingBox.x` | integer | Horizontal position of the detected face bounding box |
| `face.boundingBox.y` | integer | Vertical position of the detected face bounding box |
| `face.boundingBox.width` | integer | Width of the detected face bounding box |
| `face.boundingBox.height` | integer | Height of the detected face bounding box |
| `hasFace` | boolean | Indicates whether a face was found in the image |
| `unprocessedFaceCount` | integer | In case more than one face was detected, only the dominant face will be used for the recognition. This count indicates how many faces were not processed |
| `isLive` | boolean (nullable) | Describes whether the face on the image is live or not. Can be null, in case NO face was detected |
| `bestFrameWithFace` | string (nullable) | Best frame with face extracted from the video in Base64 format |
**Example Request:**
```bash
curl -X POST "https://liveness-detection-api-eu.realeyes.ai/v1/liveness/check" \
-H "Authorization: ApiKey API-KEY-FROM-DEV-CONSOLE" \
-H "Content-Type: application/json" \
-d '{
"video": {
"bytes": "UklGRiQAAABXQVZFZm10IBAAAAABAAEA..."
},
"includeBestFrameWithFace": false
}'
```
**Response Codes:**
- `200` - Returns the liveness check result
Index
https://verifeye-docs.realeyes.ai/redirect/concept/
This section describes the core concepts you will encounter when integrating with VerifEye's Redirect.
## Verification session
A **verification session** represents a single end-user attempt.
- A session has a unique identifier (`reVerificationSessionId` in the final redirect URL).
- The session aggregates the individual verifier outcomes into an overall verification result.
## Verification
A **Verification** represents a named, configurable verification experience. It defines how the verification flow must work (rules, enabled verifiers, thresholds, UX options, etc.), and it may also reference or contain a **face collection** used by the Face Recognition verifier.
A verification contains the following configurations:
- Verifier configurations
- Redirect configurations
- Result parameter configurations
- Security configurations
- Session Override configurations
### One-time setup (create once, reuse many times)
The API endpoints that create or modify a Verification are **one-time setup** operations and should be clearly labeled in the documentation as such. A Verification must typically be created **only once per face-collection scope**, either:
- via the developer/admin portal (recommended for most teams), or
- via a **single programmatic call** from a secure backend/service.
After creation, the same Verification configuration must be **reused** for all end-user sessions in that scope by referencing its `verification_id` (or `verification_name`, depending on the API design).
### What “scope” means (and why it matters)
A Verification is a configuration object that is tied to a particular **face collection scope**, which depends on your use case:
- **Login / authentication for an entire user base:**
You typically create **one Verification** for the whole user base (one shared face collection scope), and reuse it for every login attempt.
- **Project- or campaign-based access control (separate populations):**
You create **one Verification per project/campaign scope**, for example:
- - protecting a specific survey on a survey platform (each survey can have its own scope), or
- - a limited-stock promotion (e.g., “Discounted shoes” campaign), where you want to admit new participants only until inventory lasts—each campaign/promo can be isolated via its own face collection scope and Verification.
!!!warning Do not split one user base across multiple Verifications
Each Verification has its **own face collection scope** — a user known to one Verification is unknown to another. Creating multiple Verifications for the **same user base** (for example, one for enrollment and a separate one for authentication) is **not recommended**: the second Verification will not see the enrollment from the first and will silently auto-enroll the user again, defeating the separation.
For an enrollment-then-authentication flow for the same user base, use a **single Verification** with session-level overrides. See the [User lifecycle](https://verifeye-docs.realeyes.ai/redirect/user-lifecycle/) guide.
!!!
### Security guidance (must be created server-side)
Creating a Verification is a **privileged administrative action** and must be performed from a **trusted, secure environment** (backend, admin service, or portal). It must **not** be created by the end user on the client side.
If a user could create or control their own Verification, they could potentially influence the verification behavior (e.g., choose weaker settings, point to a different face collection, or otherwise manipulate the process). Therefore:
- **Only admin/backend credentials** should be allowed to call “create/update Verification” endpoints.
- Client applications should only receive a reference to an existing Verification (e.g., `verification_id`) and use it to start verification sessions.
!!!
Every configuration can be easily set either in the Developer Console or via VerifEye Service API.
[!ref target="blank" text="Developer Console"](https://verifeye-console.realeyes.ai/)
[!ref text="VerifEye Service API"](https://verifeye-docs.realeyes.ai/rest-api/verifeye-service-api)
!!!
[!ref text="For more about how to configure Verification, check out Verification configurations page"](https://verifeye-docs.realeyes.ai/redirect/verification-configurations/)
---
*Last updated: 2026-02-03*
Index
https://verifeye-docs.realeyes.ai/redirect/
# What is VerifEye's Redirect?
Redirect is a hosted user verification SaaS (Software as a Service) that helps you confirm a user’s identity-related signals during a short, guided camera flow.
At a high level, VerifEye:
- guides the user through a browser-based camera experience
- runs one or more configurable **verifiers** (liveness, face recognition, age and gender)
- redirects the user back to your application with the verification outcome in the URL
From an integrator’s perspective the system consists of:
- a **hosted verification page** (served by VerifEye) can be accessed with the provided **verification URL**
- a **target URL** (configured for your Verification) that receives the outcome as query parameters
You do not need to host, deploy, or run the server/client to use the SaaS.
For a detailed breakdown of supported integration patterns (full-page redirect, embedded iFrame, popup), see the **Integration Use Cases** section below.
## Concept
[!ref text="Check out the Concept page"](https://verifeye-docs.realeyes.ai/redirect/concept/)
## Use Cases
[!ref text="Check out the Use Cases page"](https://verifeye-docs.realeyes.ai/redirect/use-cases/)
## Integration Use Cases
[!ref text="Check out the Integration Use Cases page"](https://verifeye-docs.realeyes.ai/redirect/integration-use-cases/)
## User lifecycle
[!ref text="Check out the User lifecycle page"](https://verifeye-docs.realeyes.ai/redirect/user-lifecycle/)
## Security
[!ref text="Check out the Security page"](https://verifeye-docs.realeyes.ai/redirect/security/)
## Verification configuration
[!ref text="Check out Verification configurations page"](https://verifeye-docs.realeyes.ai/redirect/verification-configurations/)
## Webhook
[!ref text="Check out the Webhook page"](https://verifeye-docs.realeyes.ai/redirect/webhook/)
## Parameters
[!ref text="Check out the Parameters page"](https://verifeye-docs.realeyes.ai/redirect/parameters/)
---
*Last updated: 2026-03-31*
Index
https://verifeye-docs.realeyes.ai/redirect/integration-use-cases/
This section describes the integration use cases for VerifEye's Redirect.
## Use cases Verification setup
All the below examples use the following setup:
- Liveness Verifier in Verification mode
- Age Verifier in Threshold Verification mode (Above 18)
- Face Recognition Verifier in Calculation Only mode
- Gender Verifier in Calculation Only mode
- They use the same collection
- For testing purposes in this example we disabled `ForceSignedInput` — this is strongly recommended to keep enabled in production environments. For more details, see the [Security page](https://verifeye-docs.realeyes.ai/redirect/security/#incoming-signed-verification-url-request-integrity).
## Use case: Full-page redirect
**When to use**
- simplest integration; users leave your site temporarily and come back via redirect
**How it works (conceptually)**
- you send the user to the VerifEye verification URL
- the user completes the verification
- VerifEye redirects the browser to your result URL with the outcome in the query string parameters
**Recommended**
- validate `reSignature` server-side to avoid result tampering
[!ref text="For more information about the signature, check out the Security page"](https://verifeye-docs.realeyes.ai/redirect/security/)
**Example**
In this example we use the EU service.
- Verification URL: https://verifeye-service-eu.realeyes.ai/verification/e4fc930b-d780-47e3-ae4c-0d5d2f22e54e _(note: `ForceSignedInput` is disabled on this verification for testing — do not do this in production)_
- Target URL (configured for the Verification): https://example.com
- Result URL example (Target URL with the outcome for a specific session in the query string parameters):
```
https://example.com/?reVerificationSessionId=7a429371-f918-4900-bf1b-14a76e551042&reFaceId=99a9e4e3ac75406ebd638f95bc4f0b30&reVerificationResult=passed&reLivenessResult=passed&reFaceRecognitionResult=passed&reAgeVerificationResult=passed&reAge=31&reGenderVerificationResult=passed&reGender=male&reSignature=70ac1eb0762395c831a09f53f854ca7e9745bf5755b83ed8137ed21dec9c7307
```
[!ref text="Click here to try out" target="blank"](https://verifeye-service-eu.realeyes.ai/verification/e4fc930b-d780-47e3-ae4c-0d5d2f22e54e)
## Use case: Embedded iFrame
**When to use**
- you want the verification flow embedded in your page without full navigation
**How it works (conceptually)**
- you embed the hosted verification URL in an iFrame
- after completion, VerifEye navigates to a result page that posts a message to the parent window containing:
- `redirectedTo`: the final result URL
**Recommended**
- validate `event.origin` on the host page
- validate `reSignature` on your backend if you need tamper detection
[!ref text="For more information about origin check and the signature, check out the Security page"](https://verifeye-docs.realeyes.ai/redirect/security/)
**Example**
- Verification URL: https://verifeye-service-eu.realeyes.ai/verification/3bb1fb37-9d3a-423f-b5bc-1790a329f117 _(note: `ForceSignedInput` is disabled on this verification for testing — do not do this in production)_
- Target URL (configured for the Verification): https://verifeye-docs.realeyes.ai/iframe_popup_result_example.html
- Result URL example (Target URL with the outcome for a specific session in the query string parameters):
```
https://verifeye-docs.realeyes.ai/iframe_popup_result_example.html?reVerificationSessionId=d7c09541-03c1-403e-9b3c-146468657f27&reFaceId=99a9e4e3ac75406ebd638f95bc4f0b30&reVerificationResult=passed&reLivenessResult=passed&reFaceRecognitionResult=passed&reAgeVerificationResult=passed&reAge=31&reGenderVerificationResult=passed&reGender=male&reSignature=462cfda7b1999f243867d5a2ab1725624ca7d85d807b7e8d3cb1f285648c0810
```
[!ref text="Click here to try out" target="blank"](https://verifeye-docs.realeyes.ai/static/iframe_example.html)
The following file is a minimum example for how to use VerifEye iFrame integration
:::code source="/static/iframe_example.html" language="js" title="iframe_example.html" :::
This file shows what is set for the Target URL. This is a technical file that is responsible to receive the result query string parameters and send back the whole URL to the hosted site via `postMessage`.
:::code source="/static/iframe_popup_result_example.html" language="js" title="iframe_popup_result_example.html" :::
## Use case: Widget (Drop-in Snippet)
**When to use**
- for experiments and demos only — **not intended for production use**
- you want to quickly test or showcase the verification flow with minimal setup
**How it works (conceptually)**
- you add the widget `