Skip to content

Using Java API

IDLive Face Python API is available in the package net.idrnd.facesdk:

import net.idrnd.facesdk.*;

We support Java 8 and newer. Desktop releases support x86 64-bit only. Android AAR releases support Armv7-A, Armv8-A and x86.

Package location

The jar file with the package is located in the SDK's libs/java directory. You need to add the jar to the classpath when running java or javac:

java -cp "/opt/idliveface/libs/java/*" ...

As the Java package is backed by native libraries you also need to specify their location. They reside in the SDK's libs directory. The approach is different depending on the operating system used:

  • For Linux you need to set java.library.path property:

    java -cp "/opt/idliveface/libs/java/*" -Djava.library.path="/opt/idliveface/libs" ...
    
  • For Windows you need to add the directory to the Path environment variable. Please refer to the DLL discovery article.

It is only required when you run a Java program. The compiler doesn't need the native libraries.

Closable objects

Some of the API objects are backed by the native memory and implement AutoCloseable interface. You always need to close them, either manually with the close method, or using the try-with-resources statement:

try (Image image = new Image(path)) {
    ...
}

Failing to do so can cause a memory leak.

List of AutoClosable classes
  • DetectEngine
  • Image
  • InitConfig
  • Pipeline
  • QualityEngine

Basics

Initialize pipeline

The main entity of the IDLive Face API is a pipeline (represented by the class Pipeline). The SDK contains several pipelines, each one is described by the configuration file stored in the data/pipelines directory. To initialize a pipeline first you need to load its configuration. For example to load the configuration for the Astraea pipeline do:

String IDLIVEFACE_HOME = "/opt/idliveface";
InitConfig config = new InitConfig(IDLIVEFACE_HOME + "/data/pipelines/astraea.json");

List of all available pipelines can be found in the Pipelines article.

Next use the loaded configuration to create a pipeline:

Pipeline pipeline = new Pipeline("ConfigurablePipeline", config);

Load image

To load an image into the memory you need to create an Image object that will contain the image's content. The image can be loaded from a file:

Image image = new Image(IDLIVEFACE_HOME + "/data/images/real_face.jpg");

Or from a memory buffer:

byte[] imageBytes = ...
Image imageFromArray = new Image(imageBytes);

IDLive Face supports JPEG, PNG and other image formats.

Perform liveness check

To perform a liveness check call the pipeline's checkLiveness method:

PipelineResult result = pipeline.checkLiveness(image);

The result contains measurements of the image's liveness and quality. The main factor to decide if the image is live or spoofed is the result.livenessResult.probability. The image can be considered live if the probability is higher than 0.5:

if (result.getLivenessResult().getProbability() >= 0.5) {
    // Image is live
} else {
    // Image is spoofed
}

Additional factor to take into consideration is result.qualityResult.score. It measures how "appropriate" the image is for the liveness check. Images with the quality values lower than 0.5 should generally be rejected:

if (result.getQualityResult().getScore() < 0.5) {
    // Image has a bad quality, reject it
}

Both measurements are float values in a range of [0,1]. The detailed explanation of the results of the liveness check can be found in the Liveness check result article.

Error handling

When an error occurs the IDLive Face API throws the FaceException exception. Generally you should wrap all invocations of the API into a try-catch block:

try {
    ...
} catch (FaceException e) {
    System.out.println("Error code: " + e.getStatus() + ", message: " + e.getMessage());
}

The status of the exception is an enumeration you can use to react to specific errors. For example when the Pipeline.checkLiveness rejects an image it returns statuses that classify the rejection reason:

switch (e.getStatus()) {
    case FACE_TOO_SMALL:
        // Inform a user to get closer to a camera.
        break;
    ...
}

The list of all statuses is available in the Error statuses article.

Example program

Here is a program that uses everything described in the previous section:

Example.java
import net.idrnd.facesdk.*;

public class Example {
    private static final String IDLIVEFACE_HOME = "/opt/idliveface";

    private static Pipeline createPipeline() {
        System.out.println("Initializing...");
        try (InitConfig config = new InitConfig(IDLIVEFACE_HOME + "/data/pipelines/astraea.json")) {
            return new Pipeline("ConfigurablePipeline", config);
        }
    }

    private static void processLivenessResult(PipelineResult result) {
        System.out.println("Result: " + result);

        if (result.getQualityResult().getScore() < 0.5) {
            System.out.println("Image has a bad quality");
        } else if (result.getLivenessResult().getProbability() >= 0.5) {
            System.out.println("Image is genuine");
        } else {
            System.out.println("Image is spoofed");
        }
    }

    public static void main(String[] args) {
        try (Pipeline pipeline = createPipeline()) {
            System.out.println("\nChecking liveness for real_face.jpg");

            try (Image image = new Image(IDLIVEFACE_HOME + "/examples/images/real_face.jpg")) {
                PipelineResult result = pipeline.checkLiveness(image);
                processLivenessResult(result);
            }

            System.out.println("\nChecking liveness for spoof_face.jpg");

            try (Image image = new Image(IDLIVEFACE_HOME + "/examples/images/spoof_face.jpg")) {
                PipelineResult result = pipeline.checkLiveness(image);
                processLivenessResult(result);
            }

            System.out.println("\nChecking liveness for face_not_found.jpg");

            try (Image image = new Image(IDLIVEFACE_HOME + "/examples/images/face_not_found.jpg")) {
                pipeline.checkLiveness(image);
            }

        } catch (FaceException e) {
            System.out.println("Error: " + e.getStatus() + ", message: " + e.getMessage());
        }
    }
}

Download

It performs the liveness check for several example images and prints the following output:

Checking liveness for real_face.jpg
Result: PipelineResult{livenessResult=LivenessResult{score=2.3684978, probability=0.91439337}, qualityResult=QualityResult{score=0.84349936, class_=true}}
Image is genuine

Checking liveness for spoof_face.jpg
Result: PipelineResult{livenessResult=LivenessResult{score=-6.794679, probability=0.0011184647}, qualityResult=QualityResult{score=0.8110471, class_=true}}
Image is spoofed

Checking liveness for face_not_found.jpg
Error: FACE_NOT_FOUND, message: Failed to detect face

Using on Android

To access the data files you first need to extract them with the AssetsExtractor utility:

import net.idrnd.android.media.AssetsExtractor;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        AssetsExtractor assetsExtractor = new AssetsExtractor(getApplicationContext());
        String IDLIVEFACE_HOME = assetsExtractor.extractAssets().getPath();
    }
}

The extractor will copy the data files to the device filesystem, after which they can be used as a regular files:

InitConfig config = new InitConfig(IDLIVEFACE_HOME + "/data/pipelines/persephone.json");
Pipeline pipeline = new Pipeline("ConfigurablePipeline", config);

Files are only extracted at the first run of the application, and then cached in the filesystem.

Note that mobile releases use a different pipeline named Persephone.