redesigned tfjs bundling and build process

pull/19/head
Vladimir Mandic 2020-12-02 16:46:41 -05:00
parent d82c04870d
commit e306d69a7d
591 changed files with 66907 additions and 23022 deletions

View File

@ -1,227 +0,0 @@
# FaceAPI
## Note
This is updated **face-api.js** with latest available TensorFlow/JS as the original face-api.js is not compatible with **tfjs 2.0+**.
Forked from **face-api.js** version **0.22.2** released on March 22nd, 2020
- <https://github.com/justadudewhohacks/face-api.js>
- <https://www.npmjs.com/package/face-api.js>
Currently based on **`TensorFlow/JS` 2.7.0**
If you want to access `TFJS` classes and methods directly, they are exported as `faceapi.tf`
### Why?
Because I needed FaceAPI that does not cause version conflict with newer TFJS 2.0 that I use accross my projects
And since original FaceAPI was open-source, I've released this version as well
Unfortunately, changes ended up being too large for a simple pull request on original FaceaPI and it ended up being a full-fledged version on its own
### Differences
- Compatible with `TensorFlow/JS 2.0+`
- Compatible with `WebGL`, `CPU` and `WASM` TFJS backends
- Updated all type castings for TypeScript type checking to `TypeScript 4.1`
- Switched bundling from `UMD` to `ESM` + `CommonJS`
This does require separate process for usage in NodeJS vs Browser, but resulting code is much lighter
Fully tree shakable when imported as an `ESM` module
Browser bundle process uses `ESBuild` instead of `Rollup`
- Typescript build process now targets `ES2018` and instead of dual ES5/ES6
Resulting code is clean ES2018 JavaScript without polyfills
- Removed old tests, docs, examples
- Removed old package dependencies (`karma`, `jasmine`, `babel`, etc.)
- Updated all package dependencies
- Updated TensorFlow/JS dependencies since backends were removed from `@tensorflow/tfjs-core`
- Updated mobileNetv1 model due to `batchNorm()` dependency
- Added `version` class that returns JSON object with version of FaceAPI as well as linked TFJS
- Removed `mtcnn` and `tinyYolov2` models as they were non-functional in latest public version of `Face-API`
*If there is a demand, I can re-implement them back.*
Which means valid models are **tinyFaceDetector** and **mobileNetv1**
## Installation
Face-API ships with several pre-build versions of the library:
- `dist/face-api.js`: IIFE format for client-side Browser execution *with* TFJS pre-bundled
- `dist/face-api.esm.js`: ESM format for client-side Browser execution *with* TFJS pre-bundled
- `dist/face-api.esm.nobundle.js`: ESM format for client-side Browser execution *without* TFJS pre-bundled
- `dist/face-api.node.js`: CommonJS format for server-side NodeJS execution *without* TFJS pre-bundled
Defaults are:
```json
{
"main": "dist/face-api.cjs",
"module": "dist/face-api.esm.js",
"browser": "dist/face-api.esm.js",
}
```
Reason for additional `nobundle` version is if you want to include a specific version of TFJS and not rely on pre-packaged one
`FaceAPI` is compatible with TFJS 2.0+
Bundled versions are ~1.1MB minified and non-bundled versions are ~169KB non-minified
All versions include `sourcemap`
There are several ways to use Face-API:
### 1. IIFE script
*Recommened for quick tests and backward compatibility with older Browsers that do not support ESM such as IE*
This is simplest way for usage within Browser
Simply download `dist/face-api.js`, include it in your `HTML` file & it's ready to use
```html
<script src="dist/face-api.js"><script>
```
IIFE script bundles TFJS and auto-registers global namespace `faceapi` within Window object which can be accessed directly from a `<script>` tag or from your JS file.
### 2. ESM module
*Recommended for usage within Browser*
#### 2.1. Direct Import
To use ESM import directly in a Browser, you must import your script (e.g. `index.js`) with a `type="module"`
```html
<script src="./index.js" type="module">
```
and then in your `index.js`
```js
import * as faceapi from 'dist/face-api.esm.js';
```
or to use non-bundled version:
```js
import * as tf from `https://cdnjs.cloudflare.com/ajax/libs/tensorflow/2.7.0/tf.es2017.min.js`; // load tfjs directly from CDN link
import * as faceapi from 'dist/face-api.nobundle.js';
```
#### 2.2. With Bundler
Same as above, but expectation is that you've installed `@vladmandic/faceapi` package
and that you'll package your script using a bundler such as `webpack`, `rollup` or `esbuild`
in which case, you do not need to import a script as module - that depends on your bundler configuration
```js
import * as faceapi from '@vladmandic/face-api';
```
or if your bundler doesn't recognize `recommended` type, force usage with:
```js
import * as faceapi from '@vladmandic/face-api/dist/face-api.esm.js';
```
or to use non-bundled version
```js
import * as tf from `@tensorflow/tfjs`;
import * as faceapi from '@vladmandic/face-api/dist/face-api.nobundle.js';
```
### 3. NPM module
#### 3.1. Import CommonJS
*Recommended for NodeJS projects*
*Node: Face-API for NodeJS does not bundle TFJS due to binary dependencies that are installed during TFJS installation*
Install with:
```shell
npm install @tensorflow/tfjs-node
npm install @vladmandic/face-api
```
And then use with:
```js
const tf = require('@tensorflow/tfjs-node')
const faceapi = require('@vladmandic/face-api');
```
- if you want to CUDA GPU Accelerated NodeJS, import `tfjs-node-gpu` instead of `tfjs-node`
This requires that system is CUDA enabled and has CUDA libraries already installed.
- If you want to force CommonJS module instead of relying on `recommended` field:
```js
const faceapi = require('@vladmandic/face-api/dist/face-api.node.js');
```
### 4. Import Sources
*Recommended for complex NodeJS projects that use TFJS for other purposes and not just FaceaPI*
This way you're importing FaceAPI sources directly and not a bundle, so you have to import `@tensorflow/tfjs` explicitly
#### 4.1. For Browser with Bundler
##### 4.1.1. For JavaScript projects
```js
import * as tf from '@tensorflow/tfjs';
import * as faceapi from '@vladmandic/face-api/build/index.js';
```
##### 4.1.2. For TypeScript projects
```js
import * as tf from '@tensorflow/tfjs';
import * as faceapi from '@vladmandic/face-api/src/index.ts';
```
#### 4.2. For NodeJS
##### 4.2.1. For JavaScript projects
```js
const tf = require('@tensorflow/tfjs');
const faceapi = require('@vladmandic/face-api/build/index.js');
```
##### 4.1.2. For TypeScript projects
```js
const tf = require('@tensorflow/tfjs');
const faceapi = require('@vladmandic/face-api/src/index.ts');
```
## Weights
Pretrained models and their weights are includes in `./model`.
## Build
If you want to do a full rebuild, either download npm module
```shell
npm install @vladmandic/face-api
cd node_modules/@vladmandic/face-api
```
or clone a git project
```shell
git clone https://github.com/vladmandic/face-api
cd face-api
```
Then install all dependencies and run rebuild:
```shell
npm install
npm run build
```
Which will compile everything in `./src` into `./build` and create both ESM (standard) and IIFE (minified) bundles as well as sourcemaps in `./dist`
## Credits & Documentation
- Original documentation: [Face-API](https://github.com/justadudewhohacks/face-api.js)
- Original model weighs: [Face-API](https://github.com/justadudewhohacks/face-api.js-models)
- ML API Documentation: [Tensorflow/JS](https://js.tensorflow.org/api/latest/)
## Example
### Browser
Example that uses both models as well as all of the extensions is included in `/example/index.html`
Example can be accessed directly using Git pages using URL: <https://vladmandic.github.io/face-api/example/>
### NodeJS
Example is included in `/example/node.js`
Note that it does not require any other other 3rd party libraries
*Note: Photos shown below are taken by me*
![alt text](example/screenshot.png)

136
README.md
View File

@ -10,7 +10,6 @@ Forked from **face-api.js** version **0.22.2** released on March 22nd, 2020
- <https://www.npmjs.com/package/face-api.js> - <https://www.npmjs.com/package/face-api.js>
Currently based on **`TensorFlow/JS` 2.7.0** Currently based on **`TensorFlow/JS` 2.7.0**
If you want to access `TFJS` classes and methods directly, they are exported as `faceapi.tf`
### Why? ### Why?
@ -21,9 +20,10 @@ Unfortunately, changes ended up being too large for a simple pull request on ori
### Differences ### Differences
- Compatible with `TensorFlow/JS 2.0+` - Compatible with `TensorFlow/JS 2.0+`
- Compatible with `WebGL`, `CPU` and `WASM` TFJS backends - Compatible with `WebGL`, `CPU` and `WASM` TFJS Browser backends
- Compatible with both `tfjs-node` and `tfjs-node-gpu` TFJS NodeJS backends
- Updated all type castings for TypeScript type checking to `TypeScript 4.1` - Updated all type castings for TypeScript type checking to `TypeScript 4.1`
- Switched bundling from `UMD` to `ESM` + `CommonJS` - Switched bundling from `UMD` to `ESM` + `CommonJS` with fallback to `IIFE`
This does require separate process for usage in NodeJS vs Browser, but resulting code is much lighter This does require separate process for usage in NodeJS vs Browser, but resulting code is much lighter
Fully tree shakable when imported as an `ESM` module Fully tree shakable when imported as an `ESM` module
Browser bundle process uses `ESBuild` instead of `Rollup` Browser bundle process uses `ESBuild` instead of `Rollup`
@ -43,11 +43,11 @@ Which means valid models are **tinyFaceDetector** and **mobileNetv1**
## Installation ## Installation
Face-API ships with several pre-build versions of the library: Face-API ships with several pre-build versions of the library:
- `dist/face-api.js`: IIFE format for client-side Browser execution - `dist/face-api.js`: IIFE format for client-side Browser execution *with* TFJS pre-bundled
- `dist/face-api.esm.js`: ESM format for client-side Browser execution with TFJS pre-bundled - `dist/face-api.esm.js`: ESM format for client-side Browser execution *with* TFJS pre-bundled
- `dist/face-api.esm.nobundle.js`: ESM format for client-side Browser execution without TFJS and not minified - `dist/face-api.esm-nobundle.js`: ESM format for client-side Browser execution *without* TFJS pre-bundled
- `dist/face-api.node.js`: CommonJS format for server-side NodeJS execution with TFJS pre-bundled - `dist/face-api.node.js`: CommonJS format for server-side NodeJS execution *without* TFJS pre-bundled
- `dist/face-api.node.nobundle.js`: CommonJS format for server-side NodeJS execution without TFJS and not minified - `dist/face-api.node-gpu.js`: CommonJS format for server-side NodeJS execution *without* TFJS pre-bundled and optimized for CUDA GPU acceleration
Defaults are: Defaults are:
```json ```json
@ -58,11 +58,15 @@ Defaults are:
} }
``` ```
Reason for additional `nobundle` version is if you want to include a specific version of TFJS and not rely on pre-packaged one Bundled `TFJS` can be used directly via export: `faceapi.tf`
Reason for additional `nobundle` version is if you want to include a specific version of TFJS and not rely on pre-packaged one
`FaceAPI` is compatible with TFJS 2.0+ `FaceAPI` is compatible with TFJS 2.0+
Bundled versions are ~1.1MB minified and non-bundled versions are ~169KB non-minified All versions include `sourcemap` and `asset manifest`
All versions include `sourcemap`
<br>
There are several ways to use Face-API: There are several ways to use Face-API:
@ -79,6 +83,8 @@ Simply download `dist/face-api.js`, include it in your `HTML` file & it's ready
IIFE script bundles TFJS and auto-registers global namespace `faceapi` within Window object which can be accessed directly from a `<script>` tag or from your JS file. IIFE script bundles TFJS and auto-registers global namespace `faceapi` within Window object which can be accessed directly from a `<script>` tag or from your JS file.
<br>
### 2. ESM module ### 2. ESM module
*Recommended for usage within Browser* *Recommended for usage within Browser*
@ -97,14 +103,18 @@ and then in your `index.js`
``` ```
or to use non-bundled version: or to use non-bundled version:
```js ```js
import * as tf from `https://cdnjs.cloudflare.com/ajax/libs/tensorflow/2.7.0/tf.es2017.min.js`; // load tfjs directly from CDN link import * as tf from `https://cdnjs.cloudflare.com/ajax/libs/tensorflow/2.7.0/tf.es2017.min.js`; // load tfjs directly from CDN link or your local system
import * as faceapi from 'dist/face-api.nobundle.js'; import * as faceapi from 'dist/face-api.esm-nobundle.js';
``` ```
#### 2.2. With Bundler #### 2.2. With Bundler
Same as above, but expectation is that you've installed `@vladmandic/faceapi` package Same as above, but expectation is that you've installed `@vladmandic/faceapi` package:
and that you'll package your script using a bundler such as `webpack`, `rollup` or `esbuild` ```shell
npm install @vladmandic/face-api
```
and that you'll package your application using a bundler such as `webpack`, `rollup` or `esbuild`
in which case, you do not need to import a script as module - that depends on your bundler configuration in which case, you do not need to import a script as module - that depends on your bundler configuration
```js ```js
@ -117,71 +127,46 @@ or if your bundler doesn't recognize `recommended` type, force usage with:
or to use non-bundled version or to use non-bundled version
```js ```js
import * as tf from `@tensorflow/tfjs`; import * as tf from `@tensorflow/tfjs`;
import * as faceapi from '@vladmandic/face-api/dist/face-api.nobundle.js'; import * as faceapi from '@vladmandic/face-api/dist/face-api.esm-nobundle.js';
``` ```
<br>
### 3. NPM module ### 3. NPM module
#### 3.1. Import CommonJS #### 3.1. Import CommonJS
*Recommended for NodeJS projects* *Recommended for NodeJS projects*
*Node: Face-API for NodeJS does not bundle TFJS due to binary dependencies that are installed during TFJS installation*
Install with: Install with:
```shell ```shell
npm install @tensorflow/tfjs-node
npm install @vladmandic/face-api npm install @vladmandic/face-api
``` ```
And then use with: And then use with:
```js ```js
const tf = require('@tensorflow/tfjs-node')
const faceapi = require('@vladmandic/face-api'); const faceapi = require('@vladmandic/face-api');
``` ```
or if you want to force CommonJS module instead of relying on `recommended` field:
If you want to force CommonJS module instead of relying on `recommended` field:
```js ```js
const faceapi = require('@vladmandic/face-api/dist/face-api.node.js'); const faceapi = require('@vladmandic/face-api/dist/face-api.node.js');
``` ```
or if you want to use a non-bundled version:
Install with: If you want to GPU Accelerated execution in NodeJS, you must have CUDA libraries already installed and working
Then install appropriate version of `Face-API`:
```shell ```shell
npm install @tensorflow/tfjs npm install @tensorflow/tfjs-node
npm install @vladmandic/face-api npm install @vladmandic/face-api
``` ```
And then use with: And then use with:
```js ```js
const tf = require('@tensorflow/tfjs'); const tf = require('@tensorflow/tfjs-node-gpu')
const faceapi = require('@vladmandic/face-api/dist/face-api.node.nobundle.js'); const faceapi = require('@vladmandic/face-api/dist/face-api.node-gpu.js'); // this loads face-api version with correct bindings for tfjs-node-gpu
```
### 4. Import Sources
*Recommended for complex NodeJS projects that use TFJS for other purposes and not just FaceaPI*
This way you're importing FaceAPI sources directly and not a bundle, so you have to import `@tensorflow/tfjs` explicitly
#### 4.1. For Browser with Bundler
##### 4.1.1. For JavaScript projects
```js
import * as tf from '@tensorflow/tfjs';
import * as faceapi from '@vladmandic/face-api/build/index.js';
```
##### 4.1.2. For TypeScript projects
```js
import * as tf from '@tensorflow/tfjs';
import * as faceapi from '@vladmandic/face-api/src/index.ts';
```
#### 4.2. For NodeJS
##### 4.2.1. For JavaScript projects
```js
const tf = require('@tensorflow/tfjs');
const faceapi = require('@vladmandic/face-api/build/index.js');
```
##### 4.1.2. For TypeScript projects
```js
const tf = require('@tensorflow/tfjs');
const faceapi = require('@vladmandic/face-api/src/index.ts');
``` ```
## Weights ## Weights
@ -208,21 +193,50 @@ npm install
npm run build npm run build
``` ```
Which will compile everything in `./src` into `./build` and create both ESM (standard) and IIFE (minified) bundles as well as sourcemaps in `./dist` Build process uses script `build.js` that creates optimized build for each target:
## Documentation ```text
npm run build
For documentation refer to original project at <https://github.com/justadudewhohacks/face-api.js> > @vladmandic/face-api@0.8.9 build /home/vlado/dev/face-api
For original weighs refer to <https://github.com/justadudewhohacks/face-api.js-models> > rimraf dist/* && node ./build.js
For understanding of ts api code, in js examples below refer to <https://js.tensorflow.org/api/2.7.0/> ```
```json
2020-12-02 16:31:23 INFO: @vladmandic/face-api version 0.8.9
2020-12-02 16:31:23 INFO: User: vlado Platform: linux Arch: x64 Node: v15.0.1
2020-12-02 16:31:23 INFO: Build: file startup all target: es2018
2020-12-02 16:31:23 STATE: Build for: node type: tfjs: { imports: 1, importBytes: 39, outputBytes: 1042, outputFiles: 'dist/tfjs.esm.js' }
2020-12-02 16:31:23 STATE: Build for: node type: node: { imports: 160, importBytes: 228038, outputBytes: 134190, outputFiles: 'dist/face-api.node.js' }
2020-12-02 16:31:23 STATE: Build for: nodeGPU type: tfjs: { imports: 1, importBytes: 43, outputBytes: 1046, outputFiles: 'dist/tfjs.esm.js' }
2020-12-02 16:31:23 STATE: Build for: nodeGPU type: node: { imports: 160, importBytes: 228042, outputBytes: 134198, outputFiles: 'dist/face-api.node-gpu.js' }
2020-12-02 16:31:23 STATE: Build for: browserNoBundle type: tfjs: { imports: 1, importBytes: 1784, outputBytes: 244, outputFiles: 'dist/tfjs.esm.js' }
2020-12-02 16:31:23 STATE: Build for: browserNoBundle type: esm: { imports: 160, importBytes: 227240, outputBytes: 131024, outputFiles: 'dist/face-api.esm-nobundle.js' }
2020-12-02 16:31:24 STATE: Build for: browserBundle type: tfjs: { modules: 1045, moduleBytes: 3718721, imports: 7, importBytes: 1784, outputBytes: 1501677, outputFiles: 'dist/tfjs.esm.js' }
2020-12-02 16:31:24 STATE: Build for: browserBundle type: iife: { imports: 162, importBytes: 1728673, modules: 576, moduleBytes: 1359851, outputBytes: 1903311, outputFiles: 'dist/face-api.js' }
2020-12-02 16:31:25 STATE: Build for: browserBundle type: esm: { imports: 162, importBytes: 1728673, modules: 576, moduleBytes: 1359851, outputBytes: 1900836, outputFiles: 'dist/face-api.esm.js' }
```
<br>
## Credits & Documentation
- Original project and usage documentation: [Face-API](https://github.com/justadudewhohacks/face-api.js)
- Original model weighs: [Face-API](https://github.com/justadudewhohacks/face-api.js-models)
- ML API Documentation: [Tensorflow/JS](https://js.tensorflow.org/api/latest/)
<br>
## Example ## Example
<br>
### Browser ### Browser
Example that uses both models as well as all of the extensions is included in `/example/index.html` Example that uses both models as well as all of the extensions is included in `/example/index.html`
Example can be accessed directly using Git pages using URL: <https://vladmandic.github.io/face-api/example/> Example can be accessed directly using Git pages using URL: <https://vladmandic.github.io/face-api/example/>
<br>
### NodeJS ### NodeJS
Example is included in `/example/node.js` Example is included in `/example/node.js`

View File

@ -39,9 +39,9 @@ const targets = {
node: { node: {
platform: 'node', platform: 'node',
format: 'cjs', format: 'cjs',
metafile: 'dist/human.node.json', metafile: 'dist/face-api.node.json',
entryPoints: ['src/human.js'], entryPoints: ['src/index.ts'],
outfile: 'dist/human.node.js', outfile: 'dist/face-api.node.js',
external: ['@tensorflow'], external: ['@tensorflow'],
}, },
}, },
@ -49,17 +49,17 @@ const targets = {
tfjs: { tfjs: {
platform: 'node', platform: 'node',
format: 'cjs', format: 'cjs',
metafile: 'dist/tfjs.esm.json',
entryPoints: ['src/tfjs/tf-node-gpu.js'], entryPoints: ['src/tfjs/tf-node-gpu.js'],
outfile: 'dist/tfjs.esm.js', outfile: 'dist/tfjs.esm.js',
metafile: 'dist/tfjs.esm.json',
external: ['@tensorflow'], external: ['@tensorflow'],
}, },
node: { node: {
platform: 'node', platform: 'node',
format: 'cjs', format: 'cjs',
metafile: 'dist/human.node.json', entryPoints: ['src/index.ts'],
entryPoints: ['src/human.js'], outfile: 'dist/face-api.node-gpu.js',
outfile: 'dist/human.node-gpu.js', metafile: 'dist/face-api.node-gpu.json',
external: ['@tensorflow'], external: ['@tensorflow'],
}, },
}, },
@ -67,17 +67,17 @@ const targets = {
tfjs: { tfjs: {
platform: 'browser', platform: 'browser',
format: 'esm', format: 'esm',
metafile: 'dist/tfjs.esm.json',
entryPoints: ['src/tfjs/tf-browser.js'], entryPoints: ['src/tfjs/tf-browser.js'],
outfile: 'dist/tfjs.esm.js', outfile: 'dist/tfjs.esm.js',
metafile: 'dist/tfjs.esm.json',
external: ['fs', 'buffer', 'util', '@tensorflow'], external: ['fs', 'buffer', 'util', '@tensorflow'],
}, },
esm: { esm: {
platform: 'browser', platform: 'browser',
format: 'esm', format: 'esm',
metafile: 'dist/human.esm.json', entryPoints: ['src/index.ts'],
entryPoints: ['src/human.js'], outfile: 'dist/face-api.esm-nobundle.js',
outfile: 'dist/human.esm-nobundle.js', metafile: 'dist/face-api.esm-nobundle.json',
external: ['fs', 'buffer', 'util', '@tensorflow'], external: ['fs', 'buffer', 'util', '@tensorflow'],
}, },
}, },
@ -85,34 +85,26 @@ const targets = {
tfjs: { tfjs: {
platform: 'browser', platform: 'browser',
format: 'esm', format: 'esm',
metafile: 'dist/tfjs.esm.json',
entryPoints: ['src/tfjs/tf-browser.js'], entryPoints: ['src/tfjs/tf-browser.js'],
outfile: 'dist/tfjs.esm.js', outfile: 'dist/tfjs.esm.js',
metafile: 'dist/tfjs.esm.json',
external: ['fs', 'buffer', 'util'], external: ['fs', 'buffer', 'util'],
}, },
iife: { iife: {
platform: 'browser', platform: 'browser',
format: 'iife', format: 'iife',
globalName: 'Human', globalName: 'faceapi',
metafile: 'dist/human.json', entryPoints: ['src/index.ts'],
entryPoints: ['src/human.js'], outfile: 'dist/face-api.js',
outfile: 'dist/human.js', metafile: 'dist/face-api.json',
external: ['fs', 'buffer', 'util'], external: ['fs', 'buffer', 'util'],
}, },
esm: { esm: {
platform: 'browser', platform: 'browser',
format: 'esm', format: 'esm',
metafile: 'dist/human.esm.json', entryPoints: ['src/index.ts'],
entryPoints: ['src/human.js'], outfile: 'dist/face-api.esm.js',
outfile: 'dist/human.esm.js', metafile: 'dist/face-api.esm.json',
external: ['fs', 'buffer', 'util'],
},
demo: {
platform: 'browser',
format: 'esm',
metafile: 'dist/demo-browser-index.json',
entryPoints: ['demo/browser.js'],
outfile: 'dist/demo-browser-index.js',
external: ['fs', 'buffer', 'util'], external: ['fs', 'buffer', 'util'],
}, },
}, },

