UNPKG

@vladmandic/human

Version:

Human: AI-powered 3D Face Detection & Rotation Tracking, Face Description & Recognition, Body Pose Tracking, 3D Hand & Finger Tracking, Iris Analysis, Age & Gender & Emotion Prediction, Gesture Recognition

1,259 lines (1,181 loc) 93.1 kB
/// <reference types="offscreencanvas" /> /** meta-function that performs draw for: canvas, face, body, hand */ declare function all(inCanvas: AnyCanvas, result: Result, drawOptions?: Partial<DrawOptions>): Promise<[void, void, void, void, void] | null>; /** Defines all possible canvas types */ export declare type AnyCanvas = HTMLCanvasElement | OffscreenCanvas; /** Defines all possible image types */ export declare type AnyImage = HTMLImageElement | typeof Image; /** Defines all possible video types */ export declare type AnyVideo = HTMLMediaElement | HTMLVideoElement; /** @docalias number[] */ declare interface ArrayMap { R0: number; R1: number[]; R2: number[][]; R3: number[][][]; R4: number[][][][]; R5: number[][][][][]; R6: number[][][][][][]; } /** Possible TensorFlow backends */ export declare type BackendType = ['cpu', 'wasm', 'webgl', 'humangl', 'tensorflow', 'webgpu']; /** draw detected bodies */ declare function body(inCanvas: AnyCanvas, result: Array<BodyResult>, drawOptions?: Partial<DrawOptions>): Promise<void>; export declare type BodyAnnotation = BodyAnnotationBlazePose | BodyAnnotationEfficientPose; export declare type BodyAnnotationBlazePose = 'leftLeg' | 'rightLeg' | 'torso' | 'leftArm' | 'rightArm' | 'leftEye' | 'rightEye' | 'mouth'; export declare type BodyAnnotationEfficientPose = 'leftLeg' | 'rightLeg' | 'torso' | 'leftArm' | 'rightArm' | 'head'; /** Configures all body detection specific options */ export declare interface BodyConfig extends GenericConfig { /** maximum number of detected bodies */ maxDetected: number; /** minimum confidence for a detected body before results are discarded */ minConfidence: number; } /** body gesture type */ export declare type BodyGesture = `leaning ${'left' | 'right'}` | `raise ${'left' | 'right'} hand` | 'i give up'; /** Body Result keypoints */ export declare interface BodyKeypoint { /** body part name */ part: BodyLandmark; /** body part position */ position: Point; /** body part position normalized to 0..1 */ positionRaw: Point; /** body part position relative to body center in meters */ distance?: Point; /** body part detection score */ score: number; } export declare type BodyLandmark = BodyLandmarkPoseNet | BodyLandmarkMoveNet | BodyLandmarkEfficientNet | BodyLandmarkBlazePose; export declare type BodyLandmarkBlazePose = 'nose' | 'leftEyeInside' | 'leftEye' | 'leftEyeOutside' | 'rightEyeInside' | 'rightEye' | 'rightEyeOutside' | 'leftEar' | 'rightEar' | 'leftMouth' | 'rightMouth' | 'leftShoulder' | 'rightShoulder' | 'leftElbow' | 'rightElbow' | 'leftWrist' | 'rightWrist' | 'leftPinky' | 'rightPinky' | 'leftIndex' | 'rightIndex' | 'leftThumb' | 'rightThumb' | 'leftHip' | 'rightHip' | 'leftKnee' | 'rightKnee' | 'leftAnkle' | 'rightAnkle' | 'leftHeel' | 'rightHeel' | 'leftFoot' | 'rightFoot' | 'bodyCenter' | 'bodyTop' | 'leftPalm' | 'leftHand' | 'rightPalm' | 'rightHand'; export declare type BodyLandmarkEfficientNet = 'head' | 'neck' | 'rightShoulder' | 'rightElbow' | 'rightWrist' | 'chest' | 'leftShoulder' | 'leftElbow' | 'leftWrist' | 'bodyCenter' | 'rightHip' | 'rightKnee' | 'rightAnkle' | 'leftHip' | 'leftKnee' | 'leftAnkle'; export declare type BodyLandmarkMoveNet = 'nose' | 'leftEye' | 'rightEye' | 'leftEar' | 'rightEar' | 'leftShoulder' | 'rightShoulder' | 'leftElbow' | 'rightElbow' | 'leftWrist' | 'rightWrist' | 'leftHip' | 'rightHip' | 'leftKnee' | 'rightKnee' | 'leftAnkle' | 'rightAnkle'; export declare type BodyLandmarkPoseNet = 'nose' | 'leftEye' | 'rightEye' | 'leftEar' | 'rightEar' | 'leftShoulder' | 'rightShoulder' | 'leftElbow' | 'rightElbow' | 'leftWrist' | 'rightWrist' | 'leftHip' | 'rightHip' | 'leftKnee' | 'rightKnee' | 'leftAnkle' | 'rightAnkle'; /** Body results */ export declare interface BodyResult { /** body id */ id: number; /** body detection score */ score: number; /** detected body box */ box: Box; /** detected body box normalized to 0..1 */ boxRaw: Box; /** detected body keypoints */ keypoints: Array<BodyKeypoint>; /** detected body keypoints combined into annotated parts */ annotations: Record<BodyAnnotation, Point[][]>; } /** generic box as [x, y, width, height] */ export declare type Box = [number, number, number, number]; /** * Creates an IOHandler that loads model artifacts from user-selected files. * * This method can be used for loading from files such as user-selected files * in the browser. * When used in conjunction with `tf.loadLayersModel`, an instance of * `tf.LayersModel` (Keras-style) can be constructed from the loaded artifacts. * * ```js * // Note: This code snippet won't run properly without the actual file input * // elements in the HTML DOM. * * // Suppose there are two HTML file input (`<input type="file" ...>`) * // elements. * const uploadJSONInput = document.getElementById('upload-json'); * const uploadWeightsInput = document.getElementById('upload-weights'); * const model = await tf.loadLayersModel(tf.io.browserFiles( * [uploadJSONInput.files[0], uploadWeightsInput.files[0]])); * ``` * * @param files `File`s to load from. Currently, this function supports only * loading from files that contain Keras-style models (i.e., `tf.Model`s), for * which an `Array` of `File`s is expected (in that order): * - A JSON file containing the model topology and weight manifest. * - Optionally, One or more binary files containing the binary weights. * These files must have names that match the paths in the `weightsManifest` * contained by the aforementioned JSON file, or errors will be thrown * during loading. These weights files have the same format as the ones * generated by `tensorflowjs_converter` that comes with the `tensorflowjs` * Python PIP package. If no weights files are provided, only the model * topology will be loaded from the JSON file above. * @returns An instance of `Files` `IOHandler`. * * @doc { * heading: 'Models', * subheading: 'Loading', * namespace: 'io', * ignoreCI: true * } */ declare function browserFiles(files: File[]): IOHandler; /** * Deprecated. Use `tf.io.http`. * @param path * @param loadOptions */ declare function browserHTTPRequest(path: string, loadOptions?: LoadOptions): IOHandler; /** draw processed canvas */ declare function canvas(input: AnyCanvas | HTMLImageElement | HTMLVideoElement, output: AnyCanvas): Promise<void>; /** * Concatenate a number of ArrayBuffers into one. * * @param buffers A number of array buffers to concatenate. * @returns Result of concatenating `buffers` in order. */ declare function concatenateArrayBuffers(buffers: ArrayBuffer[]): ArrayBuffer; /** * Configuration interface definition for **Human** library * Contains all configurable parameters * Defaults: [config](https://github.com/vladmandic/human/blob/main/src/config.ts#L262) */ export declare interface Config { /** Backend used for TFJS operations * valid build-in backends are: * - Browser: `cpu`, `wasm`, `webgl`, `humangl`, `webgpu` * - NodeJS: `cpu`, `wasm`, `tensorflow` * default: `humangl` for browser and `tensorflow` for nodejs */ backend: '' | 'cpu' | 'wasm' | 'webgl' | 'humangl' | 'tensorflow' | 'webgpu'; /** Path to *.wasm files if backend is set to `wasm` * * default: auto-detects to link to CDN `jsdelivr` when running in browser */ wasmPath: string; /** Print debug statements to console * * default: `true` */ debug: boolean; /** Perform model loading and inference concurrently or sequentially * * default: `true` */ async: boolean; /** What to use for `human.warmup()` * - warmup pre-initializes all models for faster inference but can take significant time on startup * - used by `webgl`, `humangl` and `webgpu` backends * * default: `full` */ warmup: '' | 'none' | 'face' | 'full' | 'body'; /** Base model path (typically starting with file://, http:// or https://) for all models * - individual modelPath values are relative to this path * * default: `../models/` for browsers and `file://models/` for nodejs */ modelBasePath: string; /** Cache models in IndexDB on first sucessfull load * default: true if indexdb is available (browsers), false if its not (nodejs) */ cacheModels: boolean; /** Cache sensitivity * - values 0..1 where 0.01 means reset cache if input changed more than 1% * - set to 0 to disable caching * * default: 0.7 */ cacheSensitivity: number; /** Perform immediate garbage collection on deallocated tensors instead of caching them */ deallocate: boolean; /** Internal Variable */ skipAllowed: boolean; /** Filter config {@link FilterConfig} */ filter: Partial<FilterConfig>; /** Gesture config {@link GestureConfig} */ gesture: Partial<GestureConfig>; /** Face config {@link FaceConfig} */ face: Partial<FaceConfig>; /** Body config {@link BodyConfig} */ body: Partial<BodyConfig>; /** Hand config {@link HandConfig} */ hand: Partial<HandConfig>; /** Object config {@link ObjectConfig} */ object: Partial<ObjectConfig>; /** Segmentation config {@link SegmentationConfig} */ segmentation: Partial<SegmentationConfig>; } /** * Copy a model from one URL to another. * * This function supports: * * 1. Copying within a storage medium, e.g., * `tf.io.copyModel('localstorage://model-1', 'localstorage://model-2')` * 2. Copying between two storage mediums, e.g., * `tf.io.copyModel('localstorage://model-1', 'indexeddb://model-1')` * * ```js * // First create and save a model. * const model = tf.sequential(); * model.add(tf.layers.dense( * {units: 1, inputShape: [10], activation: 'sigmoid'})); * await model.save('localstorage://demo/management/model1'); * * // Then list existing models. * console.log(JSON.stringify(await tf.io.listModels())); * * // Copy the model, from Local Storage to IndexedDB. * await tf.io.copyModel( * 'localstorage://demo/management/model1', * 'indexeddb://demo/management/model1'); * * // List models again. * console.log(JSON.stringify(await tf.io.listModels())); * * // Remove both models. * await tf.io.removeModel('localstorage://demo/management/model1'); * await tf.io.removeModel('indexeddb://demo/management/model1'); * ``` * * @param sourceURL Source URL of copying. * @param destURL Destination URL of copying. * @returns ModelArtifactsInfo of the copied model (if and only if copying * is successful). * @throws Error if copying fails, e.g., if no model exists at `sourceURL`, or * if `oldPath` and `newPath` are identical. * * @doc { * heading: 'Models', * subheading: 'Management', * namespace: 'io', * ignoreCI: true * } */ declare function copyModel(sourceURL: string, destURL: string): Promise<ModelArtifactsInfo>; /** * We wrap data id since we use weak map to avoid memory leaks. * Since we have our own memory management, we have a reference counter * mapping a tensor to its data, so there is always a pointer (even if that * data is otherwise garbage collectable). * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ * Global_Objects/WeakMap */ declare type DataId = object; declare type DataToGPUOptions = DataToGPUWebGLOption; declare interface DataToGPUWebGLOption { customTexShape?: [number, number]; } /** @docalias 'float32'|'int32'|'bool'|'complex64'|'string' */ declare type DataType = keyof DataTypeMap; declare interface DataTypeMap { float32: Float32Array; int32: Int32Array; bool: Uint8Array; complex64: Float32Array; string: string[]; } /** * Decode flat ArrayBuffer as weights. * * This function does not handle sharding. * * This function is the reverse of `encodeWeights`. * * @param buffer A flat ArrayBuffer carrying the binary values of the tensors * concatenated in the order specified in `specs`. * @param specs Specifications of the names, dtypes and shapes of the tensors * whose value are encoded by `buffer`. * @return A map from tensor name to tensor value, with the names corresponding * to names in `specs`. * @throws Error, if any of the tensors has unsupported dtype. */ declare function decodeWeights(buffer: ArrayBuffer, specs: WeightsManifestEntry[]): NamedTensorMap; /** - [See all default Config values...](https://github.com/vladmandic/human/blob/main/src/config.ts#L262) */ export declare const defaults: Config; /** Face descriptor type as number array */ export declare type Descriptor = Array<number>; /** Calculates distance between two descriptors * @param options - calculation options * - order - algorithm to use * Euclidean distance if `order` is 2 (default), Minkowski distance algorithm of nth order if `order` is higher than 2 * - multiplier - by how much to enhance difference analysis in range of 1..100 * default is 20 which normalizes results to similarity above 0.5 can be considered a match */ declare function distance(descriptor1: Descriptor, descriptor2: Descriptor, options?: MatchOptions): number; declare namespace draw { export { gesture, face, body, hand, object, person, canvas, all, DrawOptions, options } } /** Draw Options * - Accessed via `human.draw.options` or provided per each draw method as the drawOptions optional parameter */ export declare type DrawOptions = { /** draw line color */ color: string; /** label color */ labelColor: string; /** label shadow color */ shadowColor: string; /** label font */ font: string; /** line spacing between labels */ lineHeight: number; /** line width for drawn lines */ lineWidth: number; /** size of drawn points */ pointSize: number; /** draw rounded boxes by n pixels */ roundRect: number; /** should points be drawn? */ drawPoints: boolean; /** should labels be drawn? */ drawLabels: boolean; /** should detected gestures be drawn? */ drawGestures: boolean; /** should draw boxes around detection results? */ drawBoxes: boolean; /** should draw polygons from detection points? */ drawPolygons: boolean; /** should draw gaze arrows? */ drawGaze: boolean; /** should fill polygons? */ fillPolygons: boolean; /** use z-coordinate when available */ useDepth: boolean; /** should lines be curved? */ useCurves: boolean; }; export declare type Emotion = 'angry' | 'disgust' | 'fear' | 'happy' | 'sad' | 'surprise' | 'neutral'; /** * Encode a map from names to weight values as an ArrayBuffer, along with an * `Array` of `WeightsManifestEntry` as specification of the encoded weights. * * This function does not perform sharding. * * This function is the reverse of `decodeWeights`. * * @param tensors A map ("dict") from names to tensors. * @param group Group to which the weights belong (optional). * @returns A `Promise` of * - A flat `ArrayBuffer` with all the binary values of the `Tensor`s * concatenated. * - An `Array` of `WeightManifestEntry`s, carrying information including * tensor names, `dtype`s and shapes. * @throws Error: on unsupported tensor `dtype`. */ declare function encodeWeights(tensors: NamedTensorMap | NamedTensor[], group?: WeightGroup): Promise<{ data: ArrayBuffer; specs: WeightsManifestEntry[]; }>; /** Env class that holds detected capabilities */ export declare class Env { /** Running in Browser */ browser: boolean; /** Running in NodeJS */ node: boolean; /** Running in WebWorker thread */ worker: boolean; /** Detected platform */ platform: string; /** Detected agent */ agent: string; /** List of supported backends */ backends: string[]; /** Has any work been performed so far */ initial: boolean; /** Are image filters supported? */ filter: boolean | undefined; /** TFJS instance details */ tfjs: { version: undefined | string; }; /** Is offscreenCanvas supported? */ offscreen: undefined | boolean; /** Are performance counter instant values or additive */ perfadd: boolean; /** WASM detected capabilities */ wasm: { supported: undefined | boolean; backend: undefined | boolean; simd: undefined | boolean; multithread: undefined | boolean; }; /** WebGL detected capabilities */ webgl: { supported: undefined | boolean; backend: undefined | boolean; version: undefined | string; renderer: undefined | string; }; /** WebGPU detected capabilities */ webgpu: { supported: undefined | boolean; backend: undefined | boolean; adapter: undefined | string; }; /** CPU info */ cpu: { model: undefined | string; flags: string[]; }; /** List of supported kernels for current backend */ kernels: string[]; /** MonkeyPatch for Canvas */ Canvas: undefined; /** MonkeyPatch for Image */ Image: undefined; /** MonkeyPatch for ImageData */ ImageData: undefined; constructor(); /** update backend information */ updateBackend(): Promise<void>; /** update cpu information */ updateCPU(): Promise<void>; } export declare const env: Env; /** Events dispatched by `human.events` * - `create`: triggered when Human object is instantiated * - `load`: triggered when models are loaded (explicitly or on-demand) * - `image`: triggered when input image is processed * - `result`: triggered when detection is complete * - `warmup`: triggered when warmup is complete */ export declare type Events = 'create' | 'load' | 'image' | 'result' | 'warmup' | 'error'; /** Defines possible externally defined canvas */ export declare type ExternalCanvas = typeof env.Canvas; /** draw detected faces */ declare function face(inCanvas: AnyCanvas, result: Array<FaceResult>, drawOptions?: Partial<DrawOptions>): Promise<void>; /** Anti-spoofing part of face configuration */ export declare interface FaceAntiSpoofConfig extends GenericConfig { } /** Configures all face-specific options: face detection, mesh analysis, age, gender, emotion detection and face description */ export declare interface FaceConfig extends GenericConfig { detector: Partial<FaceDetectorConfig>; mesh: Partial<FaceMeshConfig>; iris: Partial<FaceIrisConfig>; description: Partial<FaceDescriptionConfig>; emotion: Partial<FaceEmotionConfig>; antispoof: Partial<FaceAntiSpoofConfig>; liveness: Partial<FaceLivenessConfig>; } /** Description or face embedding part of face configuration * - also used by age and gender detection */ export declare interface FaceDescriptionConfig extends GenericConfig { /** minimum confidence for a detected face before results are discarded */ minConfidence: number; } /** Detector part of face configuration */ export declare interface FaceDetectorConfig extends GenericConfig { /** is face rotation correction performed after detecting face? * used to correctly analyze faces under high angles */ rotation: boolean; /** maximum number of detected faces */ maxDetected: number; /** minimum confidence for a detected face before results are discarded */ minConfidence: number; /** minimum overlap between two detected faces before one is discarded */ iouThreshold: number; /** should child models perform on masked image of a face */ mask: boolean; /** should face detection return processed and cropped face tensor that can with an external model for addtional processing? * if enabled it must be manually deallocated to avoid memory leak */ return: boolean; } /** Emotion part of face configuration */ export declare interface FaceEmotionConfig extends GenericConfig { /** minimum confidence for a detected face before results are discarded */ minConfidence: number; } /** face gesture type */ export declare type FaceGesture = `facing ${'left' | 'center' | 'right'}` | `blink ${'left' | 'right'} eye` | `mouth ${number}% open` | `head ${'up' | 'down'}`; /** Iris part of face configuration */ export declare interface FaceIrisConfig extends GenericConfig { } export declare type FaceLandmark = 'leftEye' | 'rightEye' | 'nose' | 'mouth' | 'leftEar' | 'rightEar' | 'symmetryLine' | 'silhouette' | 'lipsUpperOuter' | 'lipsLowerOuter' | 'lipsUpperInner' | 'lipsLowerInner' | 'rightEyeUpper0' | 'rightEyeLower0' | 'rightEyeUpper1' | 'rightEyeLower1' | 'rightEyeUpper2' | 'rightEyeLower2' | 'rightEyeLower3' | 'rightEyebrowUpper' | 'rightEyebrowLower' | 'rightEyeIris' | 'leftEyeUpper0' | 'leftEyeLower0' | 'leftEyeUpper1' | 'leftEyeLower1' | 'leftEyeUpper2' | 'leftEyeLower2' | 'leftEyeLower3' | 'leftEyebrowUpper' | 'leftEyebrowLower' | 'leftEyeIris' | 'midwayBetweenEyes' | 'noseTip' | 'noseBottom' | 'noseRightCorner' | 'noseLeftCorner' | 'rightCheek' | 'leftCheek'; /** Liveness part of face configuration */ export declare interface FaceLivenessConfig extends GenericConfig { } /** Mesh part of face configuration */ export declare interface FaceMeshConfig extends GenericConfig { } /** Face results * - Combined results of face detector, face mesh, age, gender, emotion, embedding, iris models * - Some values may be null if specific model is not enabled */ export declare interface FaceResult { /** face id */ id: number; /** overall face score */ score: number; /** detection score */ boxScore: number; /** mesh score */ faceScore: number; /** detected face box */ box: Box; /** detected face box normalized to 0..1 */ boxRaw: Box; /** detected face mesh */ mesh: Array<Point>; /** detected face mesh normalized to 0..1 */ meshRaw: Array<Point>; /** mesh keypoints combined into annotated results */ annotations: Record<FaceLandmark, Point[]>; /** detected age */ age?: number; /** detected gender */ gender?: Gender; /** gender detection score */ genderScore?: number; /** detected emotions */ emotion?: Array<{ score: number; emotion: Emotion; }>; /** detected race */ race?: Array<{ score: number; race: Race; }>; /** face descriptor */ embedding?: Array<number>; /** face iris distance from camera */ iris?: number; /** face anti-spoofing result confidence */ real?: number; /** face liveness result confidence */ live?: number; /** face rotation details */ rotation?: { angle: { roll: number; yaw: number; pitch: number; }; matrix: [number, number, number, number, number, number, number, number, number]; gaze: { bearing: number; strength: number; }; } | null; /** detected face as tensor that can be used in further pipelines */ tensor?: Tensor; } /** Run input through image filters before inference * - available only in Browser environments * - image filters run with near-zero latency as they are executed on the GPU using WebGL */ export declare interface FilterConfig { /** are image filters enabled? */ enabled: boolean; /** perform image histogram equalization * - equalization is performed on input as a whole and detected face before its passed for further analysis */ equalization: boolean; /** resize input width * - if both width and height are set to 0, there is no resizing * - if just one is set, second one is scaled automatically * - if both are set, values are used as-is */ width: number; /** resize input height * - if both width and height are set to 0, there is no resizing * - if just one is set, second one is scaled automatically * - if both are set, values are used as-is */ height: number; /** return processed canvas imagedata in result */ return: boolean; /** flip input as mirror image */ flip: boolean; /** range: -1 (darken) to 1 (lighten) */ brightness: number; /** range: -1 (reduce contrast) to 1 (increase contrast) */ contrast: number; /** range: 0 (no sharpening) to 1 (maximum sharpening) */ sharpness: number; /** range: 0 (no blur) to N (blur radius in pixels) */ blur: number; /** range: -1 (reduce saturation) to 1 (increase saturation) */ saturation: number; /** range: 0 (no change) to 360 (hue rotation in degrees) */ hue: number; /** image negative */ negative: boolean; /** image sepia colors */ sepia: boolean; /** image vintage colors */ vintage: boolean; /** image kodachrome colors */ kodachrome: boolean; /** image technicolor colors */ technicolor: boolean; /** image polaroid camera effect */ polaroid: boolean; /** range: 0 (no pixelate) to N (number of pixels to pixelate) */ pixelate: number; } export declare type Finger = 'index' | 'middle' | 'pinky' | 'ring' | 'thumb' | 'palm'; export declare type FingerCurl = 'none' | 'half' | 'full'; export declare type FingerDirection = 'verticalUp' | 'verticalDown' | 'horizontalLeft' | 'horizontalRight' | 'diagonalUpRight' | 'diagonalUpLeft' | 'diagonalDownRight' | 'diagonalDownLeft'; /** * Creates an IOHandler that loads model artifacts from memory. * * When used in conjunction with `tf.loadLayersModel`, an instance of * `tf.LayersModel` (Keras-style) can be constructed from the loaded artifacts. * * ```js * const model = await tf.loadLayersModel(tf.io.fromMemory( * modelTopology, weightSpecs, weightData)); * ``` * * @param modelArtifacts a object containing model topology (i.e., parsed from * the JSON format). * @param weightSpecs An array of `WeightsManifestEntry` objects describing the * names, shapes, types, and quantization of the weight data. * @param weightData A single `ArrayBuffer` containing the weight data, * concatenated in the order described by the weightSpecs. * @param trainingConfig Model training configuration. Optional. * * @returns A passthrough `IOHandler` that simply loads the provided data. */ declare function fromMemory(modelArtifacts: {} | ModelArtifacts, weightSpecs?: WeightsManifestEntry[], weightData?: ArrayBuffer, trainingConfig?: TrainingConfig): IOHandler; export declare type Gender = 'male' | 'female' | 'unknown'; /** Generic config type inherited by all module types */ export declare interface GenericConfig { /** is module enabled? */ enabled: boolean; /** path to model json file (relative to `modelBasePath` */ modelPath: string; /** how many max frames to go without re-running model if cached results are acceptable * for two-phase models such as face and hand caching applies to bounding boxes detection only */ skipFrames: number; /** how many max milliseconds to go without re-running model if cached results are acceptable * for two-phase models such as face and hand caching applies to bounding boxes detection only */ skipTime: number; } /** draw detected gestures */ declare function gesture(inCanvas: AnyCanvas, result: Array<GestureResult>, drawOptions?: Partial<DrawOptions>): Promise<void>; /** Controlls gesture detection */ export declare interface GestureConfig { /** is gesture detection enabled? */ enabled: boolean; } /** Gesture combined results * Each result has: * - part: part name and number where gesture was detected: `face`, `iris`, `body`, `hand` * - gesture: gesture detected */ export declare type GestureResult = { 'face': number; gesture: FaceGesture; } | { 'iris': number; gesture: IrisGesture; } | { 'body': number; gesture: BodyGesture; } | { 'hand': number; gesture: HandGesture; }; declare const getLoadHandlers: (url: string | string[], loadOptions?: LoadOptions) => IOHandler[]; /** * Create `ModelArtifacts` from a JSON file. * * @param modelJSON Object containing the parsed JSON of `model.json` * @param loadWeights Function that takes the JSON file's weights manifest, * reads weights from the listed path(s), and returns a Promise of the * weight manifest entries along with the weights data. * @returns A Promise of the `ModelArtifacts`, as described by the JSON file. */ declare function getModelArtifactsForJSON(modelJSON: ModelJSON, loadWeights: (weightsManifest: WeightsManifestConfig) => Promise<[WeightsManifestEntry[], /* weightData */ ArrayBuffer]>): Promise<ModelArtifacts>; /** * Populate ModelArtifactsInfo fields for a model with JSON topology. * @param modelArtifacts * @returns A ModelArtifactsInfo object. */ declare function getModelArtifactsInfoForJSON(modelArtifacts: ModelArtifacts): ModelArtifactsInfo; declare const getSaveHandlers: (url: string | string[]) => IOHandler[]; declare interface GPUData { tensorRef: Tensor; texture?: WebGLTexture; texShape?: [number, number]; } /** * A `tf.GraphModel` is a directed, acyclic graph built from a * SavedModel GraphDef and allows inference execution. * * A `tf.GraphModel` can only be created by loading from a model converted from * a [TensorFlow SavedModel](https://www.tensorflow.org/guide/saved_model) using * the command line converter tool and loaded via `tf.loadGraphModel`. * * @doc {heading: 'Models', subheading: 'Classes'} */ export declare class GraphModel implements InferenceModel { private modelUrl; private loadOptions; private executor; private version; private handler; private artifacts; private initializer; private resourceManager; private signature; readonly modelVersion: string; readonly inputNodes: string[]; readonly outputNodes: string[]; readonly inputs: TensorInfo[]; readonly outputs: TensorInfo[]; readonly weights: NamedTensorsMap; readonly metadata: {}; readonly modelSignature: {}; /** * @param modelUrl url for the model, or an `io.IOHandler`. * @param weightManifestUrl url for the weight file generated by * scripts/convert.py script. * @param requestOption options for Request, which allows to send credentials * and custom headers. * @param onProgress Optional, progress callback function, fired periodically * before the load is completed. */ constructor(modelUrl: string | io.IOHandler, loadOptions?: io.LoadOptions); private findIOHandler; /** * Loads the model and weight files, construct the in memory weight map and * compile the inference graph. */ load(): Promise<boolean>; /** * Synchronously construct the in memory weight map and * compile the inference graph. Also initialize hashtable if any. * * @doc {heading: 'Models', subheading: 'Classes', ignoreCI: true} */ loadSync(artifacts: io.ModelArtifacts): boolean; /** * Save the configuration and/or weights of the GraphModel. * * An `IOHandler` is an object that has a `save` method of the proper * signature defined. The `save` method manages the storing or * transmission of serialized data ("artifacts") that represent the * model's topology and weights onto or via a specific medium, such as * file downloads, local storage, IndexedDB in the web browser and HTTP * requests to a server. TensorFlow.js provides `IOHandler` * implementations for a number of frequently used saving mediums, such as * `tf.io.browserDownloads` and `tf.io.browserLocalStorage`. See `tf.io` * for more details. * * This method also allows you to refer to certain types of `IOHandler`s * as URL-like string shortcuts, such as 'localstorage://' and * 'indexeddb://'. * * Example 1: Save `model`'s topology and weights to browser [local * storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage); * then load it back. * * ```js * const modelUrl = * 'https://storage.googleapis.com/tfjs-models/savedmodel/mobilenet_v2_1.0_224/model.json'; * const model = await tf.loadGraphModel(modelUrl); * const zeros = tf.zeros([1, 224, 224, 3]); * model.predict(zeros).print(); * * const saveResults = await model.save('localstorage://my-model-1'); * * const loadedModel = await tf.loadGraphModel('localstorage://my-model-1'); * console.log('Prediction from loaded model:'); * model.predict(zeros).print(); * ``` * * @param handlerOrURL An instance of `IOHandler` or a URL-like, * scheme-based string shortcut for `IOHandler`. * @param config Options for saving the model. * @returns A `Promise` of `SaveResult`, which summarizes the result of * the saving, such as byte sizes of the saved artifacts for the model's * topology and weight values. * * @doc {heading: 'Models', subheading: 'Classes', ignoreCI: true} */ save(handlerOrURL: io.IOHandler | string, config?: io.SaveConfig): Promise<io.SaveResult>; /** * Execute the inference for the input tensors. * * @param input The input tensors, when there is single input for the model, * inputs param should be a `tf.Tensor`. For models with mutliple inputs, * inputs params should be in either `tf.Tensor`[] if the input order is * fixed, or otherwise NamedTensorMap format. * * For model with multiple inputs, we recommend you use NamedTensorMap as the * input type, if you use `tf.Tensor`[], the order of the array needs to * follow the * order of inputNodes array. @see {@link GraphModel.inputNodes} * * You can also feed any intermediate nodes using the NamedTensorMap as the * input type. For example, given the graph * InputNode => Intermediate => OutputNode, * you can execute the subgraph Intermediate => OutputNode by calling * model.execute('IntermediateNode' : tf.tensor(...)); * * This is useful for models that uses tf.dynamic_rnn, where the intermediate * state needs to be fed manually. * * For batch inference execution, the tensors for each input need to be * concatenated together. For example with mobilenet, the required input shape * is [1, 244, 244, 3], which represents the [batch, height, width, channel]. * If we are provide a batched data of 100 images, the input tensor should be * in the shape of [100, 244, 244, 3]. * * @param config Prediction configuration for specifying the batch size and * output node names. Currently the batch size option is ignored for graph * model. * * @returns Inference result tensors. The output would be single `tf.Tensor` * if model has single output node, otherwise Tensor[] or NamedTensorMap[] * will be returned for model with multiple outputs. * * @doc {heading: 'Models', subheading: 'Classes'} */ predict(inputs: Tensor | Tensor[] | NamedTensorMap, config?: ModelPredictConfig): Tensor | Tensor[] | NamedTensorMap; private normalizeInputs; private normalizeOutputs; /** * Executes inference for the model for given input tensors. * @param inputs tensor, tensor array or tensor map of the inputs for the * model, keyed by the input node names. * @param outputs output node name from the Tensorflow model, if no * outputs are specified, the default outputs of the model would be used. * You can inspect intermediate nodes of the model by adding them to the * outputs array. * * @returns A single tensor if provided with a single output or no outputs * are provided and there is only one default output, otherwise return a * tensor array. The order of the tensor array is the same as the outputs * if provided, otherwise the order of outputNodes attribute of the model. * * @doc {heading: 'Models', subheading: 'Classes'} */ execute(inputs: Tensor | Tensor[] | NamedTensorMap, outputs?: string | string[]): Tensor | Tensor[]; /** * Executes inference for the model for given input tensors in async * fashion, use this method when your model contains control flow ops. * @param inputs tensor, tensor array or tensor map of the inputs for the * model, keyed by the input node names. * @param outputs output node name from the Tensorflow model, if no outputs * are specified, the default outputs of the model would be used. You can * inspect intermediate nodes of the model by adding them to the outputs * array. * * @returns A Promise of single tensor if provided with a single output or * no outputs are provided and there is only one default output, otherwise * return a tensor map. * * @doc {heading: 'Models', subheading: 'Classes'} */ executeAsync(inputs: Tensor | Tensor[] | NamedTensorMap, outputs?: string | string[]): Promise<Tensor | Tensor[]>; /** * Get intermediate tensors for model debugging mode (flag * KEEP_INTERMEDIATE_TENSORS is true). * * @doc {heading: 'Models', subheading: 'Classes'} */ getIntermediateTensors(): NamedTensorsMap; /** * Dispose intermediate tensors for model debugging mode (flag * KEEP_INTERMEDIATE_TENSORS is true). * * @doc {heading: 'Models', subheading: 'Classes'} */ disposeIntermediateTensors(): void; private convertTensorMapToTensorsMap; /** * Releases the memory used by the weight tensors and resourceManager. * * @doc {heading: 'Models', subheading: 'Classes'} */ dispose(): void; } /** draw detected hands */ declare function hand(inCanvas: AnyCanvas, result: Array<HandResult>, drawOptions?: Partial<DrawOptions>): Promise<void>; /** Configures all hand detection specific options */ export declare interface HandConfig extends GenericConfig { /** should hand rotation correction be performed after hand detection? */ rotation: boolean; /** minimum confidence for a detected hand before results are discarded */ minConfidence: number; /** minimum overlap between two detected hands before one is discarded */ iouThreshold: number; /** maximum number of detected hands */ maxDetected: number; /** should hand landmarks be detected or just return detected hand box */ landmarks: boolean; detector: { /** path to hand detector model json */ modelPath?: string; }; skeleton: { /** path to hand skeleton model json */ modelPath?: string; }; } /** hand gesture type */ export declare type HandGesture = `${'thumb' | 'index' | 'middle' | 'ring' | 'pinky'} forward` | `${'thumb' | 'index' | 'middle' | 'ring' | 'pinky'} up` | 'victory' | 'thumbs up'; /** Hand results */ export declare interface HandResult { /** hand id */ id: number; /** hand overal score */ score: number; /** hand detection score */ boxScore: number; /** hand skelton score */ fingerScore: number; /** detected hand box */ box: Box; /** detected hand box normalized to 0..1 */ boxRaw: Box; /** detected hand keypoints */ keypoints: Array<Point>; /** detected hand class */ label: HandType; /** detected hand keypoints combined into annotated parts */ annotations: Record<Finger, Array<Point>>; /** detected hand parts annotated with part gestures */ landmarks: Record<Finger, { curl: FingerCurl; direction: FingerDirection; }>; } export declare type HandType = 'hand' | 'fist' | 'pinch' | 'point' | 'face' | 'tip' | 'pinchtip'; /** * Creates an IOHandler subtype that sends model artifacts to HTTP server. * * An HTTP request of the `multipart/form-data` mime type will be sent to the * `path` URL. The form data includes artifacts that represent the topology * and/or weights of the model. In the case of Keras-style `tf.Model`, two * blobs (files) exist in form-data: * - A JSON file consisting of `modelTopology` and `weightsManifest`. * - A binary weights file consisting of the concatenated weight values. * These files are in the same format as the one generated by * [tfjs_converter](https://js.tensorflow.org/tutorials/import-keras.html). * * The following code snippet exemplifies the client-side code that uses this * function: * * ```js * const model = tf.sequential(); * model.add( * tf.layers.dense({units: 1, inputShape: [100], activation: 'sigmoid'})); * * const saveResult = await model.save(tf.io.http( * 'http://model-server:5000/upload', {requestInit: {method: 'PUT'}})); * console.log(saveResult); * ``` * * If the default `POST` method is to be used, without any custom parameters * such as headers, you can simply pass an HTTP or HTTPS URL to `model.save`: * * ```js * const saveResult = await model.save('http://model-server:5000/upload'); * ``` * * The following GitHub Gist * https://gist.github.com/dsmilkov/1b6046fd6132d7408d5257b0976f7864 * implements a server based on [flask](https://github.com/pallets/flask) that * can receive the request. Upon receiving the model artifacts via the requst, * this particular server reconsistutes instances of [Keras * Models](https://keras.io/models/model/) in memory. * * * @param path A URL path to the model. * Can be an absolute HTTP path (e.g., * 'http://localhost:8000/model-upload)') or a relative path (e.g., * './model-upload'). * @param requestInit Request configurations to be used when sending * HTTP request to server using `fetch`. It can contain fields such as * `method`, `credentials`, `headers`, `mode`, etc. See * https://developer.mozilla.org/en-US/docs/Web/API/Request/Request * for more information. `requestInit` must not have a body, because the * body will be set by TensorFlow.js. File blobs representing the model * topology (filename: 'model.json') and the weights of the model (filename: * 'model.weights.bin') will be appended to the body. If `requestInit` has a * `body`, an Error will be thrown. * @param loadOptions Optional configuration for the loading. It includes the * following fields: * - weightPathPrefix Optional, this specifies the path prefix for weight * files, by default this is calculated from the path param. * - fetchFunc Optional, custom `fetch` function. E.g., in Node.js, * the `fetch` from node-fetch can be used here. * - onProgress Optional, progress callback function, fired periodically * before the load is completed. * @returns An instance of `IOHandler`. * * @doc { * heading: 'Models', * subheading: 'Loading', * namespace: 'io', * ignoreCI: true * } */ declare function http(path: string, loadOptions?: LoadOptions): IOHandler; /** **Human** library main class * * All methods and properties are available only as members of Human class * * - Configuration object definition: {@link Config} * - Results object definition: {@link Result} * - Possible inputs: {@link Input} * * @param userConfig - {@link Config} * @returns instance of {@link Human} */ declare class Human { #private; /** Current version of Human library in *semver* format */ version: string; /** Current configuration * - Defaults: [config](https://github.com/vladmandic/human/blob/main/src/config.ts#L262) */ config: Config; /** Last known result of detect run * - Can be accessed anytime after initial detection */ result: Result; /** Current state of Human library * - Can be polled to determine operations that are currently executed * - Progresses through: 'config', 'check', 'backend', 'load', 'run:<model>', 'idle' */ state: string; /** currenty processed image tensor and canvas */ process: { tensor: Tensor | null; canvas: AnyCanvas | null; }; /** Instance of TensorFlow/JS used by Human * - Can be embedded or externally provided * [TFJS API]: {@link https://js.tensorflow.org/api/latest/} */ tf: any; /** Object containing environment information used for diagnostics */ env: Env; /** Draw helper classes that can draw detected objects on canvas using specified draw * - canvas: draws input to canvas * - options: are global settings for all draw operations, can be overriden for each draw method {@link DrawOptions} * - face, body, hand, gesture, object, person: draws detected results as overlays on canvas */ draw: { canvas: typeof draw.canvas; face: typeof draw.face; body: typeof draw.body; hand: typeof draw.hand; gesture: typeof draw.gesture; object: typeof draw.object; person: typeof draw.person; all: typeof draw.all; options: DrawOptions; }; /** Currently loaded models * @internal * {@link Models} */ models: models.Models; /** Container for events dispatched by Human * Possible events: * - `create`: triggered when Human object is instantiated * - `load`: triggered when models are loaded (explicitly or on-demand) * - `image`: triggered when input image is processed * - `result`: triggered when detection is complete * - `warmup`: triggered when warmup is complete * - `error`: triggered on some errors */ events: EventTarget | undefined; /** Reference face triangualtion array of 468 points, used for triangle references between points */ faceTriangulation: number[]; /** Refernce UV map of 468 values, used for 3D mapping of the face mesh */ faceUVMap: [number, number][]; /** Performance object that contains values for all recently performed operations */ performance: Record<string, number>; /** WebGL debug info */ gl: Record<string, unknown>; /** Constructor for **Human** library that is futher used for all operations * @param userConfig - user configuration object {@link Config} */ constructor(userConfig?: Partial<Config>); /** internal function to measure tensor leaks */ analyze: (...msg: string[]) => void; /** Reset configuration to default values */ reset(): void; /** Validate current configuration schema */ validate(userConfig?: Partial<Config>): { reason: string; where: string; expected?: string; }[]; /** Exports face matching methods {@link match#similarity} */ similarity: typeof match.similarity; /** Exports face matching methods {@link match#distance} */ distance: typeof match.distance; /** Exports face matching methods {@link match#match} */ match: typeof match.match; /** Utility wrapper for performance.now() */ now(): number; /** Process input as return canvas and tensor * * @param input - any input {@link Input} * @param getTensor - should image processing also return tensor or just canvas * Returns object with `tensor` and `canvas` */ image(input: Input, getTensor?: boolean): Promise<{ tensor: Tensor<Rank> | null; canvas: AnyCanvas | null; }>; /** Segmentation method takes any input and returns processed canvas with body segmentation * - Segmentation is not triggered as part of detect process * @param input - {@link Input} * @param background - {@link Input} * - Optional parameter background is used to fill the background with specific input * Returns: * - `data` as raw data array with per-pixel segmentation values * - `canvas` as canvas which is input image filtered with segementation data and optionally merged with background image. canvas alpha values are set to segmentation values for easy merging * - `alpha` as grayscale canvas that represents segmentation alpha values */ segmentation(input: Input, background?: Input): Promise<{ data: number[] | Tensor; canvas: AnyCanvas | null; alpha: AnyCanvas | null; }>; /** Enhance method performs additional enhacements to face image previously detected for futher processing * * @param input - Tensor as provided in human.result.face[n].tensor * @returns Tensor */ enhance(input: Tensor): Tensor | null; /** Compare two input tensors for pixel simmilarity * - use `human.image` to process any valid input and get a tensor that can be used for compare * - when passing manually generated tensors: * - both input tensors must be in format [1, height, width, 3] * - if resolution of tensors does not match, second tensor will be resized to match resolution of the first tensor * - return value is pixel similarity score normalized by input resolution and rgb channels */ compare(firstImageTensor: Tensor, secondImageTensor: Tensor): Promise<number>; /** Explicit backend initialization * - Normally done implicitly during initial load phase * - Call to explictly register and initialize TFJS backend without any other operations * - Use when changing backend during runtime */ init(): Promise<void>; /** Load method preloads all configured models on-demand * - Not explicitly required as any required model is load implicitly on it's first run * * @param userConfig - {@link Config} */ load(userConfig?: Partial<Config>): Promise<void>; /** emit event */ emit: (event: string) => void; /** Runs interpolation using last known result and returns smoothened result * Interpolation is based on time since last known result so can be called independently * * @param result - {@link Result} op