@privateid/ultra-web-sdk-alpha
Version:
CryptoNets WebAssembly SDK
230 lines • 11.7 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
/* eslint-disable import/prefer-default-export */
/* eslint-disable lines-between-class-members */
import { proxy } from 'comlink';
import { detect } from 'detect-browser';
import { callbackTypeEnum, createCallback } from '../../../../createCallback';
import { CameraFaceMode } from '../../../../types';
import { callbackWithImageCreation, defineDimensionsForCanvas, getBaseEnrollConfig, releaseCanvas } from './face.utils';
import { DEFAULT_PREDICT_CONFIG } from '../../support/wasm';
import { getIsSIMD, printLogs } from '../../global/shared.utils';
import { CANVAS_TEST_ID, INVALID_VIDEO_ERROR, LOG_MESSAGES, URL_OVERRIDES } from './face.constants';
export class FaceService {
constructor(wasmService, cameraService) {
this.isSimd = false;
// eslint-disable-next-line class-methods-use-this
this.privid_wasm_result = () => { };
this.faceMode = CameraFaceMode.front;
getIsSIMD().then((simd) => {
this.isSimd = simd;
});
const canvas = document.createElement('canvas');
canvas.setAttribute('id', CANVAS_TEST_ID);
this.canvas = canvas;
this.wasmService = wasmService;
this.cameraService = cameraService;
printLogs('[FaceService] initialized', '');
}
preparePrivdWasmResult(callback, callbackType, image, config) {
const callbackForImageCreation = callbackWithImageCreation(callback, image, false);
this.privid_wasm_result = createCallback({
type: callbackType,
callbackFunction: callbackForImageCreation,
imageData: (config === null || config === void 0 ? void 0 : config.sendImageToJS) ? image : undefined,
});
}
// TODO: Refactor this method to use the canvas from camera service
prepareCanvasAndGetImageData(elementId, useExistingCanvas = false) {
const videoEl = document.getElementById(elementId);
const height = (videoEl === null || videoEl === void 0 ? void 0 : videoEl.videoHeight) || 0;
const width = (videoEl === null || videoEl === void 0 ? void 0 : videoEl.videoWidth) || 0;
if (width === 0)
return { result: INVALID_VIDEO_ERROR };
printLogs(`isValid:`, { height, width });
let canvas;
if (useExistingCanvas) {
canvas = this.canvas;
}
else {
canvas = document.createElement('canvas');
}
canvas.setAttribute('id', CANVAS_TEST_ID);
canvas.setAttribute('height', `${height}`);
canvas.setAttribute('width', `${width}`);
const context = canvas.getContext('2d', { willReadFrequently: true });
if (this.faceMode === CameraFaceMode.front) {
context.translate(width, 0);
context.scale(-1, 1);
}
context.drawImage(videoEl, 0, 0);
const imageData = context.getImageData(0, 0, width, height);
return { imageData, canvas, width, height };
}
runUltraProcess(fn, options) {
return __awaiter(this, void 0, void 0, function* () {
const { callback, image, config = {}, element, returnPortrait = false, useExistingCanvas = false, logMessage = LOG_MESSAGES.ULTRA_PROCESS, callbackType, } = options;
printLogs(`${logMessage}`, '');
const configJSON = Object.keys(config).length > 0 ? Object.assign({}, config) : Object.assign({}, DEFAULT_PREDICT_CONFIG);
if (image) {
this.preparePrivdWasmResult(callback, callbackType, image, config);
return fn([image], this.isSimd, JSON.stringify(configJSON), proxy(this.privid_wasm_result));
}
if (element) {
this.cameraService.setVideoElementId(element);
}
const result = this.prepareCanvasAndGetImageData(this.cameraService.getVideoElementId(), useExistingCanvas);
if ('result' in result)
return result;
const { imageData, canvas } = result;
this.preparePrivdWasmResult(callback, callbackType, imageData, config);
yield fn([imageData], this.isSimd, JSON.stringify(configJSON), proxy(this.privid_wasm_result));
if (returnPortrait) {
return imageData;
}
releaseCanvas(canvas);
return undefined;
});
}
performPredict(options) {
return this.runUltraProcess(this.wasmService.predict, Object.assign(Object.assign({}, options), { callbackType: callbackTypeEnum.predict, logMessage: options.logMessage || LOG_MESSAGES.PREDICT_ONE_FA }));
}
faceLogin(props) {
return __awaiter(this, void 0, void 0, function* () {
return this.performPredict(Object.assign(Object.assign({}, props), { useExistingCanvas: true, logMessage: LOG_MESSAGES.FACE_LOGIN }));
});
}
predict(props) {
return __awaiter(this, void 0, void 0, function* () {
return this.performPredict(Object.assign(Object.assign({}, props), { config: Object.assign({ url_name_override: URL_OVERRIDES.PREDICT }, props.config) }));
});
}
predictWithStatus(props) {
return __awaiter(this, void 0, void 0, function* () {
return this.performPredict(Object.assign(Object.assign({}, props), { config: Object.assign({ url_name_override: URL_OVERRIDES.PREDICT_STATUS }, props.config) }));
});
}
predictConfirmUser(props) {
return __awaiter(this, void 0, void 0, function* () {
return this.performPredict(Object.assign(Object.assign({}, props), { config: Object.assign({ url_name_override: URL_OVERRIDES.CONFIRM_USER }, props.config) }));
});
}
predictDeleteUser(props) {
return __awaiter(this, void 0, void 0, function* () {
return this.performPredict(Object.assign(Object.assign({}, props), { config: Object.assign({ url_name_override: URL_OVERRIDES.DELETE_USER }, props.config) }));
});
}
estimateAge(props) {
return __awaiter(this, void 0, void 0, function* () {
const baseConfig = {
input_image_format: 'rgba',
angle_rotation_left_threshold: 20.0,
angle_rotation_right_threshold: 20.0,
anti_spoofing_threshold: 0.8,
threshold_profile_predict: 0.66,
blur_threshold_enroll_pred: 40,
threshold_user_too_close: 0.8,
threshold_user_too_far: 0.2,
threshold_user_up: 0.15,
threshold_user_down: 0.9,
threshold_user_left: 0.8,
threshold_user_right: 0.2,
threshold_high_vertical_predict: 0.9,
threshold_down_vertical_predict: 2.2,
url_name_override: '',
disable_predict_mf: false,
mf_count_override: 5,
disable_estimate_age_mf: false,
threshold_profile_enroll: 0.6,
allow_only_one_face: false,
};
printLogs('[FaceService] estimateAge', true);
return this.runUltraProcess(this.wasmService.estimateAge, Object.assign(Object.assign({}, props), { callbackType: callbackTypeEnum.ageEstimation, logMessage: props.logMessage || LOG_MESSAGES.AGE_ESTIMATION, config: Object.assign(Object.assign({}, baseConfig), props.config) }));
});
}
enroll(props) {
return __awaiter(this, void 0, void 0, function* () {
printLogs('ENROLL_ONE_FA', '');
let configJSON = getBaseEnrollConfig();
const { os } = detect();
if (['iOS', 'android', 'Android OS'].includes(os)) {
configJSON = Object.assign(Object.assign({}, configJSON), { threshold_user_too_far: 0.31, threshold_user_too_close: 0.55, threshold_user_right: 0.2, threshold_user_left: 0.8, threshold_profile_enroll: 0.66 });
}
if (props.config) {
configJSON = Object.assign(Object.assign({}, configJSON), props.config);
}
if (props.element) {
this.cameraService.setVideoElementId(props.element);
}
const imageData = this.generateImageData(this.cameraService.getVideoElementDOM(), true);
const callbackForImageCreation = callbackWithImageCreation(props.callback, imageData, true);
this.privid_wasm_result = createCallback({
type: callbackTypeEnum.enroll,
callbackFunction: callbackForImageCreation,
});
const bestImage = yield this.wasmService.enroll(imageData, JSON.stringify(configJSON), proxy(this.privid_wasm_result));
if (props.returnPortrait) {
return imageData;
}
return bestImage;
});
}
generateImageData(videoElement, shouldDownscale = false) {
var _a;
const canvas = this.prepareCanvas(videoElement, shouldDownscale);
const context = canvas.getContext('2d', { willReadFrequently: true });
(_a = context.resetTransform) === null || _a === void 0 ? void 0 : _a.call(context);
if (this.faceMode === CameraFaceMode.front) {
context.translate(canvas.width, 0);
context.scale(-1, 1);
}
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
return context.getImageData(0, 0, canvas.width, canvas.height);
}
prepareCanvas(videoElement, shouldDownscale = false) {
const height = (videoElement === null || videoElement === void 0 ? void 0 : videoElement.videoHeight) || 0;
const width = (videoElement === null || videoElement === void 0 ? void 0 : videoElement.videoWidth) || 0;
if (width === 0) {
throw new Error(INVALID_VIDEO_ERROR);
}
if (!shouldDownscale) {
this.canvas.setAttribute('height', `${height}`);
this.canvas.setAttribute('width', `${width}`);
printLogs(`[FaceService] Valid Canvas:`, { width: this.canvas.width, height: this.canvas.height });
return this.canvas;
}
const canvasDimensions = defineDimensionsForCanvas({ width, height });
this.canvas.setAttribute('height', `${canvasDimensions.height}`);
this.canvas.setAttribute('width', `${canvasDimensions.width}`);
printLogs(`[FaceService] Valid Canvas Downscaled:`, { width: this.canvas.width, height: this.canvas.height });
return this.canvas;
}
// Getters and Setters
getIsSimd() {
return this.isSimd;
}
setIsSimd(value) {
this.isSimd = value;
}
getPrivid_wasm_result() {
return this.privid_wasm_result;
}
setPrivid_wasm_result(value) {
this.privid_wasm_result = value;
}
getFaceMode() {
return this.faceMode;
}
setFaceMode(value) {
this.faceMode = value;
}
}
//# sourceMappingURL=FaceService.js.map