View File

@ -1,55 +0,0 @@
{
"name": "@vladmandic/face-api",
"version": "0.8.8",
"description": "JavaScript module for Face Detection and Face Recognition Using Tensorflow/JS",
"main": "dist/face-api.node.js",
"module": "dist/face-api.esm.js",
"browser": "dist/face-api.esm.js",
"typings": "build/src/index.d.ts",
"engines": {
"node": ">=12.0.0"
},
"scripts": {
"start": "node --trace-warnings example/node.js",
"build-esm": "esbuild --bundle --format=esm --target=es2018 --platform=browser --minify --sourcemap --outfile=./dist/face-api.esm.js --log-level=error --tsconfig=./tsconfig.json --external:util --external:string_decoder --external:fs src/index.ts",
"build-esm-nobundle": "esbuild --bundle --format=esm --target=es2018 --platform=browser --sourcemap --outfile=./dist/face-api.esm.nobundle.js --log-level=error --tsconfig=./tsconfig.json --external:@tensorflow --external:util --external:string_decoder --external:fs --global-name=faceapi src/index.ts",
"build-iife": "esbuild --bundle --format=iife --target=es2018 --platform=browser --minify --sourcemap --outfile=./dist/face-api.js --log-level=error --tsconfig=./tsconfig.json --external:util --external:string_decoder --external:fs --global-name=faceapi src/index.ts",
"build-node": "esbuild --bundle --format=cjs --target=es2018 --platform=node --minify --sourcemap --outfile=./dist/face-api.node.js --log-level=error --tsconfig=./tsconfig.json src/index.ts",
"build-node-nobundle": "esbuild --bundle --format=cjs --target=es2018 --platform=node --sourcemap --outfile=./dist/face-api.node.nobundle.js --external:@tensorflow --log-level=error --tsconfig=./tsconfig.json src/index.ts",
"build": "rimraf build/* dist/* && tsc && npm run build-iife && npm run build-esm && npm run build-esm-nobundle && npm run build-node && npm run build-node-nobundle && ls -l dist/"
},
"keywords": [
"tensorflow",
"tf",
"tfjs",
"face",
"face-api",
"face-detection",
"age-gender"
],
"repository": {
"type": "git",
"url": "git+https://github.com/vladmandic/face-api.git"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/"
},
"author": "Vladimir Mandic <mandic00@live.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/vladmandic/face-api/issues"
},
"homepage": "https://github.com/vladmandic/face-api#readme",
"Dependencies": {},
"devDependencies": {
"@tensorflow/tfjs": "^2.7.0",
"@tensorflow/tfjs-node": "^2.7.0",
"@types/node": "^14.14.10",
"esbuild": "^0.8.15",
"rimraf": "^3.0.2",
"ts-node": "^9.0.0",
"tslib": "^2.0.3",
"typescript": "^4.1.2"
},
"dependencies": {}
}

