LIQA Light 1.2

Doc v2

LIQA is a JavaScript library developed by Haut.AI to help companies to standardize the incoming photos of faces. LIQA stands for "Live Image-Quality Assurance" and allows to perform a no-reference image quality assessment. LIQA estimates captured live video stream via a mobile device camera utilizing only the device's computational capabilities and returns feedback to a user to improve the quality of an image.

LIQA Light is a highly optimized and simplified package for running the analysis on the widest range of devices with minimal delays and minimum requirements. LIQA Light performs a non-verbose analysis of face recognition and face illumination and provides a human-readable status of quality. The settings are defined based on Haut.AI’s expertise in facial skin analysis.

Connect to NPM registry

Request access and credentials

LIQA Light is distributed as a private NPM package with simple installation. To get access to the registry, please:

  • Go to the haut.ai website, to the contact form

  • Leave us a message with a short description of your company, planned usage (test of technology embedding, small / medium / large business, etc.), and a contact e-mail so we could get back to you

After approving the request, you will be contacted via e-mail by Haut.AI and receive credentials for accessing the registry. For authorization, you will get your personal token as a long string:

  • password - BASE64_ENCODED_PERSONAL_ACCESS_TOKEN

  • .npmrc file

  • registry_link - URL to set connection to the repository (smth like https://pkgs.dev.azure.com/haut-ai/.../npm/registry/)

  • Please, pay attention that the credentials always have an expiration date.

  • Please, store the provided credentials securely on your side

Create authorization files

  • Go to your system Home directory:

    • for Windows (by default, installed on C drive): C:\Users\%username%

    • for Linux and MacOS: $HOME/

  • Put the provided .npmrc file in your Home directory

  • If you already have .npmrc file, open it and append the lines from the shared by Haut.AI

  • Put your password instead of "<BASE64_ENCODED_PERSONAL_ACCESS_TOKEN>" placeholder

  • Put your contact e-mail instead of <your contact email>

Install LIQA in your project:

  • Call these commands in your project with the provided to you registry_link

npm config set @liqa:registry=registry_link
npm install --save @liqa/light@^1.2

Update LIQA in your project

Update LIQA to fetch the latest bug fixes:

npm update @liqa/light

Update LIQA to download the latest major version ( ⚠️ may influence API). Here x is the latest major version.

npm update @liqa/light^x.0 

Run demo page

The demo page requires Node.js to be installed on your computer.

If Node.js is not installed, please follow the instructions at https://nodejs.org/en/ to correctly install it for your system.

The demo page requires Vue to be installed on your system. Install Vue via command.

npm install -g @vue/cli
  • Now follow to the directory where the LIQA is located

  • Build LIQA package:

cd liqa-light
npm install
  • Then, run the Vue demo:

cd demo
npm install
  • Run the local server:

npm run serve
  • Open localhost:8080 in your browser.

API Methods

static checkCameraAvailable: Promise<void>

The checkCameraAvailable method allows to validate if camera and browser are correctly setup and suitable for launching the LIQA.

LiqaLight.checkCameraAvailable().catch(e => {
    console.error("Camera error: " + e);
});

This method requires access to the device camera and will launch (and then stop) the camera to check that all parameters are correctly setup and all API methods are available in current browser. We recommend calling this method for every start before LiqaLight.init.

We highly recommend to setup a .catch operation on LiqaLight.checkCameraAvailable method with some resulting warning for the end-user. The detected issues with LIQA Light start might be critical and it is better to recommend your user to try one of stable browsers (e.g. Chrome on Android, Safari on iOS) / check their permissions on camera access for different apps, etc.

Unfortunately, LIQA Light can not detect the exact reason why the system fails to provide the full necessary access to camera and its methods.

static init: Promise<void>

The init method is the main API method that plays a role of an entry point and initializesLiqaLight:

liqaLight = LiqaLight.init({
    video: videoElement, 
    canvas: canvasElement,
    size: [width, height],
    strictness: 2,
    jpegCompressionPercantage: 100,
    limittingResolutionValue: 1500
});

Parameter

Description

video: HTMLVideoElement

Video element

<video playsinline controls></video>

CSS:

video {

-webkit-transform: scaleX(-1);

transform: scaleX(-1);

display: none;

}

canvas: HTMLCanvasElement

Canvas element

<canvas></canvas>

size: Array<number>

Set width and height (in pixels) of a stream frame as an array

strictness: number

Ascending strictness of LIQA Light model for quality analysis. Expected values are:1 | 2 | 3

jpegCompressionPercantage: number

JPEG compression level of the final photo. Expected values are numerical in range [50, 100], where 100 (%) is non-compressed photo (maximum weight). The default value is 100.

limittingResolutionValue: number

Value limiting the height (in pixels) of the photo. Expected values are numerical in range [1000, 2000]. The default value is 1500.

play: Promise<void>

The play method starts live video capturing via the frontal camera and image processing at once.

liqaLight.play()
    .catch(error => console.error(error);

captureSelfie: Promise<string>

The captureSelfie method collects a final selfie image and returns it as base64 code. It might be a good idea to show the resulting image to a user and to let him / her confirm or decline (and try once more to take a better image) the image to be sent:

liqaLight.captureSelfie().then(b64selfie => show(b64selfie));

Here is how the preview of an image can be done:

function show(b64selfie) {
    /* img is <img> element */
    img.src = b64selfie;
    img.style.width = window.innerWidth + 'px';
} 

stop: void

The stop method stops the live capturing and all calculations.

liqaLight.stop();

Stream results: data Observable

qualityStatus$: Observable<StatusData>

The qualityStatus$ (RxJS) Observable sends the general status of the current frame quality.

Property

Description

status: string

This parameter indicates an overall status of image quality:

  • Good: image quality is good enough;

  • Medium: medium quality, recommended improving;

  • Poor: poor quality. Most likely it is too dark / too light / highly non-uniform illumination;

  • Bad: low quality. Most likely the face was not detected;

position: boolean

This parameter shows the correctness of

face positioning in the specified area. It returns

true if face is correctly positioned the center

of the frame with right rotation and a good

distance from face to camera;

light: boolean

This parameter shows the correctness of

the face illumination and returns false

if face is too under- / overexposed.

Integration example

HTML elements:

<video playsinline controls ></video>
<canvas></canvas>

CSS:

video {
        -webkit-transform: scaleX(-1);
        transform: scaleX(-1);
        display: none;
}

Initialization:

const liqaLight = await LiqaLight.init(
  { 
    video: videoElement,
    canvas: canvasElement,
    size: [window.innerWidth, window.innerHeight],
    strictness: 3,
  }
);

Data visualization (v1.1):

/* LIQA Light 1.1+ */
liqaLight.qualityStatus$
  .subscribe((options) => {
    if (options.status == "Good") this.statusMsg = "Good Quality";
    else if (options.status == "Medium") this.statusMsg = "Medium Quality";
    else if (options.status == "Poor") this.statusMsg = "Poor Quality";
    else if (options.status == "Bad") this.statusMsg = "Bad Quality";
    
    this.liqaData.position = options.position;
    this.liqaData.light = options.light;

    if (!options.position) {
      this.textWarning = "Position is not okay";
    } else if (!options.light) {
      this.textWarning = "Light is not okay";
    } else {
      this.textWarning = null;
    }
  });

⚠️ For LIQA 1.0 the visualization is limited

/* LIQA Light 1.0+ */
liqaLight.qualityStatus$
  .subscribe((options) => {
    if (options.status == "Good") this.statusMsg = "Good Quality";
    else if (options.status == "Medium") this.statusMsg = "Medium Quality";
    else if (options.status == "Poor") this.statusMsg = "Poor Quality";
    else if (options.status == "Bad") this.statusMsg = "Bad Quality";
    
  });

The statusMsg can also be paired with UI elements modification (depending on your system design):

Now we are ready to start a stream capturing and processing:

liqaLight.play().catch((error) => {
    /* problems with camera setup */
    console.error(error);
}

Selfie logic (img here is an <img> element):

liqaLight.captureSelfie().then(b64selfie => {
        /* get output selfie photo and draw it */
        img.src = b64selfie;
        img.style.width = window.innerWidth + 'px';  
          
}).catch(() => {
        console.warn("LIQA is preparing, please, wait")
});

Last updated