View File

@ -1,44 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
import { ParamMapping } from './common';
export declare abstract class NeuralNetwork<TNetParams> {
protected _name: string;
protected _params: TNetParams | undefined;
protected _paramMappings: ParamMapping[];
constructor(_name: string);
get params(): TNetParams | undefined;
get paramMappings(): ParamMapping[];
get isLoaded(): boolean;
getParamFromPath(paramPath: string): tf.Tensor;
reassignParamFromPath(paramPath: string, tensor: tf.Tensor): void;
getParamList(): {
path: string;
tensor: any;
}[];
getTrainableParams(): {
path: string;
tensor: any;
}[];
getFrozenParams(): {
path: string;
tensor: any;
}[];
variable(): void;
freeze(): void;
dispose(throwOnRedispose?: boolean): void;
serializeParams(): Float32Array;
load(weightsOrUrl: Float32Array | string | undefined): Promise<void>;
loadFromUri(uri: string | undefined): Promise<void>;
loadFromDisk(filePath: string | undefined): Promise<void>;
loadFromWeightMap(weightMap: tf.NamedTensorMap): void;
extractWeights(weights: Float32Array): void;
private traversePropertyPath;
protected abstract getDefaultModelName(): string;
protected abstract extractParamsFromWeigthMap(weightMap: tf.NamedTensorMap): {
params: TNetParams;
paramMappings: ParamMapping[];
};
protected abstract extractParams(weights: Float32Array): {
params: TNetParams;
paramMappings: ParamMapping[];
};
}

View File

@ -1,122 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
import { getModelUris } from './common/getModelUris';
import { loadWeightMap } from './dom';
import { env } from './env';
export class NeuralNetwork {
constructor(_name) {
this._name = _name;
this._params = undefined;
this._paramMappings = [];
/*
try {
const testTensor = tf.tensor([0]);
testTensor.toFloat();
} catch (err) {
throw new Error(`tfjs module not loaded: load '@tensorflow/tfjs' or '@tensorflow/tfjs-core' with appropriate backend explicitly`);
}
*/
}
get params() { return this._params; }
get paramMappings() { return this._paramMappings; }
get isLoaded() { return !!this.params; }
getParamFromPath(paramPath) {
const { obj, objProp } = this.traversePropertyPath(paramPath);
return obj[objProp];
}
reassignParamFromPath(paramPath, tensor) {
const { obj, objProp } = this.traversePropertyPath(paramPath);
obj[objProp].dispose();
obj[objProp] = tensor;
}
getParamList() {
return this._paramMappings.map(({ paramPath }) => ({
path: paramPath,
tensor: this.getParamFromPath(paramPath)
}));
}
getTrainableParams() {
return this.getParamList().filter(param => param.tensor instanceof tf.Variable);
}
getFrozenParams() {
return this.getParamList().filter(param => !(param.tensor instanceof tf.Variable));
}
variable() {
this.getFrozenParams().forEach(({ path, tensor }) => {
this.reassignParamFromPath(path, tensor.variable());
});
}
freeze() {
this.getTrainableParams().forEach(({ path, tensor: variable }) => {
const tensor = tf.tensor(variable.dataSync());
variable.dispose();
this.reassignParamFromPath(path, tensor);
});
}
dispose(throwOnRedispose = true) {
this.getParamList().forEach(param => {
if (throwOnRedispose && param.tensor.isDisposed) {
throw new Error(`param tensor has already been disposed for path ${param.path}`);
}
param.tensor.dispose();
});
this._params = undefined;
}
serializeParams() {
return new Float32Array(this.getParamList()
.map(({ tensor }) => Array.from(tensor.dataSync()))
.reduce((flat, arr) => flat.concat(arr)));
}
async load(weightsOrUrl) {
if (weightsOrUrl instanceof Float32Array) {
this.extractWeights(weightsOrUrl);
return;
}
await this.loadFromUri(weightsOrUrl);
}
async loadFromUri(uri) {
if (uri && typeof uri !== 'string') {
throw new Error(`${this._name}.loadFromUri - expected model uri`);
}
const weightMap = await loadWeightMap(uri, this.getDefaultModelName());
this.loadFromWeightMap(weightMap);
}
async loadFromDisk(filePath) {
if (filePath && typeof filePath !== 'string') {
throw new Error(`${this._name}.loadFromDisk - expected model file path`);
}
const { readFile } = env.getEnv();
const { manifestUri, modelBaseUri } = getModelUris(filePath, this.getDefaultModelName());
const fetchWeightsFromDisk = (filePaths) => Promise.all(filePaths.map(filePath => readFile(filePath).then(buf => buf.buffer)));
const loadWeights = tf.io.weightsLoaderFactory(fetchWeightsFromDisk);
const manifest = JSON.parse((await readFile(manifestUri)).toString());
const weightMap = await loadWeights(manifest, modelBaseUri);
this.loadFromWeightMap(weightMap);
}
loadFromWeightMap(weightMap) {
const { paramMappings, params } = this.extractParamsFromWeigthMap(weightMap);
this._paramMappings = paramMappings;
this._params = params;
}
extractWeights(weights) {
const { paramMappings, params } = this.extractParams(weights);
this._paramMappings = paramMappings;
this._params = params;
}
traversePropertyPath(paramPath) {
if (!this.params) {
throw new Error(`traversePropertyPath - model has no loaded params`);
}
const result = paramPath.split('/').reduce((res, objProp) => {
if (!res.nextObj.hasOwnProperty(objProp)) {
throw new Error(`traversePropertyPath - object does not have property ${objProp}, for path ${paramPath}`);
}
return { obj: res.nextObj, objProp, nextObj: res.nextObj[objProp] };
}, { nextObj: this.params });
const { obj, objProp } = result;
if (!obj || !objProp || !(obj[objProp] instanceof tf.Tensor)) {
throw new Error(`traversePropertyPath - parameter is not a tensor, for path ${paramPath}`);
}
return { obj, objProp };
}
}
//# sourceMappingURL=NeuralNetwork.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"NeuralNetwork.js","sourceRoot":"","sources":["../../src/NeuralNetwork.ts"],"names":[],"mappings":"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"}

View File

@ -1,7 +0,0 @@
export declare class PlatformBrowser {
private textEncoder;
fetch(path: string, init?: RequestInit): Promise<Response>;
now(): number;
encode(text: string, encoding: string): Uint8Array;
decode(bytes: Uint8Array, encoding: string): string;
}

View File

@ -1,21 +0,0 @@
export class PlatformBrowser {
fetch(path, init) {
return fetch(path, init);
}
now() {
return performance.now();
}
encode(text, encoding) {
if (encoding !== 'utf-8' && encoding !== 'utf8') {
throw new Error(`Browser's encoder only supports utf-8, but got ${encoding}`);
}
if (this.textEncoder == null) {
this.textEncoder = new TextEncoder();
}
return this.textEncoder.encode(text);
}
decode(bytes, encoding) {
return new TextDecoder(encoding).decode(bytes);
}
}
//# sourceMappingURL=Platform.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"Platform.js","sourceRoot":"","sources":["../../src/Platform.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,eAAe;IAG1B,KAAK,CAAC,IAAY,EAAE,IAAkB;QACpC,OAAO,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,GAAG;QACD,OAAO,WAAW,CAAC,GAAG,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,IAAY,EAAE,QAAgB;QACnC,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,MAAM,EAAE;YAC/C,MAAM,IAAI,KAAK,CACX,kDAAkD,QAAQ,EAAE,CAAC,CAAC;SACnE;QACD,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,EAAE;YAC5B,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;SACtC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,CAAC,KAAiB,EAAE,QAAgB;QACxC,OAAO,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC;CACF"}

View File

@ -1,29 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
import { TinyXception } from '../xception/TinyXception';
import { AgeAndGenderPrediction, NetOutput, NetParams } from './types';
import { NeuralNetwork } from '../NeuralNetwork';
import { NetInput, TNetInput } from '../dom';
export declare class AgeGenderNet extends NeuralNetwork<NetParams> {
private _faceFeatureExtractor;
constructor(faceFeatureExtractor?: TinyXception);
get faceFeatureExtractor(): TinyXception;
runNet(input: NetInput | tf.Tensor4D): NetOutput;
forwardInput(input: NetInput | tf.Tensor4D): NetOutput;
forward(input: TNetInput): Promise<NetOutput>;
predictAgeAndGender(input: TNetInput): Promise<AgeAndGenderPrediction | AgeAndGenderPrediction[]>;
protected getDefaultModelName(): string;
dispose(throwOnRedispose?: boolean): void;
loadClassifierParams(weights: Float32Array): void;
extractClassifierParams(weights: Float32Array): {
params: NetParams;
paramMappings: import("../common").ParamMapping[];
};
protected extractParamsFromWeigthMap(weightMap: tf.NamedTensorMap): {
params: NetParams;
paramMappings: import("../common").ParamMapping[];
};
protected extractParams(weights: Float32Array): {
params: NetParams;
paramMappings: import("../common").ParamMapping[];
};
}

View File

@ -1,93 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
import { fullyConnectedLayer } from '../common/fullyConnectedLayer';
import { seperateWeightMaps } from '../faceProcessor/util';
import { TinyXception } from '../xception/TinyXception';
import { extractParams } from './extractParams';
import { extractParamsFromWeigthMap } from './extractParamsFromWeigthMap';
import { Gender } from './types';
import { NeuralNetwork } from '../NeuralNetwork';
import { NetInput, toNetInput } from '../dom';
export class AgeGenderNet extends NeuralNetwork {
constructor(faceFeatureExtractor = new TinyXception(2)) {
super('AgeGenderNet');
this._faceFeatureExtractor = faceFeatureExtractor;
}
get faceFeatureExtractor() {
return this._faceFeatureExtractor;
}
runNet(input) {
const { params } = this;
if (!params) {
throw new Error(`${this._name} - load model before inference`);
}
return tf.tidy(() => {
const bottleneckFeatures = input instanceof NetInput
? this.faceFeatureExtractor.forwardInput(input)
: input;
const pooled = tf.avgPool(bottleneckFeatures, [7, 7], [2, 2], 'valid').as2D(bottleneckFeatures.shape[0], -1);
const age = fullyConnectedLayer(pooled, params.fc.age).as1D();
const gender = fullyConnectedLayer(pooled, params.fc.gender);
return { age, gender };
});
}
forwardInput(input) {
return tf.tidy(() => {
const { age, gender } = this.runNet(input);
return { age, gender: tf.softmax(gender) };
});
}
async forward(input) {
return this.forwardInput(await toNetInput(input));
}
async predictAgeAndGender(input) {
const netInput = await toNetInput(input);
const out = await this.forwardInput(netInput);
const ages = tf.unstack(out.age);
const genders = tf.unstack(out.gender);
const ageAndGenderTensors = ages.map((ageTensor, i) => ({
ageTensor,
genderTensor: genders[i]
}));
const predictionsByBatch = await Promise.all(ageAndGenderTensors.map(async ({ ageTensor, genderTensor }) => {
const age = (await ageTensor.data())[0];
const probMale = (await genderTensor.data())[0];
const isMale = probMale > 0.5;
const gender = isMale ? Gender.MALE : Gender.FEMALE;
const genderProbability = isMale ? probMale : (1 - probMale);
ageTensor.dispose();
genderTensor.dispose();
return { age, gender, genderProbability };
}));
out.age.dispose();
out.gender.dispose();
return netInput.isBatchInput ? predictionsByBatch : predictionsByBatch[0];
}
getDefaultModelName() {
return 'age_gender_model';
}
dispose(throwOnRedispose = true) {
this.faceFeatureExtractor.dispose(throwOnRedispose);
super.dispose(throwOnRedispose);
}
loadClassifierParams(weights) {
const { params, paramMappings } = this.extractClassifierParams(weights);
this._params = params;
this._paramMappings = paramMappings;
}
extractClassifierParams(weights) {
return extractParams(weights);
}
extractParamsFromWeigthMap(weightMap) {
const { featureExtractorMap, classifierMap } = seperateWeightMaps(weightMap);
this.faceFeatureExtractor.loadFromWeightMap(featureExtractorMap);
return extractParamsFromWeigthMap(classifierMap);
}
extractParams(weights) {
const classifierWeightSize = (512 * 1 + 1) + (512 * 2 + 2);
const featureExtractorWeights = weights.slice(0, weights.length - classifierWeightSize);
const classifierWeights = weights.slice(weights.length - classifierWeightSize);
this.faceFeatureExtractor.extractWeights(featureExtractorWeights);
return this.extractClassifierParams(classifierWeights);
}
}
//# sourceMappingURL=AgeGenderNet.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"AgeGenderNet.js","sourceRoot":"","sources":["../../../src/ageGenderNet/AgeGenderNet.ts"],"names":[],"mappings":"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"}

View File

@ -1,6 +0,0 @@
import { ParamMapping } from '../common';
import { NetParams } from './types';
export declare function extractParams(weights: Float32Array): {
params: NetParams;
paramMappings: ParamMapping[];
};

View File

@ -1,16 +0,0 @@
import { extractFCParamsFactory, extractWeightsFactory } from '../common';
export function extractParams(weights) {
const paramMappings = [];
const { extractWeights, getRemainingWeights } = extractWeightsFactory(weights);
const extractFCParams = extractFCParamsFactory(extractWeights, paramMappings);
const age = extractFCParams(512, 1, 'fc/age');
const gender = extractFCParams(512, 2, 'fc/gender');
if (getRemainingWeights().length !== 0) {
throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`);
}
return {
paramMappings,
params: { fc: { age, gender } }
};
}
//# sourceMappingURL=extractParams.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"extractParams.js","sourceRoot":"","sources":["../../../src/ageGenderNet/extractParams.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAgB,MAAM,WAAW,CAAC;AAGxF,MAAM,UAAU,aAAa,CAAC,OAAqB;IAEjD,MAAM,aAAa,GAAmB,EAAE,CAAA;IAExC,MAAM,EACJ,cAAc,EACd,mBAAmB,EACpB,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAA;IAElC,MAAM,eAAe,GAAG,sBAAsB,CAAC,cAAc,EAAE,aAAa,CAAC,CAAA;IAE7E,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAA;IAC7C,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,EAAE,CAAC,EAAE,WAAW,CAAC,CAAA;IAEnD,IAAI,mBAAmB,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE;QACtC,MAAM,IAAI,KAAK,CAAC,kCAAkC,mBAAmB,EAAE,CAAC,MAAM,EAAE,CAAC,CAAA;KAClF;IAED,OAAO;QACL,aAAa;QACb,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE;KAChC,CAAA;AACH,CAAC"}

View File

@ -1,7 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
import { ParamMapping } from '../common';
import { NetParams } from './types';
export declare function extractParamsFromWeigthMap(weightMap: tf.NamedTensorMap): {
params: NetParams;
paramMappings: ParamMapping[];
};

View File

@ -1,19 +0,0 @@
import { disposeUnusedWeightTensors, extractWeightEntryFactory } from '../common';
export function extractParamsFromWeigthMap(weightMap) {
const paramMappings = [];
const extractWeightEntry = extractWeightEntryFactory(weightMap, paramMappings);
function extractFcParams(prefix) {
const weights = extractWeightEntry(`${prefix}/weights`, 2);
const bias = extractWeightEntry(`${prefix}/bias`, 1);
return { weights, bias };
}
const params = {
fc: {
age: extractFcParams('fc/age'),
gender: extractFcParams('fc/gender')
}
};
disposeUnusedWeightTensors(weightMap, paramMappings);
return { params, paramMappings };
}
//# sourceMappingURL=extractParamsFromWeigthMap.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"extractParamsFromWeigthMap.js","sourceRoot":"","sources":["../../../src/ageGenderNet/extractParamsFromWeigthMap.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,yBAAyB,EAA0B,MAAM,WAAW,CAAC;AAG1G,MAAM,UAAU,0BAA0B,CACxC,SAA4B;IAG5B,MAAM,aAAa,GAAmB,EAAE,CAAA;IAExC,MAAM,kBAAkB,GAAG,yBAAyB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IAE9E,SAAS,eAAe,CAAC,MAAc;QACrC,MAAM,OAAO,GAAG,kBAAkB,CAAc,GAAG,MAAM,UAAU,EAAE,CAAC,CAAC,CAAA;QACvE,MAAM,IAAI,GAAG,kBAAkB,CAAc,GAAG,MAAM,OAAO,EAAE,CAAC,CAAC,CAAA;QACjE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;IAC1B,CAAC;IAED,MAAM,MAAM,GAAG;QACb,EAAE,EAAE;YACF,GAAG,EAAE,eAAe,CAAC,QAAQ,CAAC;YAC9B,MAAM,EAAE,eAAe,CAAC,WAAW,CAAC;SACrC;KACF,CAAA;IAED,0BAA0B,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IAEpD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAA;AAClC,CAAC"}

View File

@ -1,2 +0,0 @@
export * from './AgeGenderNet';
export * from './types';

View File

@ -1,3 +0,0 @@
export * from './AgeGenderNet';
export * from './types';
//# sourceMappingURL=index.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ageGenderNet/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC"}

View File

@ -1,21 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
import { FCParams } from '../common';
export declare type AgeAndGenderPrediction = {
age: number;
gender: Gender;
genderProbability: number;
};
export declare enum Gender {
FEMALE = "female",
MALE = "male"
}
export declare type NetOutput = {
age: tf.Tensor1D;
gender: tf.Tensor2D;
};
export declare type NetParams = {
fc: {
age: FCParams;
gender: FCParams;
};
};

View File

@ -1,6 +0,0 @@
export var Gender;
(function (Gender) {
Gender["FEMALE"] = "female";
Gender["MALE"] = "male";
})(Gender || (Gender = {}));
//# sourceMappingURL=types.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/ageGenderNet/types.ts"],"names":[],"mappings":"AAUA,MAAM,CAAN,IAAY,MAGX;AAHD,WAAY,MAAM;IAChB,2BAAiB,CAAA;IACjB,uBAAa,CAAA;AACf,CAAC,EAHW,MAAM,KAAN,MAAM,QAGjB"}

View File

@ -1,10 +0,0 @@
import { Box } from './Box';
export interface IBoundingBox {
left: number;
top: number;
right: number;
bottom: number;
}
export declare class BoundingBox extends Box<BoundingBox> implements IBoundingBox {
constructor(left: number, top: number, right: number, bottom: number, allowNegativeDimensions?: boolean);
}

View File

@ -1,7 +0,0 @@
import { Box } from './Box';
export class BoundingBox extends Box {
constructor(left, top, right, bottom, allowNegativeDimensions = false) {
super({ left, top, right, bottom }, allowNegativeDimensions);
}
}
//# sourceMappingURL=BoundingBox.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"BoundingBox.js","sourceRoot":"","sources":["../../../src/classes/BoundingBox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAS5B,MAAM,OAAO,WAAY,SAAQ,GAAgB;IAC/C,YAAY,IAAY,EAAE,GAAW,EAAE,KAAa,EAAE,MAAc,EAAE,0BAAmC,KAAK;QAC5G,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,uBAAuB,CAAC,CAAA;IAC9D,CAAC;CACF"}

View File

@ -1,46 +0,0 @@
import { IBoundingBox } from './BoundingBox';
import { IDimensions } from './Dimensions';
import { Point } from './Point';
import { IRect } from './Rect';
export declare class Box<BoxType = any> implements IBoundingBox, IRect {
static isRect(rect: any): boolean;
static assertIsValidBox(box: any, callee: string, allowNegativeDimensions?: boolean): void;
private _x;
private _y;
private _width;
private _height;
constructor(_box: IBoundingBox | IRect, allowNegativeDimensions?: boolean);
get x(): number;
get y(): number;
get width(): number;
get height(): number;
get left(): number;
get top(): number;
get right(): number;
get bottom(): number;
get area(): number;
get topLeft(): Point;
get topRight(): Point;
get bottomLeft(): Point;
get bottomRight(): Point;
round(): Box<BoxType>;
floor(): Box<BoxType>;
toSquare(): Box<BoxType>;
rescale(s: IDimensions | number): Box<BoxType>;
pad(padX: number, padY: number): Box<BoxType>;
clipAtImageBorders(imgWidth: number, imgHeight: number): Box<BoxType>;
shift(sx: number, sy: number): Box<BoxType>;
padAtBorders(imageHeight: number, imageWidth: number): {
dy: number;
edy: number;
dx: number;
edx: number;
y: number;
ey: number;
x: number;
ex: number;
w: number;
h: number;
};
calibrate(region: Box): Box<any>;
}

View File

@ -1,140 +0,0 @@
import { isDimensions, isValidNumber } from '../utils';
import { Point } from './Point';
export class Box {
constructor(_box, allowNegativeDimensions = true) {
const box = (_box || {});
const isBbox = [box.left, box.top, box.right, box.bottom].every(isValidNumber);
const isRect = [box.x, box.y, box.width, box.height].every(isValidNumber);
if (!isRect && !isBbox) {
throw new Error(`Box.constructor - expected box to be IBoundingBox | IRect, instead have ${JSON.stringify(box)}`);
}
const [x, y, width, height] = isRect
? [box.x, box.y, box.width, box.height]
: [box.left, box.top, box.right - box.left, box.bottom - box.top];
Box.assertIsValidBox({ x, y, width, height }, 'Box.constructor', allowNegativeDimensions);
this._x = x;
this._y = y;
this._width = width;
this._height = height;
}
static isRect(rect) {
return !!rect && [rect.x, rect.y, rect.width, rect.height].every(isValidNumber);
}
static assertIsValidBox(box, callee, allowNegativeDimensions = false) {
if (!Box.isRect(box)) {
throw new Error(`${callee} - invalid box: ${JSON.stringify(box)}, expected object with properties x, y, width, height`);
}
if (!allowNegativeDimensions && (box.width < 0 || box.height < 0)) {
throw new Error(`${callee} - width (${box.width}) and height (${box.height}) must be positive numbers`);
}
}
get x() { return this._x; }
get y() { return this._y; }
get width() { return this._width; }
get height() { return this._height; }
get left() { return this.x; }
get top() { return this.y; }
get right() { return this.x + this.width; }
get bottom() { return this.y + this.height; }
get area() { return this.width * this.height; }
get topLeft() { return new Point(this.left, this.top); }
get topRight() { return new Point(this.right, this.top); }
get bottomLeft() { return new Point(this.left, this.bottom); }
get bottomRight() { return new Point(this.right, this.bottom); }
round() {
const [x, y, width, height] = [this.x, this.y, this.width, this.height]
.map(val => Math.round(val));
return new Box({ x, y, width, height });
}
floor() {
const [x, y, width, height] = [this.x, this.y, this.width, this.height]
.map(val => Math.floor(val));
return new Box({ x, y, width, height });
}
toSquare() {
let { x, y, width, height } = this;
const diff = Math.abs(width - height);
if (width < height) {
x -= (diff / 2);
width += diff;
}
if (height < width) {
y -= (diff / 2);
height += diff;
}
return new Box({ x, y, width, height });
}
rescale(s) {
const scaleX = isDimensions(s) ? s.width : s;
const scaleY = isDimensions(s) ? s.height : s;
return new Box({
x: this.x * scaleX,
y: this.y * scaleY,
width: this.width * scaleX,
height: this.height * scaleY
});
}
pad(padX, padY) {
let [x, y, width, height] = [
this.x - (padX / 2),
this.y - (padY / 2),
this.width + padX,
this.height + padY
];
return new Box({ x, y, width, height });
}
clipAtImageBorders(imgWidth, imgHeight) {
const { x, y, right, bottom } = this;
const clippedX = Math.max(x, 0);
const clippedY = Math.max(y, 0);
const newWidth = right - clippedX;
const newHeight = bottom - clippedY;
const clippedWidth = Math.min(newWidth, imgWidth - clippedX);
const clippedHeight = Math.min(newHeight, imgHeight - clippedY);
return (new Box({ x: clippedX, y: clippedY, width: clippedWidth, height: clippedHeight })).floor();
}
shift(sx, sy) {
const { width, height } = this;
const x = this.x + sx;
const y = this.y + sy;
return new Box({ x, y, width, height });
}
padAtBorders(imageHeight, imageWidth) {
const w = this.width + 1;
const h = this.height + 1;
let dx = 1;
let dy = 1;
let edx = w;
let edy = h;
let x = this.left;
let y = this.top;
let ex = this.right;
let ey = this.bottom;
if (ex > imageWidth) {
edx = -ex + imageWidth + w;
ex = imageWidth;
}
if (ey > imageHeight) {
edy = -ey + imageHeight + h;
ey = imageHeight;
}
if (x < 1) {
edy = 2 - x;
x = 1;
}
if (y < 1) {
edy = 2 - y;
y = 1;
}
return { dy, edy, dx, edx, y, ey, x, ex, w, h };
}
calibrate(region) {
return new Box({
left: this.left + (region.left * this.width),
top: this.top + (region.top * this.height),
right: this.right + (region.right * this.width),
bottom: this.bottom + (region.bottom * this.height)
}).toSquare().round();
}
}
//# sourceMappingURL=Box.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,12 +0,0 @@
export interface IDimensions {
width: number;
height: number;
}
export declare class Dimensions implements IDimensions {
private _width;
private _height;
constructor(width: number, height: number);
get width(): number;
get height(): number;
reverse(): Dimensions;
}

View File

@ -1,16 +0,0 @@
import { isValidNumber } from '../utils';
export class Dimensions {
constructor(width, height) {
if (!isValidNumber(width) || !isValidNumber(height)) {
throw new Error(`Dimensions.constructor - expected width and height to be valid numbers, instead have ${JSON.stringify({ width, height })}`);
}
this._width = width;
this._height = height;
}
get width() { return this._width; }
get height() { return this._height; }
reverse() {
return new Dimensions(1 / this.width, 1 / this.height);
}
}
//# sourceMappingURL=Dimensions.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"Dimensions.js","sourceRoot":"","sources":["../../../src/classes/Dimensions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAOzC,MAAM,OAAO,UAAU;IAKrB,YAAY,KAAa,EAAE,MAAc;QACvC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE;YACnD,MAAM,IAAI,KAAK,CAAC,wFAAwF,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;SAC7I;QAED,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;IACvB,CAAC;IAED,IAAW,KAAK,KAAa,OAAO,IAAI,CAAC,MAAM,CAAA,CAAC,CAAC;IACjD,IAAW,MAAM,KAAa,OAAO,IAAI,CAAC,OAAO,CAAA,CAAC,CAAC;IAE5C,OAAO;QACZ,OAAO,IAAI,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;IACxD,CAAC;CACF"}

View File

@ -1,12 +0,0 @@
import { Box } from './Box';
import { IDimensions } from './Dimensions';
import { ObjectDetection } from './ObjectDetection';
import { Rect } from './Rect';
export interface IFaceDetecion {
score: number;
box: Box;
}
export declare class FaceDetection extends ObjectDetection implements IFaceDetecion {
constructor(score: number, relativeBox: Rect, imageDims: IDimensions);
forSize(width: number, height: number): FaceDetection;
}

View File

@ -1,11 +0,0 @@
import { ObjectDetection } from './ObjectDetection';
export class FaceDetection extends ObjectDetection {
constructor(score, relativeBox, imageDims) {
super(score, score, '', relativeBox, imageDims);
}
forSize(width, height) {
const { score, relativeBox, imageDims } = super.forSize(width, height);
return new FaceDetection(score, relativeBox, imageDims);
}
}
//# sourceMappingURL=FaceDetection.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"FaceDetection.js","sourceRoot":"","sources":["../../../src/classes/FaceDetection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAQpD,MAAM,OAAO,aAAc,SAAQ,eAAe;IAChD,YACE,KAAa,EACb,WAAiB,EACjB,SAAsB;QAEtB,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,SAAS,CAAC,CAAA;IACjD,CAAC;IAEM,OAAO,CAAC,KAAa,EAAE,MAAc;QAC1C,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QACtE,OAAO,IAAI,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,CAAC,CAAA;IACzD,CAAC;CACF"}

View File

@ -1,42 +0,0 @@
import { IBoundingBox } from './BoundingBox';
import { Box } from './Box';
import { Dimensions, IDimensions } from './Dimensions';
import { FaceDetection } from './FaceDetection';
import { Point } from './Point';
import { IRect } from './Rect';
export interface IFaceLandmarks {
positions: Point[];
shift: Point;
}
export declare class FaceLandmarks implements IFaceLandmarks {
protected _shift: Point;
protected _positions: Point[];
protected _imgDims: Dimensions;
constructor(relativeFaceLandmarkPositions: Point[], imgDims: IDimensions, shift?: Point);
get shift(): Point;
get imageWidth(): number;
get imageHeight(): number;
get positions(): Point[];
get relativePositions(): Point[];
forSize<T extends FaceLandmarks>(width: number, height: number): T;
shiftBy<T extends FaceLandmarks>(x: number, y: number): T;
shiftByPoint<T extends FaceLandmarks>(pt: Point): T;
/**
* Aligns the face landmarks after face detection from the relative positions of the faces
* bounding box, or it's current shift. This function should be used to align the face images
* after face detection has been performed, before they are passed to the face recognition net.
* This will make the computed face descriptor more accurate.
*
* @param detection (optional) The bounding box of the face or the face detection result. If
* no argument was passed the position of the face landmarks are assumed to be relative to
* it's current shift.
* @returns The bounding box of the aligned face.
*/
align(detection?: FaceDetection | IRect | IBoundingBox | null, options?: {
useDlibAlignment?: boolean;
minBoxPadding?: number;
}): Box;
private alignDlib;
private alignMinBbox;
protected getRefPointsForAlignment(): Point[];
}

View File

@ -1,79 +0,0 @@
import { minBbox } from '../ops';
import { getCenterPoint } from '../utils';
import { Box } from './Box';
import { Dimensions } from './Dimensions';
import { FaceDetection } from './FaceDetection';
import { Point } from './Point';
import { Rect } from './Rect';
// face alignment constants
const relX = 0.5;
const relY = 0.43;
const relScale = 0.45;
export class FaceLandmarks {
constructor(relativeFaceLandmarkPositions, imgDims, shift = new Point(0, 0)) {
const { width, height } = imgDims;
this._imgDims = new Dimensions(width, height);
this._shift = shift;
this._positions = relativeFaceLandmarkPositions.map(pt => pt.mul(new Point(width, height)).add(shift));
}
get shift() { return new Point(this._shift.x, this._shift.y); }
get imageWidth() { return this._imgDims.width; }
get imageHeight() { return this._imgDims.height; }
get positions() { return this._positions; }
get relativePositions() {
return this._positions.map(pt => pt.sub(this._shift).div(new Point(this.imageWidth, this.imageHeight)));
}
forSize(width, height) {
return new this.constructor(this.relativePositions, { width, height });
}
shiftBy(x, y) {
return new this.constructor(this.relativePositions, this._imgDims, new Point(x, y));
}
shiftByPoint(pt) {
return this.shiftBy(pt.x, pt.y);
}
/**
* Aligns the face landmarks after face detection from the relative positions of the faces
* bounding box, or it's current shift. This function should be used to align the face images
* after face detection has been performed, before they are passed to the face recognition net.
* This will make the computed face descriptor more accurate.
*
* @param detection (optional) The bounding box of the face or the face detection result. If
* no argument was passed the position of the face landmarks are assumed to be relative to
* it's current shift.
* @returns The bounding box of the aligned face.
*/
align(detection, options = {}) {
if (detection) {
const box = detection instanceof FaceDetection
? detection.box.floor()
: new Box(detection);
return this.shiftBy(box.x, box.y).align(null, options);
}
const { useDlibAlignment, minBoxPadding } = Object.assign({}, { useDlibAlignment: false, minBoxPadding: 0.2 }, options);
if (useDlibAlignment) {
return this.alignDlib();
}
return this.alignMinBbox(minBoxPadding);
}
alignDlib() {
const centers = this.getRefPointsForAlignment();
const [leftEyeCenter, rightEyeCenter, mouthCenter] = centers;
const distToMouth = (pt) => mouthCenter.sub(pt).magnitude();
const eyeToMouthDist = (distToMouth(leftEyeCenter) + distToMouth(rightEyeCenter)) / 2;
const size = Math.floor(eyeToMouthDist / relScale);
const refPoint = getCenterPoint(centers);
// TODO: pad in case rectangle is out of image bounds
const x = Math.floor(Math.max(0, refPoint.x - (relX * size)));
const y = Math.floor(Math.max(0, refPoint.y - (relY * size)));
return new Rect(x, y, Math.min(size, this.imageWidth + x), Math.min(size, this.imageHeight + y));
}
alignMinBbox(padding) {
const box = minBbox(this.positions);
return box.pad(box.width * padding, box.height * padding);
}
getRefPointsForAlignment() {
throw new Error('getRefPointsForAlignment not implemented by base class');
}
}
//# sourceMappingURL=FaceLandmarks.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"FaceLandmarks.js","sourceRoot":"","sources":["../../../src/classes/FaceLandmarks.ts"],"names":[],"mappings":"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"}

View File

@ -1,5 +0,0 @@
import { FaceLandmarks } from './FaceLandmarks';
import { Point } from './Point';
export declare class FaceLandmarks5 extends FaceLandmarks {
protected getRefPointsForAlignment(): Point[];
}

View File

@ -1,13 +0,0 @@
import { getCenterPoint } from '../utils';
import { FaceLandmarks } from './FaceLandmarks';
export class FaceLandmarks5 extends FaceLandmarks {
getRefPointsForAlignment() {
const pts = this.positions;
return [
pts[0],
pts[1],
getCenterPoint([pts[3], pts[4]])
];
}
}
//# sourceMappingURL=FaceLandmarks5.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"FaceLandmarks5.js","sourceRoot":"","sources":["../../../src/classes/FaceLandmarks5.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIhD,MAAM,OAAO,cAAe,SAAQ,aAAa;IAErC,wBAAwB;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAA;QAC1B,OAAO;YACL,GAAG,CAAC,CAAC,CAAC;YACN,GAAG,CAAC,CAAC,CAAC;YACN,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SACjC,CAAA;IACH,CAAC;CACF"}

View File

@ -1,12 +0,0 @@
import { FaceLandmarks } from './FaceLandmarks';
import { Point } from './Point';
export declare class FaceLandmarks68 extends FaceLandmarks {
getJawOutline(): Point[];
getLeftEyeBrow(): Point[];
getRightEyeBrow(): Point[];
getNose(): Point[];
getLeftEye(): Point[];
getRightEye(): Point[];
getMouth(): Point[];
protected getRefPointsForAlignment(): Point[];
}

View File

@ -1,33 +0,0 @@
import { getCenterPoint } from '../utils';
import { FaceLandmarks } from './FaceLandmarks';
export class FaceLandmarks68 extends FaceLandmarks {
getJawOutline() {
return this.positions.slice(0, 17);
}
getLeftEyeBrow() {
return this.positions.slice(17, 22);
}
getRightEyeBrow() {
return this.positions.slice(22, 27);
}
getNose() {
return this.positions.slice(27, 36);
}
getLeftEye() {
return this.positions.slice(36, 42);
}
getRightEye() {
return this.positions.slice(42, 48);
}
getMouth() {
return this.positions.slice(48, 68);
}
getRefPointsForAlignment() {
return [
this.getLeftEye(),
this.getRightEye(),
this.getMouth()
].map(getCenterPoint);
}
}
//# sourceMappingURL=FaceLandmarks68.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"FaceLandmarks68.js","sourceRoot":"","sources":["../../../src/classes/FaceLandmarks68.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,MAAM,OAAO,eAAgB,SAAQ,aAAa;IACzC,aAAa;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACpC,CAAC;IAEM,cAAc;QACnB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACrC,CAAC;IAEM,eAAe;QACpB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACrC,CAAC;IAEM,OAAO;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACrC,CAAC;IAEM,UAAU;QACf,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACrC,CAAC;IAEM,WAAW;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACrC,CAAC;IAEM,QAAQ;QACb,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACrC,CAAC;IAES,wBAAwB;QAChC,OAAO;YACL,IAAI,CAAC,UAAU,EAAE;YACjB,IAAI,CAAC,WAAW,EAAE;YAClB,IAAI,CAAC,QAAQ,EAAE;SAChB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;IACvB,CAAC;CACF"}

View File

@ -1,12 +0,0 @@
export interface IFaceMatch {
label: string;
distance: number;
}
export declare class FaceMatch implements IFaceMatch {
private _label;
private _distance;
constructor(label: string, distance: number);
get label(): string;
get distance(): number;
toString(withDistance?: boolean): string;
}

View File

@ -1,13 +0,0 @@
import { round } from '../utils';
export class FaceMatch {
constructor(label, distance) {
this._label = label;
this._distance = distance;
}
get label() { return this._label; }
get distance() { return this._distance; }
toString(withDistance = true) {
return `${this.label}${withDistance ? ` (${round(this.distance)})` : ''}`;
}
}
//# sourceMappingURL=FaceMatch.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"FaceMatch.js","sourceRoot":"","sources":["../../../src/classes/FaceMatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAOjC,MAAM,OAAO,SAAS;IAIpB,YAAY,KAAa,EAAE,QAAgB;QACzC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAA;IAC3B,CAAC;IAED,IAAW,KAAK,KAAa,OAAO,IAAI,CAAC,MAAM,CAAA,CAAC,CAAC;IACjD,IAAW,QAAQ,KAAa,OAAO,IAAI,CAAC,SAAS,CAAA,CAAC,CAAC;IAEhD,QAAQ,CAAC,eAAwB,IAAI;QAC1C,OAAO,GAAG,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;IAC3E,CAAC;CACF"}

View File

@ -1,9 +0,0 @@
import { IBoundingBox } from './BoundingBox';
import { Box } from './Box';
import { IRect } from './Rect';
export declare class LabeledBox extends Box<LabeledBox> {
static assertIsValidLabeledBox(box: any, callee: string): void;
private _label;
constructor(box: IBoundingBox | IRect | any, label: number);
get label(): number;
}

View File

@ -1,16 +0,0 @@
import { isValidNumber } from '../utils';
import { Box } from './Box';
export class LabeledBox extends Box {
constructor(box, label) {
super(box);
this._label = label;
}
static assertIsValidLabeledBox(box, callee) {
Box.assertIsValidBox(box, callee);
if (!isValidNumber(box.label)) {
throw new Error(`${callee} - expected property label (${box.label}) to be a number`);
}
}
get label() { return this._label; }
}
//# sourceMappingURL=LabeledBox.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"LabeledBox.js","sourceRoot":"","sources":["../../../src/classes/LabeledBox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG5B,MAAM,OAAO,UAAW,SAAQ,GAAe;IAY7C,YAAY,GAA+B,EAAE,KAAa;QACxD,KAAK,CAAC,GAAG,CAAC,CAAA;QACV,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;IACrB,CAAC;IAbM,MAAM,CAAC,uBAAuB,CAAC,GAAQ,EAAE,MAAc;QAC5D,GAAG,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QAEjC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;YAC7B,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,+BAA+B,GAAG,CAAC,KAAK,kBAAkB,CAAC,CAAA;SACrF;IACH,CAAC;IASD,IAAW,KAAK,KAAa,OAAO,IAAI,CAAC,MAAM,CAAA,CAAC,CAAC;CAElD"}

View File

@ -1,9 +0,0 @@
export declare class LabeledFaceDescriptors {
private _label;
private _descriptors;
constructor(label: string, descriptors: Float32Array[]);
get label(): string;
get descriptors(): Float32Array[];
toJSON(): any;
static fromJSON(json: any): LabeledFaceDescriptors;
}

View File

@ -1,27 +0,0 @@
export class LabeledFaceDescriptors {
constructor(label, descriptors) {
if (!(typeof label === 'string')) {
throw new Error('LabeledFaceDescriptors - constructor expected label to be a string');
}
if (!Array.isArray(descriptors) || descriptors.some(desc => !(desc instanceof Float32Array))) {
throw new Error('LabeledFaceDescriptors - constructor expected descriptors to be an array of Float32Array');
}
this._label = label;
this._descriptors = descriptors;
}
get label() { return this._label; }
get descriptors() { return this._descriptors; }
toJSON() {
return {
label: this.label,
descriptors: this.descriptors.map((d) => Array.from(d))
};
}
static fromJSON(json) {
const descriptors = json.descriptors.map((d) => {
return new Float32Array(d);
});
return new LabeledFaceDescriptors(json.label, descriptors);
}
}
//# sourceMappingURL=LabeledFaceDescriptors.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"LabeledFaceDescriptors.js","sourceRoot":"","sources":["../../../src/classes/LabeledFaceDescriptors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,sBAAsB;IAIjC,YAAY,KAAa,EAAE,WAA2B;QACpD,IAAI,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,EAAE;YAChC,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAA;SACtF;QAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,YAAY,YAAY,CAAC,CAAC,EAAE;YAC5F,MAAM,IAAI,KAAK,CAAC,0FAA0F,CAAC,CAAA;SAC5G;QAED,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,YAAY,GAAG,WAAW,CAAA;IACjC,CAAC;IAED,IAAW,KAAK,KAAa,OAAO,IAAI,CAAC,MAAM,CAAA,CAAC,CAAC;IACjD,IAAW,WAAW,KAAqB,OAAO,IAAI,CAAC,YAAY,CAAA,CAAC,CAAC;IAE9D,MAAM;QACX,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SACxD,CAAC;IACJ,CAAC;IAEM,MAAM,CAAC,QAAQ,CAAC,IAAS;QAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE;YAClD,OAAO,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,sBAAsB,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAC7D,CAAC;CAEF"}

View File

@ -1,20 +0,0 @@
import { Box } from './Box';
import { Dimensions, IDimensions } from './Dimensions';
import { IRect } from './Rect';
export declare class ObjectDetection {
private _score;
private _classScore;
private _className;
private _box;
private _imageDims;
constructor(score: number, classScore: number, className: string, relativeBox: IRect, imageDims: IDimensions);
get score(): number;
get classScore(): number;
get className(): string;
get box(): Box;
get imageDims(): Dimensions;
get imageWidth(): number;
get imageHeight(): number;
get relativeBox(): Box;
forSize(width: number, height: number): ObjectDetection;
}

View File

@ -1,23 +0,0 @@
import { Box } from './Box';
import { Dimensions } from './Dimensions';
export class ObjectDetection {
constructor(score, classScore, className, relativeBox, imageDims) {
this._imageDims = new Dimensions(imageDims.width, imageDims.height);
this._score = score;
this._classScore = classScore;
this._className = className;
this._box = new Box(relativeBox).rescale(this._imageDims);
}
get score() { return this._score; }
get classScore() { return this._classScore; }
get className() { return this._className; }
get box() { return this._box; }
get imageDims() { return this._imageDims; }
get imageWidth() { return this.imageDims.width; }
get imageHeight() { return this.imageDims.height; }
get relativeBox() { return new Box(this._box).rescale(this.imageDims.reverse()); }
forSize(width, height) {
return new ObjectDetection(this.score, this.classScore, this.className, this.relativeBox, { width, height });
}
}
//# sourceMappingURL=ObjectDetection.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"ObjectDetection.js","sourceRoot":"","sources":["../../../src/classes/ObjectDetection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAe,MAAM,cAAc,CAAC;AAGvD,MAAM,OAAO,eAAe;IAO1B,YACE,KAAa,EACb,UAAkB,EAClB,SAAiB,EACjB,WAAkB,EAClB,SAAsB;QAEtB,IAAI,CAAC,UAAU,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,CAAA;QACnE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,WAAW,GAAG,UAAU,CAAA;QAC7B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAA;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAC3D,CAAC;IAED,IAAW,KAAK,KAAa,OAAO,IAAI,CAAC,MAAM,CAAA,CAAC,CAAC;IACjD,IAAW,UAAU,KAAa,OAAO,IAAI,CAAC,WAAW,CAAA,CAAC,CAAC;IAC3D,IAAW,SAAS,KAAa,OAAO,IAAI,CAAC,UAAU,CAAA,CAAC,CAAC;IACzD,IAAW,GAAG,KAAU,OAAO,IAAI,CAAC,IAAI,CAAA,CAAC,CAAC;IAC1C,IAAW,SAAS,KAAiB,OAAO,IAAI,CAAC,UAAU,CAAA,CAAC,CAAC;IAC7D,IAAW,UAAU,KAAa,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAA,CAAC,CAAC;IAC/D,IAAW,WAAW,KAAa,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAA,CAAC,CAAC;IACjE,IAAW,WAAW,KAAU,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAA,CAAC,CAAC;IAEtF,OAAO,CAAC,KAAa,EAAE,MAAc;QAC1C,OAAO,IAAI,eAAe,CACxB,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,WAAW,EAChB,EAAE,KAAK,EAAE,MAAM,EAAC,CACjB,CAAA;IACH,CAAC;CACF"}

View File

@ -1,18 +0,0 @@
export interface IPoint {
x: number;
y: number;
}
export declare class Point implements IPoint {
private _x;
private _y;
constructor(x: number, y: number);
get x(): number;
get y(): number;
add(pt: IPoint): Point;
sub(pt: IPoint): Point;
mul(pt: IPoint): Point;
div(pt: IPoint): Point;
abs(): Point;
magnitude(): number;
floor(): Point;
}

View File

@ -1,30 +0,0 @@
export class Point {
constructor(x, y) {
this._x = x;
this._y = y;
}
get x() { return this._x; }
get y() { return this._y; }
add(pt) {
return new Point(this.x + pt.x, this.y + pt.y);
}
sub(pt) {
return new Point(this.x - pt.x, this.y - pt.y);
}
mul(pt) {
return new Point(this.x * pt.x, this.y * pt.y);
}
div(pt) {
return new Point(this.x / pt.x, this.y / pt.y);
}
abs() {
return new Point(Math.abs(this.x), Math.abs(this.y));
}
magnitude() {
return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
}
floor() {
return new Point(Math.floor(this.x), Math.floor(this.y));
}
}
//# sourceMappingURL=Point.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"Point.js","sourceRoot":"","sources":["../../../src/classes/Point.ts"],"names":[],"mappings":"AAKA,MAAM,OAAO,KAAK;IAIhB,YAAY,CAAS,EAAE,CAAS;QAC9B,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;QACX,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;IACb,CAAC;IAED,IAAI,CAAC,KAAa,OAAO,IAAI,CAAC,EAAE,CAAA,CAAC,CAAC;IAClC,IAAI,CAAC,KAAa,OAAO,IAAI,CAAC,EAAE,CAAA,CAAC,CAAC;IAE3B,GAAG,CAAC,EAAU;QACnB,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;IAChD,CAAC;IAEM,GAAG,CAAC,EAAU;QACnB,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;IAChD,CAAC;IAEM,GAAG,CAAC,EAAU;QACnB,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;IAChD,CAAC;IAEM,GAAG,CAAC,EAAU;QACnB,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;IAChD,CAAC;IAEM,GAAG;QACR,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IACtD,CAAC;IAEM,SAAS;QACd,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAC7D,CAAC;IAEM,KAAK;QACV,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1D,CAAC;CACF"}

View File

@ -1,11 +0,0 @@
import { IBoundingBox } from './BoundingBox';
import { LabeledBox } from './LabeledBox';
import { IRect } from './Rect';
export declare class PredictedBox extends LabeledBox {
static assertIsValidPredictedBox(box: any, callee: string): void;
private _score;
private _classScore;
constructor(box: IBoundingBox | IRect | any, label: number, score: number, classScore: number);
get score(): number;
get classScore(): number;
}

View File

@ -1,19 +0,0 @@
import { isValidProbablitiy } from '../utils';
import { LabeledBox } from './LabeledBox';
export class PredictedBox extends LabeledBox {
constructor(box, label, score, classScore) {
super(box, label);
this._score = score;
this._classScore = classScore;
}
static assertIsValidPredictedBox(box, callee) {
LabeledBox.assertIsValidLabeledBox(box, callee);
if (!isValidProbablitiy(box.score)
|| !isValidProbablitiy(box.classScore)) {
throw new Error(`${callee} - expected properties score (${box.score}) and (${box.classScore}) to be a number between [0, 1]`);
}
}
get score() { return this._score; }
get classScore() { return this._classScore; }
}
//# sourceMappingURL=PredictedBox.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"PredictedBox.js","sourceRoot":"","sources":["../../../src/classes/PredictedBox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,MAAM,OAAO,YAAa,SAAQ,UAAU;IAgB1C,YAAY,GAA+B,EAAE,KAAa,EAAE,KAAa,EAAE,UAAkB;QAC3F,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACjB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,WAAW,GAAG,UAAU,CAAA;IAC/B,CAAC;IAlBM,MAAM,CAAC,yBAAyB,CAAC,GAAQ,EAAE,MAAc;QAC9D,UAAU,CAAC,uBAAuB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QAE/C,IACE,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC;eAC3B,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,EACtC;YACA,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,iCAAiC,GAAG,CAAC,KAAK,UAAU,GAAG,CAAC,UAAU,iCAAiC,CAAC,CAAA;SAC9H;IACH,CAAC;IAWD,IAAW,KAAK,KAAa,OAAO,IAAI,CAAC,MAAM,CAAA,CAAC,CAAC;IACjD,IAAW,UAAU,KAAa,OAAO,IAAI,CAAC,WAAW,CAAA,CAAC,CAAC;CAE5D"}

View File

@ -1,10 +0,0 @@
import { Box } from './Box';
export interface IRect {
x: number;
y: number;
width: number;
height: number;
}
export declare class Rect extends Box<Rect> implements IRect {
constructor(x: number, y: number, width: number, height: number, allowNegativeDimensions?: boolean);
}

View File

@ -1,7 +0,0 @@
import { Box } from './Box';
export class Rect extends Box {
constructor(x, y, width, height, allowNegativeDimensions = false) {
super({ x, y, width, height }, allowNegativeDimensions);
}
}
//# sourceMappingURL=Rect.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"Rect.js","sourceRoot":"","sources":["../../../src/classes/Rect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAS5B,MAAM,OAAO,IAAK,SAAQ,GAAS;IACjC,YAAY,CAAS,EAAE,CAAS,EAAE,KAAa,EAAE,MAAc,EAAE,0BAAmC,KAAK;QACvG,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,uBAAuB,CAAC,CAAA;IACzD,CAAC;CACF"}

View File

@ -1,14 +0,0 @@
export * from './BoundingBox';
export * from './Box';
export * from './Dimensions';
export * from './FaceDetection';
export * from './FaceLandmarks';
export * from './FaceLandmarks5';
export * from './FaceLandmarks68';
export * from './FaceMatch';
export * from './LabeledBox';
export * from './LabeledFaceDescriptors';
export * from './ObjectDetection';
export * from './Point';
export * from './PredictedBox';
export * from './Rect';

View File

@ -1,15 +0,0 @@
export * from './BoundingBox';
export * from './Box';
export * from './Dimensions';
export * from './FaceDetection';
export * from './FaceLandmarks';
export * from './FaceLandmarks5';
export * from './FaceLandmarks68';
export * from './FaceMatch';
export * from './LabeledBox';
export * from './LabeledFaceDescriptors';
export * from './ObjectDetection';
export * from './Point';
export * from './PredictedBox';
export * from './Rect';
//# sourceMappingURL=index.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/classes/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA;AAC7B,cAAc,OAAO,CAAA;AACrB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAA;AACjC,cAAc,SAAS,CAAA;AACvB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,QAAQ,CAAA"}

View File

@ -1,3 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
import { ConvParams } from './types';
export declare function convLayer(x: tf.Tensor4D, params: ConvParams, padding?: 'valid' | 'same', withRelu?: boolean): tf.Tensor4D;

View File

@ -1,8 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
export function convLayer(x, params, padding = 'same', withRelu = false) {
return tf.tidy(() => {
const out = tf.add(tf.conv2d(x, params.filters, [1, 1], padding), params.bias);
return withRelu ? tf.relu(out) : out;
});
}
//# sourceMappingURL=convLayer.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"convLayer.js","sourceRoot":"","sources":["../../../src/common/convLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,oCAAoC,CAAC;AAIzD,MAAM,UAAU,SAAS,CACvB,CAAc,EACd,MAAkB,EAClB,UAA4B,MAAM,EAClC,WAAoB,KAAK;IAEzB,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;QAClB,MAAM,GAAG,GAAG,EAAE,CAAC,GAAG,CAChB,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,EAC7C,MAAM,CAAC,IAAI,CACG,CAAA;QAEhB,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;IACtC,CAAC,CAAC,CAAA;AACJ,CAAC"}

View File

@ -1,3 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
import { SeparableConvParams } from './types';
export declare function depthwiseSeparableConv(x: tf.Tensor4D, params: SeparableConvParams, stride: [number, number]): tf.Tensor4D;

View File

@ -1,9 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
export function depthwiseSeparableConv(x, params, stride) {
return tf.tidy(() => {
let out = tf.separableConv2d(x, params.depthwise_filter, params.pointwise_filter, stride, 'same');
out = tf.add(out, params.bias);
return out;
});
}
//# sourceMappingURL=depthwiseSeparableConv.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"depthwiseSeparableConv.js","sourceRoot":"","sources":["../../../src/common/depthwiseSeparableConv.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,oCAAoC,CAAC;AAIzD,MAAM,UAAU,sBAAsB,CACpC,CAAc,EACd,MAA2B,EAC3B,MAAwB;IAExB,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;QAClB,IAAI,GAAG,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QACjG,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;QAC9B,OAAO,GAAG,CAAA;IACZ,CAAC,CAAC,CAAA;AACJ,CAAC"}

View File

@ -1,2 +0,0 @@
import { ParamMapping } from './types';
export declare function disposeUnusedWeightTensors(weightMap: any, paramMappings: ParamMapping[]): void;

View File

@ -1,8 +0,0 @@
export function disposeUnusedWeightTensors(weightMap, paramMappings) {
Object.keys(weightMap).forEach(path => {
if (!paramMappings.some(pm => pm.originalPath === path)) {
weightMap[path].dispose();
}
});
}
//# sourceMappingURL=disposeUnusedWeightTensors.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"disposeUnusedWeightTensors.js","sourceRoot":"","sources":["../../../src/common/disposeUnusedWeightTensors.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,0BAA0B,CAAC,SAAc,EAAE,aAA6B;IACtF,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACpC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,KAAK,IAAI,CAAC,EAAE;YACvD,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAA;SAC1B;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}

View File

@ -1,2 +0,0 @@
import { ConvParams, ExtractWeightsFunction, ParamMapping } from './types';
export declare function extractConvParamsFactory(extractWeights: ExtractWeightsFunction, paramMappings: ParamMapping[]): (channelsIn: number, channelsOut: number, filterSize: number, mappedPrefix: string) => ConvParams;

View File

@ -1,10 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
export function extractConvParamsFactory(extractWeights, paramMappings) {
return function (channelsIn, channelsOut, filterSize, mappedPrefix) {
const filters = tf.tensor4d(extractWeights(channelsIn * channelsOut * filterSize * filterSize), [filterSize, filterSize, channelsIn, channelsOut]);
const bias = tf.tensor1d(extractWeights(channelsOut));
paramMappings.push({ paramPath: `${mappedPrefix}/filters` }, { paramPath: `${mappedPrefix}/bias` });
return { filters, bias };
};
}
//# sourceMappingURL=extractConvParamsFactory.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"extractConvParamsFactory.js","sourceRoot":"","sources":["../../../src/common/extractConvParamsFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,oCAAoC,CAAC;AAIzD,MAAM,UAAU,wBAAwB,CACtC,cAAsC,EACtC,aAA6B;IAG7B,OAAO,UACL,UAAkB,EAClB,WAAmB,EACnB,UAAkB,EAClB,YAAoB;QAGpB,MAAM,OAAO,GAAG,EAAE,CAAC,QAAQ,CACzB,cAAc,CAAC,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC,EAClE,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,CAAC,CAClD,CAAA;QACD,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAA;QAErD,aAAa,CAAC,IAAI,CAChB,EAAE,SAAS,EAAE,GAAG,YAAY,UAAU,EAAE,EACxC,EAAE,SAAS,EAAE,GAAG,YAAY,OAAO,EAAE,CACtC,CAAA;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;IAC1B,CAAC,CAAA;AAEH,CAAC"}

View File

@ -1,2 +0,0 @@
import { ExtractWeightsFunction, FCParams, ParamMapping } from './types';
export declare function extractFCParamsFactory(extractWeights: ExtractWeightsFunction, paramMappings: ParamMapping[]): (channelsIn: number, channelsOut: number, mappedPrefix: string) => FCParams;

View File

@ -1,13 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
export function extractFCParamsFactory(extractWeights, paramMappings) {
return function (channelsIn, channelsOut, mappedPrefix) {
const fc_weights = tf.tensor2d(extractWeights(channelsIn * channelsOut), [channelsIn, channelsOut]);
const fc_bias = tf.tensor1d(extractWeights(channelsOut));
paramMappings.push({ paramPath: `${mappedPrefix}/weights` }, { paramPath: `${mappedPrefix}/bias` });
return {
weights: fc_weights,
bias: fc_bias
};
};
}
//# sourceMappingURL=extractFCParamsFactory.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"extractFCParamsFactory.js","sourceRoot":"","sources":["../../../src/common/extractFCParamsFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,oCAAoC,CAAC;AAKzD,MAAM,UAAU,sBAAsB,CACpC,cAAsC,EACtC,aAA6B;IAG7B,OAAO,UACL,UAAkB,EAClB,WAAmB,EACnB,YAAoB;QAGpB,MAAM,UAAU,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,UAAU,GAAG,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAA;QACnG,MAAM,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAA;QAExD,aAAa,CAAC,IAAI,CAChB,EAAE,SAAS,EAAE,GAAG,YAAY,UAAU,EAAE,EACxC,EAAE,SAAS,EAAE,GAAG,YAAY,OAAO,EAAE,CACtC,CAAA;QAED,OAAO;YACL,OAAO,EAAE,UAAU;YACnB,IAAI,EAAE,OAAO;SACd,CAAA;IACH,CAAC,CAAA;AAEH,CAAC"}

View File

@ -1,3 +0,0 @@
import { ExtractWeightsFunction, ParamMapping, SeparableConvParams } from './types';
export declare function extractSeparableConvParamsFactory(extractWeights: ExtractWeightsFunction, paramMappings: ParamMapping[]): (channelsIn: number, channelsOut: number, mappedPrefix: string) => SeparableConvParams;
export declare function loadSeparableConvParamsFactory(extractWeightEntry: <T>(originalPath: string, paramRank: number) => T): (prefix: string) => SeparableConvParams;

View File

@ -1,20 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
import { SeparableConvParams } from './types';
export function extractSeparableConvParamsFactory(extractWeights, paramMappings) {
return function (channelsIn, channelsOut, mappedPrefix) {
const depthwise_filter = tf.tensor4d(extractWeights(3 * 3 * channelsIn), [3, 3, channelsIn, 1]);
const pointwise_filter = tf.tensor4d(extractWeights(channelsIn * channelsOut), [1, 1, channelsIn, channelsOut]);
const bias = tf.tensor1d(extractWeights(channelsOut));
paramMappings.push({ paramPath: `${mappedPrefix}/depthwise_filter` }, { paramPath: `${mappedPrefix}/pointwise_filter` }, { paramPath: `${mappedPrefix}/bias` });
return new SeparableConvParams(depthwise_filter, pointwise_filter, bias);
};
}
export function loadSeparableConvParamsFactory(extractWeightEntry) {
return function (prefix) {
const depthwise_filter = extractWeightEntry(`${prefix}/depthwise_filter`, 4);
const pointwise_filter = extractWeightEntry(`${prefix}/pointwise_filter`, 4);
const bias = extractWeightEntry(`${prefix}/bias`, 1);
return new SeparableConvParams(depthwise_filter, pointwise_filter, bias);
};
}
//# sourceMappingURL=extractSeparableConvParamsFactory.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"extractSeparableConvParamsFactory.js","sourceRoot":"","sources":["../../../src/common/extractSeparableConvParamsFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,oCAAoC,CAAC;AAEzD,OAAO,EAAwC,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEpF,MAAM,UAAU,iCAAiC,CAC/C,cAAsC,EACtC,aAA6B;IAG7B,OAAO,UAAS,UAAkB,EAAE,WAAmB,EAAE,YAAoB;QAC3E,MAAM,gBAAgB,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAA;QAC/F,MAAM,gBAAgB,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,UAAU,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAA;QAC/G,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAA;QAErD,aAAa,CAAC,IAAI,CAChB,EAAE,SAAS,EAAE,GAAG,YAAY,mBAAmB,EAAE,EACjD,EAAE,SAAS,EAAE,GAAG,YAAY,mBAAmB,EAAE,EACjD,EAAE,SAAS,EAAE,GAAG,YAAY,OAAO,EAAE,CACtC,CAAA;QAED,OAAO,IAAI,mBAAmB,CAC5B,gBAAgB,EAChB,gBAAgB,EAChB,IAAI,CACL,CAAA;IACH,CAAC,CAAA;AAEH,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,kBAAqE;IAGrE,OAAO,UAAU,MAAc;QAC7B,MAAM,gBAAgB,GAAG,kBAAkB,CAAc,GAAG,MAAM,mBAAmB,EAAE,CAAC,CAAC,CAAA;QACzF,MAAM,gBAAgB,GAAG,kBAAkB,CAAc,GAAG,MAAM,mBAAmB,EAAE,CAAC,CAAC,CAAA;QACzF,MAAM,IAAI,GAAG,kBAAkB,CAAc,GAAG,MAAM,OAAO,EAAE,CAAC,CAAC,CAAA;QAEjE,OAAO,IAAI,mBAAmB,CAC5B,gBAAgB,EAChB,gBAAgB,EAChB,IAAI,CACL,CAAA;IACH,CAAC,CAAA;AAEH,CAAC"}

View File

@ -1,2 +0,0 @@
import { ParamMapping } from './types';
export declare function extractWeightEntryFactory(weightMap: any, paramMappings: ParamMapping[]): <T>(originalPath: string, paramRank: number, mappedPath?: string | undefined) => T;

View File

@ -1,12 +0,0 @@
import { isTensor } from '../utils';
export function extractWeightEntryFactory(weightMap, paramMappings) {
return function (originalPath, paramRank, mappedPath) {
const tensor = weightMap[originalPath];
if (!isTensor(tensor, paramRank)) {
throw new Error(`expected weightMap[${originalPath}] to be a Tensor${paramRank}D, instead have ${tensor}`);
}
paramMappings.push({ originalPath, paramPath: mappedPath || originalPath });
return tensor;
};
}
//# sourceMappingURL=extractWeightEntryFactory.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"extractWeightEntryFactory.js","sourceRoot":"","sources":["../../../src/common/extractWeightEntryFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAGpC,MAAM,UAAU,yBAAyB,CAAC,SAAc,EAAE,aAA6B;IAErF,OAAO,UAAa,YAAoB,EAAE,SAAiB,EAAE,UAAmB;QAC9E,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,CAAA;QAEtC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE;YAChC,MAAM,IAAI,KAAK,CAAC,sBAAsB,YAAY,mBAAmB,SAAS,mBAAmB,MAAM,EAAE,CAAC,CAAA;SAC3G;QAED,aAAa,CAAC,IAAI,CAChB,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,IAAI,YAAY,EAAE,CACxD,CAAA;QAED,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;AAEH,CAAC"}

View File

@ -1,4 +0,0 @@
export declare function extractWeightsFactory(weights: Float32Array): {
extractWeights: (numWeights: number) => Float32Array;
getRemainingWeights: () => Float32Array;
};

View File

@ -1,16 +0,0 @@
export function extractWeightsFactory(weights) {
let remainingWeights = weights;
function extractWeights(numWeights) {
const ret = remainingWeights.slice(0, numWeights);
remainingWeights = remainingWeights.slice(numWeights);
return ret;
}
function getRemainingWeights() {
return remainingWeights;
}
return {
extractWeights,
getRemainingWeights
};
}
//# sourceMappingURL=extractWeightsFactory.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"extractWeightsFactory.js","sourceRoot":"","sources":["../../../src/common/extractWeightsFactory.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,qBAAqB,CAAC,OAAqB;IACzD,IAAI,gBAAgB,GAAG,OAAO,CAAA;IAE9B,SAAS,cAAc,CAAC,UAAkB;QACxC,MAAM,GAAG,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;QACjD,gBAAgB,GAAG,gBAAgB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;QACrD,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,SAAS,mBAAmB;QAC1B,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAED,OAAO;QACL,cAAc;QACd,mBAAmB;KACpB,CAAA;AACH,CAAC"}

View File

@ -1,3 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
import { FCParams } from './types';
export declare function fullyConnectedLayer(x: tf.Tensor2D, params: FCParams): tf.Tensor2D;

View File

@ -1,5 +0,0 @@
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
export function fullyConnectedLayer(x, params) {
return tf.tidy(() => tf.add(tf.matMul(x, params.weights), params.bias));
}
//# sourceMappingURL=fullyConnectedLayer.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"fullyConnectedLayer.js","sourceRoot":"","sources":["../../../src/common/fullyConnectedLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,oCAAoC,CAAC;AAIzD,MAAM,UAAU,mBAAmB,CACjC,CAAc,EACd,MAAgB;IAEhB,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAClB,EAAE,CAAC,GAAG,CACJ,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,EAC5B,MAAM,CAAC,IAAI,CACZ,CACF,CAAA;AACH,CAAC"}

View File

@ -1,4 +0,0 @@
export declare function getModelUris(uri: string | undefined, defaultModelName: string): {
modelBaseUri: string;
manifestUri: string;
};

View File

@ -1,28 +0,0 @@
export function getModelUris(uri, defaultModelName) {
const defaultManifestFilename = `${defaultModelName}-weights_manifest.json`;
if (!uri) {
return {
modelBaseUri: '',
manifestUri: defaultManifestFilename
};
}
if (uri === '/') {
return {
modelBaseUri: '/',
manifestUri: `/${defaultManifestFilename}`
};
}
const protocol = uri.startsWith('http://') ? 'http://' : uri.startsWith('https://') ? 'https://' : '';
uri = uri.replace(protocol, '');
const parts = uri.split('/').filter(s => s);
const manifestFile = uri.endsWith('.json')
? parts[parts.length - 1]
: defaultManifestFilename;
let modelBaseUri = protocol + (uri.endsWith('.json') ? parts.slice(0, parts.length - 1) : parts).join('/');
modelBaseUri = uri.startsWith('/') ? `/${modelBaseUri}` : modelBaseUri;
return {
modelBaseUri,
manifestUri: modelBaseUri === '/' ? `/${manifestFile}` : `${modelBaseUri}/${manifestFile}`
};
}
//# sourceMappingURL=getModelUris.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"getModelUris.js","sourceRoot":"","sources":["../../../src/common/getModelUris.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,GAAuB,EAAE,gBAAwB;IAC5E,MAAM,uBAAuB,GAAG,GAAG,gBAAgB,wBAAwB,CAAA;IAE3E,IAAI,CAAC,GAAG,EAAE;QACR,OAAO;YACL,YAAY,EAAE,EAAE;YAChB,WAAW,EAAE,uBAAuB;SACrC,CAAA;KACF;IAED,IAAI,GAAG,KAAK,GAAG,EAAE;QACf,OAAO;YACL,YAAY,EAAE,GAAG;YACjB,WAAW,EAAE,IAAI,uBAAuB,EAAE;SAC3C,CAAA;KACF;IACD,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IACtG,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEhC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAE3C,MAAM,YAAY,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;QACxC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACzB,CAAC,CAAC,uBAAuB,CAAA;IAE3B,IAAI,YAAY,GAAG,QAAQ,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC1G,YAAY,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC,CAAC,YAAY,CAAA;IAEtE,OAAO;QACL,YAAY;QACZ,WAAW,EAAE,YAAY,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC,CAAC,GAAG,YAAY,IAAI,YAAY,EAAE;KAC3F,CAAA;AACH,CAAC"}

Some files were not shown because too many files have changed in this diff Show More