Unverified Commit fb378dd3 by justadudewhohacks Committed by GitHub

Merge pull request #10 from justadudewhohacks/face-landmarks

68 point face landmark detection
parents c378f933 b9588f96
import { createCanvas, getContext2dOrThrow, getElement, getMediaDimensions } from './utils'; import { createCanvasFromMedia, getElement } from './utils';
var NetInput = /** @class */ (function () { var NetInput = /** @class */ (function () {
function NetInput(mediaArg, dims) { function NetInput(mediaArg, dims) {
var _this = this; var _this = this;
...@@ -27,10 +27,8 @@ var NetInput = /** @class */ (function () { ...@@ -27,10 +27,8 @@ var NetInput = /** @class */ (function () {
return; return;
} }
// if input is batch type, make sure every canvas has the same dimensions // if input is batch type, make sure every canvas has the same dimensions
var _a = this.dims || dims || getMediaDimensions(media), width = _a.width, height = _a.height; var canvasDims = this.dims || dims;
var canvas = createCanvas({ width: width, height: height }); this._canvases.push(createCanvasFromMedia(media, canvasDims));
getContext2dOrThrow(canvas).drawImage(media, 0, 0, width, height);
this._canvases.push(canvas);
}; };
Object.defineProperty(NetInput.prototype, "canvases", { Object.defineProperty(NetInput.prototype, "canvases", {
get: function () { get: function () {
......
{"version":3,"file":"NetInput.js","sourceRoot":"","sources":["../src/NetInput.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE5F;IAGE,kBACE,QAAmB,EACnB,IAAiB;QAFnB,iBA2BC;QAvBC,IAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC3C,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;QAEd,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE;YACzB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAA;SAC1D;QAED,IAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QAG5C,MAAM,CAAC,OAAO,CAAC,UAAC,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC,CAAC,KAAK,YAAY,gBAAgB,IAAI,KAAK,YAAY,gBAAgB,IAAI,KAAK,YAAY,iBAAiB,CAAC,EAAE;gBACnH,IAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,qBAAmB,CAAC,MAAG,CAAC,CAAC,CAAC,EAAE,CAAA;gBACtE,IAAI,OAAO,aAAa,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;oBACxC,MAAM,IAAI,KAAK,CAAC,eAAa,OAAO,qEAAkE,CAAC,CAAA;iBACxG;gBACD,MAAM,IAAI,KAAK,CAAC,eAAa,OAAO,kHAA+G,CAAC,CAAA;aACrJ;QACH,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;QACnB,MAAM,CAAC,OAAO,CAAC,UAAA,CAAC,IAAI,OAAA,KAAI,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,EAAxB,CAAwB,CAAC,CAAA;IAC/C,CAAC;IAEO,6BAAU,GAAlB,UAAmB,KAAoB,EAAE,IAAiB;QACxD,IAAI,KAAK,YAAY,iBAAiB,EAAE;YACtC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAC1B,OAAM;SACP;QAED,yEAAyE;QACnE,IAAA,mDAAkE,EAAhE,gBAAK,EAAE,kBAAM,CAAmD;QAExE,IAAM,MAAM,GAAG,YAAY,CAAC,EAAE,KAAK,OAAA,EAAE,MAAM,QAAA,EAAE,CAAC,CAAA;QAC9C,mBAAmB,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;QACjE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC7B,CAAC;IAED,sBAAW,8BAAQ;aAAnB;YACE,OAAO,IAAI,CAAC,SAAS,CAAA;QACvB,CAAC;;;OAAA;IAED,sBAAW,2BAAK;aAAhB;YACE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAA;QACxC,CAAC;;;OAAA;IAED,sBAAW,4BAAM;aAAjB;YACE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAA;QACzC,CAAC;;;OAAA;IAED,sBAAW,0BAAI;aAAf;YACQ,IAAA,SAAwB,EAAtB,gBAAK,EAAE,kBAAM,CAAS;YAC9B,OAAO,CAAC,KAAK,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,OAAA,EAAE,MAAM,QAAA,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;QAC7D,CAAC;;;OAAA;IACH,eAAC;AAAD,CAAC,AA9DD,IA8DC"} {"version":3,"file":"NetInput.js","sourceRoot":"","sources":["../src/NetInput.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAuB,UAAU,EAAsB,MAAM,SAAS,CAAC;AAErG;IAGE,kBACE,QAAmB,EACnB,IAAiB;QAFnB,iBA2BC;QAvBC,IAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC3C,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;QAEd,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE;YACzB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAA;SAC1D;QAED,IAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QAG5C,MAAM,CAAC,OAAO,CAAC,UAAC,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC,CAAC,KAAK,YAAY,gBAAgB,IAAI,KAAK,YAAY,gBAAgB,IAAI,KAAK,YAAY,iBAAiB,CAAC,EAAE;gBACnH,IAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,qBAAmB,CAAC,MAAG,CAAC,CAAC,CAAC,EAAE,CAAA;gBACtE,IAAI,OAAO,aAAa,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;oBACxC,MAAM,IAAI,KAAK,CAAC,eAAa,OAAO,qEAAkE,CAAC,CAAA;iBACxG;gBACD,MAAM,IAAI,KAAK,CAAC,eAAa,OAAO,kHAA+G,CAAC,CAAA;aACrJ;QACH,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;QACnB,MAAM,CAAC,OAAO,CAAC,UAAA,CAAC,IAAI,OAAA,KAAI,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,EAAxB,CAAwB,CAAC,CAAA;IAC/C,CAAC;IAEO,6BAAU,GAAlB,UAAmB,KAAoB,EAAE,IAAiB;QACxD,IAAI,KAAK,YAAY,iBAAiB,EAAE;YACtC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAC1B,OAAM;SACP;QAED,yEAAyE;QACzE,IAAM,UAAU,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAA;QACpC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAA;IAC/D,CAAC;IAED,sBAAW,8BAAQ;aAAnB;YACE,OAAO,IAAI,CAAC,SAAS,CAAA;QACvB,CAAC;;;OAAA;IAED,sBAAW,2BAAK;aAAhB;YACE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAA;QACxC,CAAC;;;OAAA;IAED,sBAAW,4BAAM;aAAjB;YACE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAA;QACzC,CAAC;;;OAAA;IAED,sBAAW,0BAAI;aAAf;YACQ,IAAA,SAAwB,EAAtB,gBAAK,EAAE,kBAAM,CAAS;YAC9B,OAAO,CAAC,KAAK,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,OAAA,EAAE,MAAM,QAAA,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;QAC7D,CAAC;;;OAAA;IACH,eAAC;AAAD,CAAC,AA3DD,IA2DC"}
\ No newline at end of file \ No newline at end of file
export interface IPoint {
x: number;
y: number;
}
export declare class Point implements IPoint {
x: number;
y: number;
constructor(x: number, y: number);
add(pt: IPoint): Point;
sub(pt: IPoint): Point;
mul(pt: IPoint): Point;
div(pt: IPoint): Point;
}
var Point = /** @class */ (function () {
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.add = function (pt) {
return new Point(this.x + pt.x, this.y + pt.y);
};
Point.prototype.sub = function (pt) {
return new Point(this.x - pt.x, this.y - pt.y);
};
Point.prototype.mul = function (pt) {
return new Point(this.x * pt.x, this.y * pt.y);
};
Point.prototype.div = function (pt) {
return new Point(this.x / pt.x, this.y / pt.y);
};
return Point;
}());
export { Point };
//# sourceMappingURL=Point.js.map
\ No newline at end of file
{"version":3,"file":"Point.js","sourceRoot":"","sources":["../src/Point.ts"],"names":[],"mappings":"AAKA;IAIE,eAAY,CAAS,EAAE,CAAS;QAC9B,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;QACV,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;IACZ,CAAC;IAEM,mBAAG,GAAV,UAAW,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,mBAAG,GAAV,UAAW,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,mBAAG,GAAV,UAAW,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,mBAAG,GAAV,UAAW,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;IACH,YAAC;AAAD,CAAC,AAxBD,IAwBC"}
\ No newline at end of file
export declare class Rect {
x: number;
y: number;
width: number;
height: number;
constructor(x: number, y: number, width: number, height: number);
floor(): Rect;
}
var Rect = /** @class */ (function () {
function Rect(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
Rect.prototype.floor = function () {
return new Rect(Math.floor(this.x), Math.floor(this.y), Math.floor(this.width), Math.floor(this.height));
};
return Rect;
}());
export { Rect };
//# sourceMappingURL=Rect.js.map
\ No newline at end of file
{"version":3,"file":"Rect.js","sourceRoot":"","sources":["../src/Rect.ts"],"names":[],"mappings":"AAAA;IAME,cAAY,CAAS,EAAE,CAAS,EAAE,KAAa,EAAE,MAAc;QAC7D,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;QACV,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;QACV,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;IAEM,oBAAK,GAAZ;QACE,OAAO,IAAI,IAAI,CACb,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAClB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAClB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EACtB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CACxB,CAAA;IACH,CAAC;IACH,WAAC;AAAD,CAAC,AArBD,IAqBC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { ConvParams } from './types';
export declare function convLayer(x: tf.Tensor4D, params: ConvParams, padding?: 'valid' | 'same', withRelu?: boolean): tf.Tensor4D;
import * as tf from '@tensorflow/tfjs-core';
export function convLayer(x, params, padding, withRelu) {
if (padding === void 0) { padding = 'same'; }
if (withRelu === void 0) { withRelu = false; }
return tf.tidy(function () {
var out = tf.add(tf.conv2d(x, params.filters, [1, 1], padding), params.bias);
return withRelu ? tf.relu(out) : out;
});
}
//# sourceMappingURL=convLayer.js.map
\ No newline at end of file
{"version":3,"file":"convLayer.js","sourceRoot":"","sources":["../../src/commons/convLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAI5C,MAAM,oBACJ,CAAc,EACd,MAAkB,EAClB,OAAkC,EAClC,QAAyB;IADzB,wBAAA,EAAA,gBAAkC;IAClC,yBAAA,EAAA,gBAAyB;IAEzB,OAAO,EAAE,CAAC,IAAI,CAAC;QACb,IAAM,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"}
\ No newline at end of file
import { ConvParams, ExtractWeightsFunction } from './types';
export declare function extractConvParamsFactory(extractWeights: ExtractWeightsFunction): (channelsIn: number, channelsOut: number, filterSize: number) => ConvParams;
import * as tf from '@tensorflow/tfjs-core';
export function extractConvParamsFactory(extractWeights) {
return function (channelsIn, channelsOut, filterSize) {
var filters = tf.tensor4d(extractWeights(channelsIn * channelsOut * filterSize * filterSize), [filterSize, filterSize, channelsIn, channelsOut]);
var bias = tf.tensor1d(extractWeights(channelsOut));
return {
filters: filters,
bias: bias
};
};
}
//# sourceMappingURL=extractConvParamsFactory.js.map
\ No newline at end of file
{"version":3,"file":"extractConvParamsFactory.js","sourceRoot":"","sources":["../../src/commons/extractConvParamsFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAI5C,MAAM,mCAAmC,cAAsC;IAC7E,OAAO,UACL,UAAkB,EAClB,WAAmB,EACnB,UAAkB;QAElB,IAAM,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,IAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAA;QAErD,OAAO;YACL,OAAO,SAAA;YACP,IAAI,MAAA;SACL,CAAA;IACH,CAAC,CAAA;AACH,CAAC"}
\ No newline at end of file
export declare function extractWeightsFactory(weights: Float32Array): {
extractWeights: (numWeights: number) => Float32Array;
getRemainingWeights: () => Float32Array;
};
export function extractWeightsFactory(weights) {
var remainingWeights = weights;
function extractWeights(numWeights) {
var ret = remainingWeights.slice(0, numWeights);
remainingWeights = remainingWeights.slice(numWeights);
return ret;
}
function getRemainingWeights() {
return remainingWeights;
}
return {
extractWeights: extractWeights,
getRemainingWeights: getRemainingWeights
};
}
//# sourceMappingURL=extractWeightsFactory.js.map
\ No newline at end of file
{"version":3,"file":"extractWeightsFactory.js","sourceRoot":"","sources":["../../src/commons/extractWeightsFactory.ts"],"names":[],"mappings":"AAAA,MAAM,gCAAgC,OAAqB;IACzD,IAAI,gBAAgB,GAAG,OAAO,CAAA;IAE9B,wBAAwB,UAAkB;QACxC,IAAM,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;QACE,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAED,OAAO;QACL,cAAc,gBAAA;QACd,mBAAmB,qBAAA;KACpB,CAAA;AACH,CAAC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
export declare type ConvParams = {
filters: tf.Tensor4D;
bias: tf.Tensor1D;
};
export declare type ExtractWeightsFunction = (numWeights: number) => Float32Array;
//# sourceMappingURL=types.js.map
\ No newline at end of file
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/commons/types.ts"],"names":[],"mappings":""}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { FaceDetectionResult } from './faceDetectionNet/FaceDetectionResult'; import { FaceDetection } from './faceDetectionNet/FaceDetection';
import { NetInput } from './NetInput'; import { NetInput } from './NetInput';
import { TNetInput } from './types'; import { TNetInput } from './types';
/** /**
...@@ -13,4 +13,4 @@ import { TNetInput } from './types'; ...@@ -13,4 +13,4 @@ import { TNetInput } from './types';
* @param detections The face detection results for that image. * @param detections The face detection results for that image.
* @returns Tensors of the corresponding image region for each detected face. * @returns Tensors of the corresponding image region for each detected face.
*/ */
export declare function extractFaceTensors(image: tf.Tensor | NetInput | TNetInput, detections: FaceDetectionResult[]): tf.Tensor4D[]; export declare function extractFaceTensors(image: tf.Tensor | NetInput | TNetInput, detections: FaceDetection[]): tf.Tensor4D[];
...@@ -17,7 +17,7 @@ export function extractFaceTensors(image, detections) { ...@@ -17,7 +17,7 @@ export function extractFaceTensors(image, detections) {
// TODO handle batches // TODO handle batches
var _a = imgTensor.shape, batchSize = _a[0], imgHeight = _a[1], imgWidth = _a[2], numChannels = _a[3]; var _a = imgTensor.shape, batchSize = _a[0], imgHeight = _a[1], imgWidth = _a[2], numChannels = _a[3];
var faceTensors = detections.map(function (det) { var faceTensors = detections.map(function (det) {
var _a = det.forSize(imgWidth, imgHeight).box, x = _a.x, y = _a.y, width = _a.width, height = _a.height; var _a = det.forSize(imgWidth, imgHeight).getBox().floor(), x = _a.x, y = _a.y, width = _a.width, height = _a.height;
return tf.slice(imgTensor, [0, y, x, 0], [1, height, width, numChannels]); return tf.slice(imgTensor, [0, y, x, 0], [1, height, width, numChannels]);
}); });
return faceTensors; return faceTensors;
......
{"version":3,"file":"extractFaceTensors.js","sourceRoot":"","sources":["../src/extractFaceTensors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAI5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD;;;;;;;;;;GAUG;AACH,MAAM,6BACJ,KAAuC,EACvC,UAAiC;IAEjC,OAAO,EAAE,CAAC,IAAI,CAAC;QACb,IAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,CAAA;QAEvC,sBAAsB;QAChB,IAAA,oBAA+D,EAA9D,iBAAS,EAAE,iBAAS,EAAE,gBAAQ,EAAE,mBAAW,CAAmB;QAErE,IAAM,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC,UAAA,GAAG;YAC9B,IAAA,yCAA8D,EAA5D,QAAC,EAAE,QAAC,EAAE,gBAAK,EAAE,kBAAM,CAAyC;YACpE,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAA;QAC3E,CAAC,CAAC,CAAA;QAEF,OAAO,WAAW,CAAA;IACpB,CAAC,CAAC,CAAA;AACJ,CAAC"} {"version":3,"file":"extractFaceTensors.js","sourceRoot":"","sources":["../src/extractFaceTensors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAG5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIlD;;;;;;;;;;GAUG;AACH,MAAM,6BACJ,KAAuC,EACvC,UAA2B;IAE3B,OAAO,EAAE,CAAC,IAAI,CAAC;QACb,IAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,CAAA;QAEvC,sBAAsB;QAChB,IAAA,oBAA+D,EAA9D,iBAAS,EAAE,iBAAS,EAAE,gBAAQ,EAAE,mBAAW,CAAmB;QAErE,IAAM,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC,UAAA,GAAG;YAC9B,IAAA,sDAA2E,EAAzE,QAAC,EAAE,QAAC,EAAE,gBAAK,EAAE,kBAAM,CAAsD;YACjF,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAA;QAC3E,CAAC,CAAC,CAAA;QAEF,OAAO,WAAW,CAAA;IACpB,CAAC,CAAC,CAAA;AACJ,CAAC"}
\ No newline at end of file \ No newline at end of file
import { FaceDetectionResult } from './faceDetectionNet/FaceDetectionResult'; import { FaceDetection } from './faceDetectionNet/FaceDetection';
/** /**
* Extracts the image regions containing the detected faces. * Extracts the image regions containing the detected faces.
* *
...@@ -6,4 +6,4 @@ import { FaceDetectionResult } from './faceDetectionNet/FaceDetectionResult'; ...@@ -6,4 +6,4 @@ import { FaceDetectionResult } from './faceDetectionNet/FaceDetectionResult';
* @param detections The face detection results for that image. * @param detections The face detection results for that image.
* @returns The Canvases of the corresponding image region for each detected face. * @returns The Canvases of the corresponding image region for each detected face.
*/ */
export declare function extractFaces(image: HTMLCanvasElement, detections: FaceDetectionResult[]): HTMLCanvasElement[]; export declare function extractFaces(image: HTMLCanvasElement, detections: FaceDetection[]): HTMLCanvasElement[];
...@@ -9,7 +9,7 @@ import { createCanvas, getContext2dOrThrow } from './utils'; ...@@ -9,7 +9,7 @@ import { createCanvas, getContext2dOrThrow } from './utils';
export function extractFaces(image, detections) { export function extractFaces(image, detections) {
var ctx = getContext2dOrThrow(image); var ctx = getContext2dOrThrow(image);
return detections.map(function (det) { return detections.map(function (det) {
var _a = det.forSize(image.width, image.height).box, x = _a.x, y = _a.y, width = _a.width, height = _a.height; var _a = det.forSize(image.width, image.height).getBox().floor(), x = _a.x, y = _a.y, width = _a.width, height = _a.height;
var faceImg = createCanvas({ width: width, height: height }); var faceImg = createCanvas({ width: width, height: height });
getContext2dOrThrow(faceImg) getContext2dOrThrow(faceImg)
.putImageData(ctx.getImageData(x, y, width, height), 0, 0); .putImageData(ctx.getImageData(x, y, width, height), 0, 0);
......
{"version":3,"file":"extractFaces.js","sourceRoot":"","sources":["../src/extractFaces.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,uBACJ,KAAwB,EACxB,UAAiC;IAEjC,IAAM,GAAG,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;IAEtC,OAAO,UAAU,CAAC,GAAG,CAAC,UAAA,GAAG;QACjB,IAAA,+CAAoE,EAAlE,QAAC,EAAE,QAAC,EAAE,gBAAK,EAAE,kBAAM,CAA+C;QAE1E,IAAM,OAAO,GAAG,YAAY,CAAC,EAAE,KAAK,OAAA,EAAE,MAAM,QAAA,EAAE,CAAC,CAAA;QAC/C,mBAAmB,CAAC,OAAO,CAAC;aACzB,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QAC5D,OAAO,OAAO,CAAA;IAChB,CAAC,CAAC,CAAA;AACJ,CAAC"} {"version":3,"file":"extractFaces.js","sourceRoot":"","sources":["../src/extractFaces.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,uBACJ,KAAwB,EACxB,UAA2B;IAE3B,IAAM,GAAG,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;IAEtC,OAAO,UAAU,CAAC,GAAG,CAAC,UAAA,GAAG;QACjB,IAAA,4DAAiF,EAA/E,QAAC,EAAE,QAAC,EAAE,gBAAK,EAAE,kBAAM,CAA4D;QACvF,IAAM,OAAO,GAAG,YAAY,CAAC,EAAE,KAAK,OAAA,EAAE,MAAM,QAAA,EAAE,CAAC,CAAA;QAC/C,mBAAmB,CAAC,OAAO,CAAC;aACzB,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QAC5D,OAAO,OAAO,CAAA;IAChB,CAAC,CAAC,CAAA;AACJ,CAAC"}
\ No newline at end of file \ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
import { Rect } from '../Rect';
import { Dimensions } from '../types';
export declare class FaceDetection {
private _score;
private _box;
private _imageWidth;
private _imageHeight;
constructor(score: number, relativeBox: Rect, imageDims: Dimensions);
getScore(): number;
getBox(): Rect;
getImageWidth(): number;
getImageHeight(): number;
getRelativeBox(): Rect;
forSize(width: number, height: number): FaceDetection;
}
import { Rect } from '../Rect';
var FaceDetection = /** @class */ (function () {
function FaceDetection(score, relativeBox, imageDims) {
var width = imageDims.width, height = imageDims.height;
this._imageWidth = width;
this._imageHeight = height;
this._score = score;
this._box = new Rect(relativeBox.x * width, relativeBox.y * height, relativeBox.width * width, relativeBox.height * height);
}
FaceDetection.prototype.getScore = function () {
return this._score;
};
FaceDetection.prototype.getBox = function () {
return this._box;
};
FaceDetection.prototype.getImageWidth = function () {
return this._imageWidth;
};
FaceDetection.prototype.getImageHeight = function () {
return this._imageHeight;
};
FaceDetection.prototype.getRelativeBox = function () {
return new Rect(this._box.x / this._imageWidth, this._box.y / this._imageHeight, this._box.width / this._imageWidth, this._box.height / this._imageHeight);
};
FaceDetection.prototype.forSize = function (width, height) {
return new FaceDetection(this._score, this.getRelativeBox(), { width: width, height: height });
};
return FaceDetection;
}());
export { FaceDetection };
//# sourceMappingURL=FaceDetection.js.map
\ No newline at end of file
{"version":3,"file":"FaceDetection.js","sourceRoot":"","sources":["../../src/faceDetectionNet/FaceDetection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG/B;IAME,uBACE,KAAa,EACb,WAAiB,EACjB,SAAqB;QAEb,IAAA,uBAAK,EAAE,yBAAM,CAAc;QACnC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAA;QACxB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAA;QAC1B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAClB,WAAW,CAAC,CAAC,GAAG,KAAK,EACrB,WAAW,CAAC,CAAC,GAAG,MAAM,EACtB,WAAW,CAAC,KAAK,GAAG,KAAK,EACzB,WAAW,CAAC,MAAM,GAAG,MAAM,CAC5B,CAAA;IACH,CAAC;IAEM,gCAAQ,GAAf;QACE,OAAO,IAAI,CAAC,MAAM,CAAA;IACpB,CAAC;IAEM,8BAAM,GAAb;QACE,OAAO,IAAI,CAAC,IAAI,CAAA;IAClB,CAAC;IAEM,qCAAa,GAApB;QACE,OAAO,IAAI,CAAC,WAAW,CAAA;IACzB,CAAC;IAEM,sCAAc,GAArB;QACE,OAAO,IAAI,CAAC,YAAY,CAAA;IAC1B,CAAC;IAEM,sCAAc,GAArB;QACE,OAAO,IAAI,IAAI,CACb,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,EAC9B,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,EAC/B,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,WAAW,EAClC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,YAAY,CACrC,CAAA;IACH,CAAC;IAEM,+BAAO,GAAd,UAAe,KAAa,EAAE,MAAc;QAC1C,OAAO,IAAI,aAAa,CACtB,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,cAAc,EAAE,EACrB,EAAE,KAAK,OAAA,EAAE,MAAM,QAAA,EAAC,CACjB,CAAA;IACH,CAAC;IACH,oBAAC;AAAD,CAAC,AAvDD,IAuDC"}
\ No newline at end of file
import { FaceDetectionNet } from './types';
export declare class FaceDetectionResult {
private _score;
private _topRelative;
private _leftRelative;
private _bottomRelative;
private _rightRelative;
constructor(score: number, topRelative: number, leftRelative: number, bottomRelative: number, rightRelative: number);
forSize(width: number, height: number): FaceDetectionNet.Detection;
}
var FaceDetectionResult = /** @class */ (function () {
function FaceDetectionResult(score, topRelative, leftRelative, bottomRelative, rightRelative) {
this._score = score;
this._topRelative = Math.max(0, topRelative),
this._leftRelative = Math.max(0, leftRelative),
this._bottomRelative = Math.min(1.0, bottomRelative),
this._rightRelative = Math.min(1.0, rightRelative);
}
FaceDetectionResult.prototype.forSize = function (width, height) {
var x = Math.floor(this._leftRelative * width);
var y = Math.floor(this._topRelative * height);
return {
score: this._score,
box: {
x: x,
y: y,
width: Math.floor(this._rightRelative * width) - x,
height: Math.floor(this._bottomRelative * height) - y
}
};
};
return FaceDetectionResult;
}());
export { FaceDetectionResult };
//# sourceMappingURL=FaceDetectionResult.js.map
\ No newline at end of file
{"version":3,"file":"FaceDetectionResult.js","sourceRoot":"","sources":["../../src/faceDetectionNet/FaceDetectionResult.ts"],"names":[],"mappings":"AAEA;IAOE,6BACE,KAAa,EACb,WAAmB,EACnB,YAAoB,EACpB,cAAsB,EACtB,aAAqB;QAErB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC;YAC5C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC;YAC9C,IAAI,CAAC,eAAe,GAAI,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,cAAc,CAAC;YACrD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,aAAa,CAAC,CAAA;IACpD,CAAC;IAEM,qCAAO,GAAd,UAAe,KAAa,EAAE,MAAc;QAC1C,IAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,CAAA;QAChD,IAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,CAAA;QAChD,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,MAAM;YAClB,GAAG,EAAE;gBACH,CAAC,GAAA;gBACD,CAAC,GAAA;gBACD,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,GAAG,CAAC;gBAClD,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC;aACtD;SACF,CAAA;IACH,CAAC;IACH,0BAAC;AAAD,CAAC,AAlCD,IAkCC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
function convWithBias(x, params) { import { convLayer } from '../commons/convLayer';
return tf.tidy(function () {
return tf.add(tf.conv2d(x, params.filters, [1, 1], 'same'), params.bias);
});
}
export function boxPredictionLayer(x, params) { export function boxPredictionLayer(x, params) {
return tf.tidy(function () { return tf.tidy(function () {
var batchSize = x.shape[0]; var batchSize = x.shape[0];
var boxPredictionEncoding = tf.reshape(convWithBias(x, params.box_encoding_predictor_params), [batchSize, -1, 1, 4]); var boxPredictionEncoding = tf.reshape(convLayer(x, params.box_encoding_predictor_params), [batchSize, -1, 1, 4]);
var classPrediction = tf.reshape(convWithBias(x, params.class_predictor_params), [batchSize, -1, 3]); var classPrediction = tf.reshape(convLayer(x, params.class_predictor_params), [batchSize, -1, 3]);
return { return {
boxPredictionEncoding: boxPredictionEncoding, boxPredictionEncoding: boxPredictionEncoding,
classPrediction: classPrediction classPrediction: classPrediction
......
{"version":3,"file":"boxPredictionLayer.js","sourceRoot":"","sources":["../../src/faceDetectionNet/boxPredictionLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAI5C,sBACE,CAAc,EACd,MAA2C;IAE3C,OAAO,EAAE,CAAC,IAAI,CAAC;QACb,OAAA,EAAE,CAAC,GAAG,CACJ,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,EAC5C,MAAM,CAAC,IAAI,CACZ;IAHD,CAGC,CACF,CAAA;AACH,CAAC;AAED,MAAM,6BACJ,CAAc,EACd,MAA4C;IAE5C,OAAO,EAAE,CAAC,IAAI,CAAC;QAEb,IAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAE5B,IAAM,qBAAqB,GAAG,EAAE,CAAC,OAAO,CACtC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,6BAA6B,CAAC,EACrD,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CACtB,CAAA;QACD,IAAM,eAAe,GAAG,EAAE,CAAC,OAAO,CAChC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,sBAAsB,CAAC,EAC9C,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CACnB,CAAA;QAED,OAAO;YACL,qBAAqB,uBAAA;YACrB,eAAe,iBAAA;SAChB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"} {"version":3,"file":"boxPredictionLayer.js","sourceRoot":"","sources":["../../src/faceDetectionNet/boxPredictionLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjD,MAAM,6BACJ,CAAc,EACd,MAA4C;IAE5C,OAAO,EAAE,CAAC,IAAI,CAAC;QAEb,IAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAE5B,IAAM,qBAAqB,GAAG,EAAE,CAAC,OAAO,CACtC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,6BAA6B,CAAC,EAClD,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CACtB,CAAA;QACD,IAAM,eAAe,GAAG,EAAE,CAAC,OAAO,CAChC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,sBAAsB,CAAC,EAC3C,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CACnB,CAAA;QAED,OAAO;YACL,qBAAqB,uBAAA;YACrB,eAAe,iBAAA;SAChB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
\ No newline at end of file \ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { extractWeightsFactory } from '../commons/extractWeightsFactory';
function extractorsFactory(extractWeights) { function extractorsFactory(extractWeights) {
function extractDepthwiseConvParams(numChannels) { function extractDepthwiseConvParams(numChannels) {
var filters = tf.tensor4d(extractWeights(3 * 3 * numChannels), [3, 3, numChannels, 1]); var filters = tf.tensor4d(extractWeights(3 * 3 * numChannels), [3, 3, numChannels, 1]);
...@@ -14,7 +15,7 @@ function extractorsFactory(extractWeights) { ...@@ -14,7 +15,7 @@ function extractorsFactory(extractWeights) {
batch_norm_variance: batch_norm_variance batch_norm_variance: batch_norm_variance
}; };
} }
function extractConvWithBiasParams(channelsIn, channelsOut, filterSize) { function extractConvParams(channelsIn, channelsOut, filterSize) {
var filters = tf.tensor4d(extractWeights(channelsIn * channelsOut * filterSize * filterSize), [filterSize, filterSize, channelsIn, channelsOut]); var filters = tf.tensor4d(extractWeights(channelsIn * channelsOut * filterSize * filterSize), [filterSize, filterSize, channelsIn, channelsOut]);
var bias = tf.tensor1d(extractWeights(channelsOut)); var bias = tf.tensor1d(extractWeights(channelsOut));
return { return {
...@@ -23,7 +24,7 @@ function extractorsFactory(extractWeights) { ...@@ -23,7 +24,7 @@ function extractorsFactory(extractWeights) {
}; };
} }
function extractPointwiseConvParams(channelsIn, channelsOut, filterSize) { function extractPointwiseConvParams(channelsIn, channelsOut, filterSize) {
var _a = extractConvWithBiasParams(channelsIn, channelsOut, filterSize), filters = _a.filters, bias = _a.bias; var _a = extractConvParams(channelsIn, channelsOut, filterSize), filters = _a.filters, bias = _a.bias;
return { return {
filters: filters, filters: filters,
batch_norm_offset: bias batch_norm_offset: bias
...@@ -72,18 +73,18 @@ function extractorsFactory(extractWeights) { ...@@ -72,18 +73,18 @@ function extractorsFactory(extractWeights) {
var conv_5_params = extractPointwiseConvParams(128, 256, 3); var conv_5_params = extractPointwiseConvParams(128, 256, 3);
var conv_6_params = extractPointwiseConvParams(256, 64, 1); var conv_6_params = extractPointwiseConvParams(256, 64, 1);
var conv_7_params = extractPointwiseConvParams(64, 128, 3); var conv_7_params = extractPointwiseConvParams(64, 128, 3);
var box_encoding_0_predictor_params = extractConvWithBiasParams(512, 12, 1); var box_encoding_0_predictor_params = extractConvParams(512, 12, 1);
var class_predictor_0_params = extractConvWithBiasParams(512, 9, 1); var class_predictor_0_params = extractConvParams(512, 9, 1);
var box_encoding_1_predictor_params = extractConvWithBiasParams(1024, 24, 1); var box_encoding_1_predictor_params = extractConvParams(1024, 24, 1);
var class_predictor_1_params = extractConvWithBiasParams(1024, 18, 1); var class_predictor_1_params = extractConvParams(1024, 18, 1);
var box_encoding_2_predictor_params = extractConvWithBiasParams(512, 24, 1); var box_encoding_2_predictor_params = extractConvParams(512, 24, 1);
var class_predictor_2_params = extractConvWithBiasParams(512, 18, 1); var class_predictor_2_params = extractConvParams(512, 18, 1);
var box_encoding_3_predictor_params = extractConvWithBiasParams(256, 24, 1); var box_encoding_3_predictor_params = extractConvParams(256, 24, 1);
var class_predictor_3_params = extractConvWithBiasParams(256, 18, 1); var class_predictor_3_params = extractConvParams(256, 18, 1);
var box_encoding_4_predictor_params = extractConvWithBiasParams(256, 24, 1); var box_encoding_4_predictor_params = extractConvParams(256, 24, 1);
var class_predictor_4_params = extractConvWithBiasParams(256, 18, 1); var class_predictor_4_params = extractConvParams(256, 18, 1);
var box_encoding_5_predictor_params = extractConvWithBiasParams(128, 24, 1); var box_encoding_5_predictor_params = extractConvParams(128, 24, 1);
var class_predictor_5_params = extractConvWithBiasParams(128, 18, 1); var class_predictor_5_params = extractConvParams(128, 18, 1);
var box_predictor_0_params = { var box_predictor_0_params = {
box_encoding_predictor_params: box_encoding_0_predictor_params, box_encoding_predictor_params: box_encoding_0_predictor_params,
class_predictor_params: class_predictor_0_params class_predictor_params: class_predictor_0_params
...@@ -131,20 +132,16 @@ function extractorsFactory(extractWeights) { ...@@ -131,20 +132,16 @@ function extractorsFactory(extractWeights) {
}; };
} }
export function extractParams(weights) { export function extractParams(weights) {
var extractWeights = function (numWeights) { var _a = extractWeightsFactory(weights), extractWeights = _a.extractWeights, getRemainingWeights = _a.getRemainingWeights;
var ret = weights.slice(0, numWeights); var _b = extractorsFactory(extractWeights), extractMobilenetV1Params = _b.extractMobilenetV1Params, extractPredictionLayerParams = _b.extractPredictionLayerParams;
weights = weights.slice(numWeights);
return ret;
};
var _a = extractorsFactory(extractWeights), extractMobilenetV1Params = _a.extractMobilenetV1Params, extractPredictionLayerParams = _a.extractPredictionLayerParams;
var mobilenetv1_params = extractMobilenetV1Params(); var mobilenetv1_params = extractMobilenetV1Params();
var prediction_layer_params = extractPredictionLayerParams(); var prediction_layer_params = extractPredictionLayerParams();
var extra_dim = tf.tensor3d(extractWeights(5118 * 4), [1, 5118, 4]); var extra_dim = tf.tensor3d(extractWeights(5118 * 4), [1, 5118, 4]);
var output_layer_params = { var output_layer_params = {
extra_dim: extra_dim extra_dim: extra_dim
}; };
if (weights.length !== 0) { if (getRemainingWeights().length !== 0) {
throw new Error("weights remaing after extract: " + weights.length); throw new Error("weights remaing after extract: " + getRemainingWeights().length);
} }
return { return {
mobilenetv1_params: mobilenetv1_params, mobilenetv1_params: mobilenetv1_params,
......
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { NetInput } from '../NetInput'; import { NetInput } from '../NetInput';
import { FaceDetectionResult } from './FaceDetectionResult'; import { FaceDetection } from './FaceDetection';
export declare function faceDetectionNet(weights: Float32Array): { export declare function faceDetectionNet(weights: Float32Array): {
forward: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | tf.Tensor<tf.Rank> | NetInput) => { forward: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | NetInput | tf.Tensor<tf.Rank>) => {
boxes: tf.Tensor<tf.Rank.R2>[]; boxes: tf.Tensor<tf.Rank.R2>[];
scores: tf.Tensor<tf.Rank.R1>[]; scores: tf.Tensor<tf.Rank.R1>[];
}; };
locateFaces: (input: tf.Tensor<tf.Rank> | NetInput, minConfidence?: number, maxResults?: number) => Promise<FaceDetectionResult[]>; locateFaces: (input: NetInput | tf.Tensor<tf.Rank>, minConfidence?: number, maxResults?: number) => Promise<FaceDetection[]>;
}; };
...@@ -3,12 +3,13 @@ import * as tf from '@tensorflow/tfjs-core'; ...@@ -3,12 +3,13 @@ import * as tf from '@tensorflow/tfjs-core';
import { getImageTensor } from '../getImageTensor'; import { getImageTensor } from '../getImageTensor';
import { padToSquare } from '../padToSquare'; import { padToSquare } from '../padToSquare';
import { extractParams } from './extractParams'; import { extractParams } from './extractParams';
import { FaceDetectionResult } from './FaceDetectionResult'; import { FaceDetection } from './FaceDetection';
import { mobileNetV1 } from './mobileNetV1'; import { mobileNetV1 } from './mobileNetV1';
import { nonMaxSuppression } from './nonMaxSuppression'; import { nonMaxSuppression } from './nonMaxSuppression';
import { outputLayer } from './outputLayer'; import { outputLayer } from './outputLayer';
import { predictionLayer } from './predictionLayer'; import { predictionLayer } from './predictionLayer';
import { resizeLayer } from './resizeLayer'; import { resizeLayer } from './resizeLayer';
import { Rect } from '../Rect';
export function faceDetectionNet(weights) { export function faceDetectionNet(weights) {
var params = extractParams(weights); var params = extractParams(weights);
function forwardTensor(imgTensor) { function forwardTensor(imgTensor) {
...@@ -26,7 +27,7 @@ export function faceDetectionNet(weights) { ...@@ -26,7 +27,7 @@ export function faceDetectionNet(weights) {
if (minConfidence === void 0) { minConfidence = 0.8; } if (minConfidence === void 0) { minConfidence = 0.8; }
if (maxResults === void 0) { maxResults = 100; } if (maxResults === void 0) { maxResults = 100; }
return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__awaiter(this, void 0, void 0, function () {
var paddedHeightRelative, paddedWidthRelative, _a, _boxes, _scores, boxes, scores, i, scoresData, _b, _c, iouThreshold, indices, results; var paddedHeightRelative, paddedWidthRelative, imageDimensions, _a, _boxes, _scores, boxes, scores, i, scoresData, _b, _c, iouThreshold, indices, results;
return tslib_1.__generator(this, function (_d) { return tslib_1.__generator(this, function (_d) {
switch (_d.label) { switch (_d.label) {
case 0: case 0:
...@@ -34,6 +35,7 @@ export function faceDetectionNet(weights) { ...@@ -34,6 +35,7 @@ export function faceDetectionNet(weights) {
_a = tf.tidy(function () { _a = tf.tidy(function () {
var imgTensor = getImageTensor(input); var imgTensor = getImageTensor(input);
var _a = imgTensor.shape.slice(1), height = _a[0], width = _a[1]; var _a = imgTensor.shape.slice(1), height = _a[0], width = _a[1];
imageDimensions = { width: width, height: height };
imgTensor = padToSquare(imgTensor); imgTensor = padToSquare(imgTensor);
paddedHeightRelative = imgTensor.shape[1] / height; paddedHeightRelative = imgTensor.shape[1] / height;
paddedWidthRelative = imgTensor.shape[2] / width; paddedWidthRelative = imgTensor.shape[2] / width;
...@@ -52,7 +54,17 @@ export function faceDetectionNet(weights) { ...@@ -52,7 +54,17 @@ export function faceDetectionNet(weights) {
iouThreshold = 0.5; iouThreshold = 0.5;
indices = nonMaxSuppression(boxes, scoresData, maxResults, iouThreshold, minConfidence); indices = nonMaxSuppression(boxes, scoresData, maxResults, iouThreshold, minConfidence);
results = indices results = indices
.map(function (idx) { return new FaceDetectionResult(scoresData[idx], boxes.get(idx, 0) * paddedHeightRelative, boxes.get(idx, 1) * paddedWidthRelative, boxes.get(idx, 2) * paddedHeightRelative, boxes.get(idx, 3) * paddedWidthRelative); }); .map(function (idx) {
var _a = [
Math.max(0, boxes.get(idx, 0)),
Math.min(1.0, boxes.get(idx, 2))
].map(function (val) { return val * paddedHeightRelative; }), top = _a[0], bottom = _a[1];
var _b = [
Math.max(0, boxes.get(idx, 1)),
Math.min(1.0, boxes.get(idx, 3))
].map(function (val) { return val * paddedWidthRelative; }), left = _b[0], right = _b[1];
return new FaceDetection(scoresData[idx], new Rect(left, top, right - left, bottom - top), imageDimensions);
});
boxes.dispose(); boxes.dispose();
scores.dispose(); scores.dispose();
return [2 /*return*/, results]; return [2 /*return*/, results];
......
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/faceDetectionNet/index.ts"],"names":[],"mappings":"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"} {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/faceDetectionNet/index.ts"],"names":[],"mappings":"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"}
\ No newline at end of file \ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { ConvParams } from '../commons/types';
export declare namespace FaceDetectionNet { export declare namespace FaceDetectionNet {
type PointwiseConvParams = { type PointwiseConvParams = {
filters: tf.Tensor4D; filters: tf.Tensor4D;
...@@ -21,13 +22,9 @@ export declare namespace FaceDetectionNet { ...@@ -21,13 +22,9 @@ export declare namespace FaceDetectionNet {
conv_pair_params: ConvPairParams[]; conv_pair_params: ConvPairParams[];
}; };
} }
type ConvWithBiasParams = {
filters: tf.Tensor4D;
bias: tf.Tensor1D;
};
type BoxPredictionParams = { type BoxPredictionParams = {
box_encoding_predictor_params: ConvWithBiasParams; box_encoding_predictor_params: ConvParams;
class_predictor_params: ConvWithBiasParams; class_predictor_params: ConvParams;
}; };
type PredictionLayerParams = { type PredictionLayerParams = {
conv_0_params: PointwiseConvParams; conv_0_params: PointwiseConvParams;
...@@ -53,13 +50,4 @@ export declare namespace FaceDetectionNet { ...@@ -53,13 +50,4 @@ export declare namespace FaceDetectionNet {
prediction_layer_params: PredictionLayerParams; prediction_layer_params: PredictionLayerParams;
output_layer_params: OutputLayerParams; output_layer_params: OutputLayerParams;
}; };
type Detection = {
score: number;
box: {
x: number;
y: number;
width: number;
height: number;
};
};
} }
import { Point } from '../Point';
import { Dimensions } from '../types';
export declare class FaceLandmarks {
private _faceLandmarks;
private _imageWidth;
private _imageHeight;
private _shift;
constructor(relativeFaceLandmarkPositions: Point[], imageDims: Dimensions, shift?: Point);
getPositions(): Point[];
getRelativePositions(): Point[];
getJawOutline(): Point[];
getLeftEyeBrow(): Point[];
getRightEyeBrow(): Point[];
getNose(): Point[];
getLeftEye(): Point[];
getRightEye(): Point[];
getMouth(): Point[];
forSize(width: number, height: number): FaceLandmarks;
shift(x: number, y: number): FaceLandmarks;
}
import { Point } from '../Point';
var FaceLandmarks = /** @class */ (function () {
function FaceLandmarks(relativeFaceLandmarkPositions, imageDims, shift) {
if (shift === void 0) { shift = new Point(0, 0); }
var width = imageDims.width, height = imageDims.height;
this._imageWidth = width;
this._imageHeight = height;
this._shift = shift;
this._faceLandmarks = relativeFaceLandmarkPositions.map(function (pt) { return pt.mul(new Point(width, height)).add(shift); });
}
FaceLandmarks.prototype.getPositions = function () {
return this._faceLandmarks;
};
FaceLandmarks.prototype.getRelativePositions = function () {
var _this = this;
return this._faceLandmarks.map(function (pt) { return pt.sub(_this._shift).div(new Point(_this._imageWidth, _this._imageHeight)); });
};
FaceLandmarks.prototype.getJawOutline = function () {
return this._faceLandmarks.slice(0, 17);
};
FaceLandmarks.prototype.getLeftEyeBrow = function () {
return this._faceLandmarks.slice(17, 22);
};
FaceLandmarks.prototype.getRightEyeBrow = function () {
return this._faceLandmarks.slice(22, 27);
};
FaceLandmarks.prototype.getNose = function () {
return this._faceLandmarks.slice(27, 36);
};
FaceLandmarks.prototype.getLeftEye = function () {
return this._faceLandmarks.slice(36, 42);
};
FaceLandmarks.prototype.getRightEye = function () {
return this._faceLandmarks.slice(42, 48);
};
FaceLandmarks.prototype.getMouth = function () {
return this._faceLandmarks.slice(48, 68);
};
FaceLandmarks.prototype.forSize = function (width, height) {
return new FaceLandmarks(this.getRelativePositions(), { width: width, height: height });
};
FaceLandmarks.prototype.shift = function (x, y) {
return new FaceLandmarks(this.getRelativePositions(), { width: this._imageWidth, height: this._imageHeight }, new Point(x, y));
};
return FaceLandmarks;
}());
export { FaceLandmarks };
//# sourceMappingURL=FaceLandmarks.js.map
\ No newline at end of file
{"version":3,"file":"FaceLandmarks.js","sourceRoot":"","sources":["../../src/faceLandmarkNet/FaceLandmarks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAU,MAAM,UAAU,CAAC;AAGzC;IAME,uBACE,6BAAsC,EACtC,SAAqB,EACrB,KAA8B;QAA9B,sBAAA,EAAA,YAAmB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAEtB,IAAA,uBAAK,EAAE,yBAAM,CAAc;QACnC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAA;QACxB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAA;QAC1B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,cAAc,GAAG,6BAA6B,CAAC,GAAG,CACrD,UAAA,EAAE,IAAI,OAAA,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAA3C,CAA2C,CAClD,CAAA;IACH,CAAC;IAEM,oCAAY,GAAnB;QACE,OAAO,IAAI,CAAC,cAAc,CAAA;IAC5B,CAAC;IAEM,4CAAoB,GAA3B;QAAA,iBAIC;QAHC,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAC5B,UAAA,EAAE,IAAI,OAAA,EAAE,CAAC,GAAG,CAAC,KAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,KAAI,CAAC,WAAW,EAAE,KAAI,CAAC,YAAY,CAAC,CAAC,EAAvE,CAAuE,CAC9E,CAAA;IACH,CAAC;IAEM,qCAAa,GAApB;QACE,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACzC,CAAC;IAEM,sCAAc,GAArB;QACE,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IAC1C,CAAC;IAEM,uCAAe,GAAtB;QACE,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IAC1C,CAAC;IAEM,+BAAO,GAAd;QACE,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IAC1C,CAAC;IAEM,kCAAU,GAAjB;QACE,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IAC1C,CAAC;IAEM,mCAAW,GAAlB;QACE,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IAC1C,CAAC;IAEM,gCAAQ,GAAf;QACE,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IAC1C,CAAC;IAEM,+BAAO,GAAd,UAAe,KAAa,EAAE,MAAc;QAC1C,OAAO,IAAI,aAAa,CACtB,IAAI,CAAC,oBAAoB,EAAE,EAC3B,EAAE,KAAK,OAAA,EAAE,MAAM,QAAA,EAAE,CAClB,CAAA;IACH,CAAC;IAEM,6BAAK,GAAZ,UAAa,CAAS,EAAE,CAAS;QAC/B,OAAO,IAAI,aAAa,CACtB,IAAI,CAAC,oBAAoB,EAAE,EAC3B,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,EACtD,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAChB,CAAA;IACH,CAAC;IACH,oBAAC;AAAD,CAAC,AAxED,IAwEC"}
\ No newline at end of file
import { FaceLandmarkNet } from './types';
export declare function extractParams(weights: Float32Array): FaceLandmarkNet.NetParams;
import * as tf from '@tensorflow/tfjs-core';
import { extractConvParamsFactory } from '../commons/extractConvParamsFactory';
import { extractWeightsFactory } from '../commons/extractWeightsFactory';
export function extractParams(weights) {
var _a = extractWeightsFactory(weights), extractWeights = _a.extractWeights, getRemainingWeights = _a.getRemainingWeights;
var extractConvParams = extractConvParamsFactory(extractWeights);
function extractFcParams(channelsIn, channelsOut) {
var fc_weights = tf.tensor2d(extractWeights(channelsIn * channelsOut), [channelsIn, channelsOut]);
var fc_bias = tf.tensor1d(extractWeights(channelsOut));
return {
weights: fc_weights,
bias: fc_bias
};
}
var conv0_params = extractConvParams(3, 32, 3);
var conv1_params = extractConvParams(32, 64, 3);
var conv2_params = extractConvParams(64, 64, 3);
var conv3_params = extractConvParams(64, 64, 3);
var conv4_params = extractConvParams(64, 64, 3);
var conv5_params = extractConvParams(64, 128, 3);
var conv6_params = extractConvParams(128, 128, 3);
var conv7_params = extractConvParams(128, 256, 3);
var fc0_params = extractFcParams(6400, 1024);
var fc1_params = extractFcParams(1024, 136);
if (getRemainingWeights().length !== 0) {
throw new Error("weights remaing after extract: " + getRemainingWeights().length);
}
return {
conv0_params: conv0_params,
conv1_params: conv1_params,
conv2_params: conv2_params,
conv3_params: conv3_params,
conv4_params: conv4_params,
conv5_params: conv5_params,
conv6_params: conv6_params,
conv7_params: conv7_params,
fc0_params: fc0_params,
fc1_params: fc1_params
};
}
//# sourceMappingURL=extractParams.js.map
\ No newline at end of file
{"version":3,"file":"extractParams.js","sourceRoot":"","sources":["../../src/faceLandmarkNet/extractParams.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAGzE,MAAM,wBAAwB,OAAqB;IAC3C,IAAA,mCAG4B,EAFhC,kCAAc,EACd,4CAAmB,CACa;IAElC,IAAM,iBAAiB,GAAG,wBAAwB,CAAC,cAAc,CAAC,CAAA;IAElE,yBAAyB,UAAkB,EAAE,WAAmB;QAC9D,IAAM,UAAU,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,UAAU,GAAG,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAA;QACnG,IAAM,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAA;QACxD,OAAO;YACL,OAAO,EAAE,UAAU;YACnB,IAAI,EAAE,OAAO;SACd,CAAA;IACH,CAAC;IAED,IAAM,YAAY,GAAG,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;IAChD,IAAM,YAAY,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;IACjD,IAAM,YAAY,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;IACjD,IAAM,YAAY,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;IACjD,IAAM,YAAY,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;IACjD,IAAM,YAAY,GAAG,iBAAiB,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;IAClD,IAAM,YAAY,GAAG,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;IACnD,IAAM,YAAY,GAAG,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;IACnD,IAAM,UAAU,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAC9C,IAAM,UAAU,GAAG,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAE7C,IAAI,mBAAmB,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE;QACtC,MAAM,IAAI,KAAK,CAAC,oCAAkC,mBAAmB,EAAE,CAAC,MAAQ,CAAC,CAAA;KAClF;IAED,OAAO;QACL,YAAY,cAAA;QACZ,YAAY,cAAA;QACZ,YAAY,cAAA;QACZ,YAAY,cAAA;QACZ,YAAY,cAAA;QACZ,YAAY,cAAA;QACZ,YAAY,cAAA;QACZ,YAAY,cAAA;QACZ,UAAU,YAAA;QACV,UAAU,YAAA;KACX,CAAA;AACH,CAAC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { FaceLandmarkNet } from './types';
export declare function fullyConnectedLayer(x: tf.Tensor2D, params: FaceLandmarkNet.FCParams): tf.Tensor2D;
import * as tf from '@tensorflow/tfjs-core';
export function fullyConnectedLayer(x, params) {
return tf.tidy(function () {
return tf.add(tf.matMul(x, params.weights), params.bias);
});
}
//# sourceMappingURL=fullyConnectedLayer.js.map
\ No newline at end of file
{"version":3,"file":"fullyConnectedLayer.js","sourceRoot":"","sources":["../../src/faceLandmarkNet/fullyConnectedLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAI5C,MAAM,8BACJ,CAAc,EACd,MAAgC;IAEhC,OAAO,EAAE,CAAC,IAAI,CAAC;QACb,OAAA,EAAE,CAAC,GAAG,CACJ,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,EAC5B,MAAM,CAAC,IAAI,CACZ;IAHD,CAGC,CACF,CAAA;AACH,CAAC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { NetInput } from '../NetInput';
import { FaceLandmarks } from './FaceLandmarks';
export declare function faceLandmarkNet(weights: Float32Array): {
detectLandmarks: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | NetInput | tf.Tensor<tf.Rank>) => Promise<FaceLandmarks>;
};
import * as tslib_1 from "tslib";
import * as tf from '@tensorflow/tfjs-core';
import { convLayer } from '../commons/convLayer';
import { getImageTensor } from '../getImageTensor';
import { Point } from '../Point';
import { extractParams } from './extractParams';
import { FaceLandmarks } from './FaceLandmarks';
import { fullyConnectedLayer } from './fullyConnectedLayer';
function conv(x, params) {
return convLayer(x, params, 'valid', true);
}
function maxPool(x, strides) {
if (strides === void 0) { strides = [2, 2]; }
return tf.maxPool(x, [2, 2], strides, 'valid');
}
export function faceLandmarkNet(weights) {
var params = extractParams(weights);
function detectLandmarks(input) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var imageDimensions, outTensor, faceLandmarksArray, _a, _b, xCoords, yCoords;
return tslib_1.__generator(this, function (_c) {
switch (_c.label) {
case 0:
outTensor = tf.tidy(function () {
var imgTensor = getImageTensor(input);
var _a = imgTensor.shape.slice(1), height = _a[0], width = _a[1];
imageDimensions = { width: width, height: height };
// work with 128 x 128 sized face images
if (imgTensor.shape[1] !== 128 || imgTensor.shape[2] !== 128) {
imgTensor = tf.image.resizeBilinear(imgTensor, [128, 128]);
}
var out = conv(imgTensor, params.conv0_params);
out = maxPool(out);
out = conv(out, params.conv1_params);
out = conv(out, params.conv2_params);
out = maxPool(out);
out = conv(out, params.conv3_params);
out = conv(out, params.conv4_params);
out = maxPool(out);
out = conv(out, params.conv5_params);
out = conv(out, params.conv6_params);
out = maxPool(out, [1, 1]);
out = conv(out, params.conv7_params);
var fc0 = tf.relu(fullyConnectedLayer(out.as2D(out.shape[0], -1), params.fc0_params));
var fc1 = fullyConnectedLayer(fc0, params.fc1_params);
return fc1;
});
_b = (_a = Array).from;
return [4 /*yield*/, outTensor.data()];
case 1:
faceLandmarksArray = _b.apply(_a, [_c.sent()]);
outTensor.dispose();
xCoords = faceLandmarksArray.filter(function (c, i) { return (i - 1) % 2; });
yCoords = faceLandmarksArray.filter(function (c, i) { return i % 2; });
return [2 /*return*/, new FaceLandmarks(Array(68).fill(0).map(function (_, i) { return new Point(xCoords[i], yCoords[i]); }), imageDimensions)];
}
});
});
}
return {
detectLandmarks: detectLandmarks
};
}
//# sourceMappingURL=index.js.map
\ No newline at end of file
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/faceLandmarkNet/index.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,cAAc,CAAc,EAAE,MAAkB;IAC9C,OAAO,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;AAC5C,CAAC;AAED,iBAAiB,CAAc,EAAE,OAAkC;IAAlC,wBAAA,EAAA,WAA6B,CAAC,EAAE,CAAC,CAAC;IACjE,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;AAChD,CAAC;AAED,MAAM,0BAA0B,OAAqB;IACnD,IAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;IAErC,yBAA+B,KAAuC;;;;;;wBAG9D,SAAS,GAAG,EAAE,CAAC,IAAI,CAAC;4BACxB,IAAI,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,CAAA;4BAC/B,IAAA,6BAA0C,EAAzC,cAAM,EAAE,aAAK,CAA4B;4BAChD,eAAe,GAAG,EAAE,KAAK,OAAA,EAAE,MAAM,QAAA,EAAE,CAAA;4BAGnC,wCAAwC;4BACxC,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;gCAC5D,SAAS,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;6BAC3D;4BAED,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;4BAC9C,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;4BAClB,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;4BACpC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;4BACpC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;4BAClB,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;4BACpC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;4BACpC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;4BAClB,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;4BACpC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;4BACpC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;4BAC1B,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;4BACpC,IAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAA;4BACvF,IAAM,GAAG,GAAG,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,CAAA;4BAEvD,OAAO,GAAG,CAAA;wBACZ,CAAC,CAAC,CAAA;wBAEyB,KAAA,CAAA,KAAA,KAAK,CAAA,CAAC,IAAI,CAAA;wBAAC,qBAAM,SAAS,CAAC,IAAI,EAAE,EAAA;;wBAAtD,kBAAkB,GAAG,cAAW,SAAsB,EAAC;wBAC7D,SAAS,CAAC,OAAO,EAAE,CAAA;wBAEb,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,UAAC,CAAC,EAAE,CAAC,IAAK,OAAA,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAX,CAAW,CAAC,CAAA;wBAC1D,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,UAAC,CAAC,EAAE,CAAC,IAAK,OAAA,CAAC,GAAG,CAAC,EAAL,CAAK,CAAC,CAAA;wBAE1D,sBAAO,IAAI,aAAa,CACtB,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAC,CAAC,EAAE,CAAC,IAAK,OAAA,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAjC,CAAiC,CAAC,EAClE,eAA6B,CAC9B,EAAA;;;;KACF;IAED,OAAO;QACL,eAAe,iBAAA;KAChB,CAAA;AACH,CAAC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { ConvParams } from '../commons/types';
export declare namespace FaceLandmarkNet {
type FCParams = {
weights: tf.Tensor2D;
bias: tf.Tensor1D;
};
type NetParams = {
conv0_params: ConvParams;
conv1_params: ConvParams;
conv2_params: ConvParams;
conv3_params: ConvParams;
conv4_params: ConvParams;
conv5_params: ConvParams;
conv6_params: ConvParams;
conv7_params: ConvParams;
fc0_params: FCParams;
fc1_params: FCParams;
};
}
//# sourceMappingURL=types.js.map
\ No newline at end of file
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/faceLandmarkNet/types.ts"],"names":[],"mappings":""}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { scale } from './scaleLayer'; import { scale } from './scaleLayer';
function convLayer(x, params, stride, withRelu, padding) { function convLayer(x, params, strides, withRelu, padding) {
if (padding === void 0) { padding = 'same'; } if (padding === void 0) { padding = 'same'; }
var _a = params.conv, filters = _a.filters, biases = _a.biases; var _a = params.conv, filters = _a.filters, bias = _a.bias;
var out = tf.conv2d(x, filters, [stride, stride], padding); var out = tf.conv2d(x, filters, strides, padding);
out = tf.add(out, biases); out = tf.add(out, bias);
out = scale(out, params.scale); out = scale(out, params.scale);
return withRelu ? tf.relu(out) : out; return withRelu ? tf.relu(out) : out;
} }
export function conv(x, params) { export function conv(x, params) {
return convLayer(x, params, 1, true); return convLayer(x, params, [1, 1], true);
} }
export function convNoRelu(x, params) { export function convNoRelu(x, params) {
return convLayer(x, params, 1, false); return convLayer(x, params, [1, 1], false);
} }
export function convDown(x, params) { export function convDown(x, params) {
return convLayer(x, params, 2, true, 'valid'); return convLayer(x, params, [2, 2], true, 'valid');
} }
//# sourceMappingURL=convLayer.js.map //# sourceMappingURL=convLayer.js.map
\ No newline at end of file
{"version":3,"file":"convLayer.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/convLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAIrC,mBACE,CAAc,EACd,MAA0C,EAC1C,MAAc,EACd,QAAiB,EACjB,OAAkC;IAAlC,wBAAA,EAAA,gBAAkC;IAE5B,IAAA,gBAAiC,EAA/B,oBAAO,EAAE,kBAAM,CAAgB;IAEvC,IAAI,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAA;IAC1D,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IACzB,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IAC9B,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;AACtC,CAAC;AAED,MAAM,eAAe,CAAc,EAAE,MAA0C;IAC7E,OAAO,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;AACtC,CAAC;AAED,MAAM,qBAAqB,CAAc,EAAE,MAA0C;IACnF,OAAO,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,mBAAmB,CAAc,EAAE,MAA0C;IACjF,OAAO,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;AAC/C,CAAC"} {"version":3,"file":"convLayer.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/convLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAIrC,mBACE,CAAc,EACd,MAA0C,EAC1C,OAAyB,EACzB,QAAiB,EACjB,OAAkC;IAAlC,wBAAA,EAAA,gBAAkC;IAE5B,IAAA,gBAA+B,EAA7B,oBAAO,EAAE,cAAI,CAAgB;IAErC,IAAI,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACjD,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IACvB,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IAC9B,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;AACtC,CAAC;AAED,MAAM,eAAe,CAAc,EAAE,MAA0C;IAC7E,OAAO,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;AAC3C,CAAC;AAED,MAAM,qBAAqB,CAAc,EAAE,MAA0C;IACnF,OAAO,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;AAC5C,CAAC;AAED,MAAM,mBAAmB,CAAc,EAAE,MAA0C;IACjF,OAAO,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;AACpD,CAAC"}
\ No newline at end of file \ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { extractWeightsFactory } from '../commons/extractWeightsFactory';
import { isFloat } from '../utils'; import { isFloat } from '../utils';
function extractorsFactory(extractWeights) { function extractorsFactory(extractWeights) {
function extractFilterValues(numFilterValues, numFilters, filterSize) { function extractFilterValues(numFilterValues, numFilters, filterSize) {
...@@ -19,12 +20,12 @@ function extractorsFactory(extractWeights) { ...@@ -19,12 +20,12 @@ function extractorsFactory(extractWeights) {
} }
function extractConvLayerParams(numFilterValues, numFilters, filterSize) { function extractConvLayerParams(numFilterValues, numFilters, filterSize) {
var conv_filters = extractFilterValues(numFilterValues, numFilters, filterSize); var conv_filters = extractFilterValues(numFilterValues, numFilters, filterSize);
var conv_biases = tf.tensor1d(extractWeights(numFilters)); var conv_bias = tf.tensor1d(extractWeights(numFilters));
var scale = extractScaleLayerParams(numFilters); var scale = extractScaleLayerParams(numFilters);
return { return {
conv: { conv: {
filters: conv_filters, filters: conv_filters,
biases: conv_biases bias: conv_bias
}, },
scale: scale scale: scale
}; };
...@@ -44,12 +45,8 @@ function extractorsFactory(extractWeights) { ...@@ -44,12 +45,8 @@ function extractorsFactory(extractWeights) {
}; };
} }
export function extractParams(weights) { export function extractParams(weights) {
var extractWeights = function (numWeights) { var _a = extractWeightsFactory(weights), extractWeights = _a.extractWeights, getRemainingWeights = _a.getRemainingWeights;
var ret = weights.slice(0, numWeights); var _b = extractorsFactory(extractWeights), extractConvLayerParams = _b.extractConvLayerParams, extractResidualLayerParams = _b.extractResidualLayerParams;
weights = weights.slice(numWeights);
return ret;
};
var _a = extractorsFactory(extractWeights), extractConvLayerParams = _a.extractConvLayerParams, extractResidualLayerParams = _a.extractResidualLayerParams;
var conv32_down = extractConvLayerParams(4704, 32, 7); var conv32_down = extractConvLayerParams(4704, 32, 7);
var conv32_1 = extractResidualLayerParams(9216, 32, 3); var conv32_1 = extractResidualLayerParams(9216, 32, 3);
var conv32_2 = extractResidualLayerParams(9216, 32, 3); var conv32_2 = extractResidualLayerParams(9216, 32, 3);
...@@ -66,8 +63,8 @@ export function extractParams(weights) { ...@@ -66,8 +63,8 @@ export function extractParams(weights) {
var conv256_2 = extractResidualLayerParams(589824, 256, 3); var conv256_2 = extractResidualLayerParams(589824, 256, 3);
var conv256_down_out = extractResidualLayerParams(589824, 256, 3); var conv256_down_out = extractResidualLayerParams(589824, 256, 3);
var fc = tf.transpose(tf.tensor2d(extractWeights(256 * 128), [128, 256]), [1, 0]); var fc = tf.transpose(tf.tensor2d(extractWeights(256 * 128), [128, 256]), [1, 0]);
if (weights.length !== 0) { if (getRemainingWeights().length !== 0) {
throw new Error("weights remaing after extract: " + weights.length); throw new Error("weights remaing after extract: " + getRemainingWeights().length);
} }
return { return {
conv32_down: conv32_down, conv32_down: conv32_down,
......
{"version":3,"file":"extractParams.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/extractParams.ts"],"names":[],"mappings":"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"} {"version":3,"file":"extractParams.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/extractParams.ts"],"names":[],"mappings":"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"}
\ No newline at end of file \ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { NetInput } from '../NetInput'; import { NetInput } from '../NetInput';
export declare function faceRecognitionNet(weights: Float32Array): { export declare function faceRecognitionNet(weights: Float32Array): {
computeFaceDescriptor: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | tf.Tensor<tf.Rank> | NetInput) => Promise<Int32Array | Uint8Array | Float32Array>; computeFaceDescriptor: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | NetInput | tf.Tensor<tf.Rank>) => Promise<Int32Array | Uint8Array | Float32Array>;
computeFaceDescriptorSync: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | tf.Tensor<tf.Rank> | NetInput) => Int32Array | Uint8Array | Float32Array; computeFaceDescriptorSync: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | NetInput | tf.Tensor<tf.Rank>) => Int32Array | Uint8Array | Float32Array;
forward: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | tf.Tensor<tf.Rank> | NetInput) => tf.Tensor<tf.Rank.R2>; forward: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | NetInput | tf.Tensor<tf.Rank>) => tf.Tensor<tf.Rank.R2>;
}; };
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { ConvParams } from '../commons/types';
export declare namespace FaceRecognitionNet { export declare namespace FaceRecognitionNet {
type ScaleLayerParams = { type ScaleLayerParams = {
weights: tf.Tensor1D; weights: tf.Tensor1D;
...@@ -8,10 +9,6 @@ export declare namespace FaceRecognitionNet { ...@@ -8,10 +9,6 @@ export declare namespace FaceRecognitionNet {
conv1: ConvLayerParams; conv1: ConvLayerParams;
conv2: ConvLayerParams; conv2: ConvLayerParams;
}; };
type ConvParams = {
filters: tf.Tensor4D;
biases: tf.Tensor1D;
};
type ConvLayerParams = { type ConvLayerParams = {
conv: ConvParams; conv: ConvParams;
scale: ScaleLayerParams; scale: ScaleLayerParams;
......
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { euclideanDistance } from './euclideanDistance'; import { euclideanDistance } from './euclideanDistance';
import { faceDetectionNet } from './faceDetectionNet'; import { faceDetectionNet } from './faceDetectionNet';
import { faceLandmarkNet } from './faceLandmarkNet';
import { faceRecognitionNet } from './faceRecognitionNet'; import { faceRecognitionNet } from './faceRecognitionNet';
import { NetInput } from './NetInput'; import { NetInput } from './NetInput';
import { padToSquare } from './padToSquare'; import { padToSquare } from './padToSquare';
export { euclideanDistance, faceDetectionNet, faceRecognitionNet, NetInput, tf, padToSquare }; export { euclideanDistance, faceDetectionNet, faceLandmarkNet, faceRecognitionNet, NetInput, tf, padToSquare };
export * from './extractFaces'; export * from './extractFaces';
export * from './extractFaceTensors'; export * from './extractFaceTensors';
export * from './utils'; export * from './utils';
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { euclideanDistance } from './euclideanDistance'; import { euclideanDistance } from './euclideanDistance';
import { faceDetectionNet } from './faceDetectionNet'; import { faceDetectionNet } from './faceDetectionNet';
import { faceLandmarkNet } from './faceLandmarkNet';
import { faceRecognitionNet } from './faceRecognitionNet'; import { faceRecognitionNet } from './faceRecognitionNet';
import { NetInput } from './NetInput'; import { NetInput } from './NetInput';
import { padToSquare } from './padToSquare'; import { padToSquare } from './padToSquare';
export { euclideanDistance, faceDetectionNet, faceRecognitionNet, NetInput, tf, padToSquare }; export { euclideanDistance, faceDetectionNet, faceLandmarkNet, faceRecognitionNet, NetInput, tf, padToSquare };
export * from './extractFaces'; export * from './extractFaces';
export * from './extractFaceTensors'; export * from './extractFaceTensors';
export * from './utils'; export * from './utils';
......
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,QAAQ,EACR,EAAE,EACF,WAAW,EACZ,CAAA;AAED,cAAc,gBAAgB,CAAA;AAC9B,cAAc,sBAAsB,CAAA;AACpC,cAAc,SAAS,CAAA"} {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,QAAQ,EACR,EAAE,EACF,WAAW,EACZ,CAAA;AAED,cAAc,gBAAgB,CAAA;AAC9B,cAAc,sBAAsB,CAAA;AACpC,cAAc,SAAS,CAAA"}
\ No newline at end of file \ No newline at end of file
...@@ -6,13 +6,22 @@ export declare type Dimensions = { ...@@ -6,13 +6,22 @@ export declare type Dimensions = {
height: number; height: number;
}; };
export declare type DrawBoxOptions = { export declare type DrawBoxOptions = {
lineWidth: number; lineWidth?: number;
color: string; color?: string;
}; };
export declare type DrawTextOptions = { export declare type DrawTextOptions = {
lineWidth?: number;
fontSize?: number;
fontStyle?: string;
color?: string;
};
export declare type DrawLandmarksOptions = {
lineWidth?: number;
color?: string;
};
export declare type DrawOptions = {
lineWidth: number; lineWidth: number;
fontSize: number; fontSize: number;
fontStyle: string; fontStyle: string;
color: string; color: string;
}; };
export declare type DrawOptions = DrawBoxOptions & DrawTextOptions;
import { FaceDetectionNet } from './faceDetectionNet/types'; import { FaceDetection } from './faceDetectionNet/FaceDetection';
import { Dimensions, DrawBoxOptions, DrawOptions, DrawTextOptions } from './types'; import { FaceLandmarks } from './faceLandmarkNet/FaceLandmarks';
import { Dimensions, DrawBoxOptions, DrawLandmarksOptions, DrawOptions, DrawTextOptions } from './types';
export declare function isFloat(num: number): boolean; export declare function isFloat(num: number): boolean;
export declare function round(num: number): number; export declare function round(num: number): number;
export declare function getElement(arg: string | any): any; export declare function getElement(arg: string | any): any;
export declare function getContext2dOrThrow(canvas: HTMLCanvasElement): CanvasRenderingContext2D; export declare function getContext2dOrThrow(canvas: HTMLCanvasElement): CanvasRenderingContext2D;
export declare function createCanvas({width, height}: Dimensions): HTMLCanvasElement; export declare function createCanvas({width, height}: Dimensions): HTMLCanvasElement;
export declare function createCanvasWithImageData({width, height}: Dimensions, buf: Uint8ClampedArray): HTMLCanvasElement; export declare function createCanvasFromMedia(media: HTMLImageElement | HTMLVideoElement, dims?: Dimensions): HTMLCanvasElement;
export declare function getMediaDimensions(media: HTMLImageElement | HTMLVideoElement): { export declare function getMediaDimensions(media: HTMLImageElement | HTMLVideoElement): {
width: number; width: number;
height: number; height: number;
...@@ -14,6 +15,9 @@ export declare function bufferToImage(buf: Blob): Promise<HTMLImageElement>; ...@@ -14,6 +15,9 @@ export declare function bufferToImage(buf: Blob): Promise<HTMLImageElement>;
export declare function getDefaultDrawOptions(): DrawOptions; export declare function getDefaultDrawOptions(): DrawOptions;
export declare function drawBox(ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, options: DrawBoxOptions): void; export declare function drawBox(ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, options: DrawBoxOptions): void;
export declare function drawText(ctx: CanvasRenderingContext2D, x: number, y: number, text: string, options: DrawTextOptions): void; export declare function drawText(ctx: CanvasRenderingContext2D, x: number, y: number, text: string, options: DrawTextOptions): void;
export declare function drawDetection(canvasArg: string | HTMLCanvasElement, detection: FaceDetectionNet.Detection | FaceDetectionNet.Detection[], options?: DrawBoxOptions & DrawTextOptions & { export declare function drawDetection(canvasArg: string | HTMLCanvasElement, detection: FaceDetection | FaceDetection[], options?: DrawBoxOptions & DrawTextOptions & {
withScore: boolean; withScore: boolean;
}): void; }): void;
export declare function drawLandmarks(canvasArg: string | HTMLCanvasElement, faceLandmarks: FaceLandmarks, options?: DrawLandmarksOptions & {
drawLines: boolean;
}): void;
...@@ -24,10 +24,10 @@ export function createCanvas(_a) { ...@@ -24,10 +24,10 @@ export function createCanvas(_a) {
canvas.height = height; canvas.height = height;
return canvas; return canvas;
} }
export function createCanvasWithImageData(_a, buf) { export function createCanvasFromMedia(media, dims) {
var width = _a.width, height = _a.height; var _a = dims || getMediaDimensions(media), width = _a.width, height = _a.height;
var canvas = createCanvas({ width: width, height: height }); var canvas = createCanvas({ width: width, height: height });
getContext2dOrThrow(canvas).putImageData(new ImageData(buf, width, height), 0, 0); getContext2dOrThrow(canvas).drawImage(media, 0, 0, width, height);
return canvas; return canvas;
} }
export function getMediaDimensions(media) { export function getMediaDimensions(media) {
...@@ -64,15 +64,17 @@ export function getDefaultDrawOptions() { ...@@ -64,15 +64,17 @@ export function getDefaultDrawOptions() {
}; };
} }
export function drawBox(ctx, x, y, w, h, options) { export function drawBox(ctx, x, y, w, h, options) {
ctx.strokeStyle = options.color; var drawOptions = Object.assign(getDefaultDrawOptions(), (options || {}));
ctx.lineWidth = options.lineWidth; ctx.strokeStyle = drawOptions.color;
ctx.lineWidth = drawOptions.lineWidth;
ctx.strokeRect(x, y, w, h); ctx.strokeRect(x, y, w, h);
} }
export function drawText(ctx, x, y, text, options) { export function drawText(ctx, x, y, text, options) {
var padText = 2 + options.lineWidth; var drawOptions = Object.assign(getDefaultDrawOptions(), (options || {}));
ctx.fillStyle = options.color; var padText = 2 + drawOptions.lineWidth;
ctx.font = options.fontSize + "px " + options.fontStyle; ctx.fillStyle = drawOptions.color;
ctx.fillText(text, x + padText, y + padText + (options.fontSize * 0.6)); ctx.font = drawOptions.fontSize + "px " + drawOptions.fontStyle;
ctx.fillText(text, x + padText, y + padText + (drawOptions.fontSize * 0.6));
} }
export function drawDetection(canvasArg, detection, options) { export function drawDetection(canvasArg, detection, options) {
var canvas = getElement(canvasArg); var canvas = getElement(canvasArg);
...@@ -83,15 +85,60 @@ export function drawDetection(canvasArg, detection, options) { ...@@ -83,15 +85,60 @@ export function drawDetection(canvasArg, detection, options) {
? detection ? detection
: [detection]; : [detection];
detectionArray.forEach(function (det) { detectionArray.forEach(function (det) {
var score = det.score, box = det.box; var _a = det.getBox(), x = _a.x, y = _a.y, width = _a.width, height = _a.height;
var x = box.x, y = box.y, width = box.width, height = box.height;
var drawOptions = Object.assign(getDefaultDrawOptions(), (options || {})); var drawOptions = Object.assign(getDefaultDrawOptions(), (options || {}));
var withScore = Object.assign({ withScore: true }, (options || {})).withScore; var withScore = Object.assign({ withScore: true }, (options || {})).withScore;
var ctx = getContext2dOrThrow(canvas); var ctx = getContext2dOrThrow(canvas);
drawBox(ctx, x, y, width, height, drawOptions); drawBox(ctx, x, y, width, height, drawOptions);
if (withScore) { if (withScore) {
drawText(ctx, x, y, "" + round(score), drawOptions); drawText(ctx, x, y, "" + round(det.getScore()), drawOptions);
} }
}); });
} }
function drawContour(ctx, points, isClosed) {
if (isClosed === void 0) { isClosed = false; }
ctx.beginPath();
points.slice(1).forEach(function (_a, prevIdx) {
var x = _a.x, y = _a.y;
var from = points[prevIdx];
ctx.moveTo(from.x, from.y);
ctx.lineTo(x, y);
});
if (isClosed) {
var from = points[points.length - 1];
var to = points[0];
if (!from || !to) {
return;
}
ctx.moveTo(from.x, from.y);
ctx.lineTo(to.x, to.y);
}
ctx.stroke();
}
export function drawLandmarks(canvasArg, faceLandmarks, options) {
var canvas = getElement(canvasArg);
if (!(canvas instanceof HTMLCanvasElement)) {
throw new Error('drawLandmarks - expected canvas to be of type: HTMLCanvasElement');
}
var drawOptions = Object.assign(getDefaultDrawOptions(), (options || {}));
var drawLines = Object.assign({ drawLines: false }, (options || {})).drawLines;
var ctx = getContext2dOrThrow(canvas);
var lineWidth = drawOptions.lineWidth, color = drawOptions.color;
if (drawLines) {
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
drawContour(ctx, faceLandmarks.getJawOutline());
drawContour(ctx, faceLandmarks.getLeftEyeBrow());
drawContour(ctx, faceLandmarks.getRightEyeBrow());
drawContour(ctx, faceLandmarks.getNose());
drawContour(ctx, faceLandmarks.getLeftEye(), true);
drawContour(ctx, faceLandmarks.getRightEye(), true);
drawContour(ctx, faceLandmarks.getMouth(), true);
return;
}
// else draw points
var ptOffset = lineWidth / 2;
ctx.fillStyle = color;
faceLandmarks.getPositions().forEach(function (pt) { return ctx.fillRect(pt.x - ptOffset, pt.y - ptOffset, lineWidth, lineWidth); });
}
//# sourceMappingURL=utils.js.map //# sourceMappingURL=utils.js.map
\ No newline at end of file
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"} {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
\ No newline at end of file \ No newline at end of file
...@@ -24,6 +24,12 @@ async function initFaceRecognitionNet() { ...@@ -24,6 +24,12 @@ async function initFaceRecognitionNet() {
return faceapi.faceRecognitionNet(weights) return faceapi.faceRecognitionNet(weights)
} }
async function initFaceLandmarkNet() {
const res = await axios.get('face_landmark_68_model.weights', { responseType: 'arraybuffer' })
const weights = new Float32Array(res.data)
return faceapi.faceLandmarkNet(weights)
}
// fetch first image of each class and compute their descriptors // fetch first image of each class and compute their descriptors
async function initTrainDescriptorsByClass(net, numImagesForTraining = 1) { async function initTrainDescriptorsByClass(net, numImagesForTraining = 1) {
const maxAvailableImagesPerClass = 5 const maxAvailableImagesPerClass = 5
...@@ -83,6 +89,14 @@ function renderNavBar(navbarId, exampleUri) { ...@@ -83,6 +89,14 @@ function renderNavBar(navbarId, exampleUri) {
name: 'Face Similarity' name: 'Face Similarity'
}, },
{ {
uri: 'face_landmarks',
name: 'Face Landmarks'
},
{
uri: 'detect_and_draw_landmarks',
name: 'Detect and Draw Landmarks'
},
{
uri: 'detect_and_draw_faces', uri: 'detect_and_draw_faces',
name: 'Detect and Draw Faces' name: 'Detect and Draw Faces'
}, },
......
...@@ -15,7 +15,9 @@ app.get('/face_detection', (req, res) => res.sendFile(path.join(viewsDir, 'faceD ...@@ -15,7 +15,9 @@ app.get('/face_detection', (req, res) => res.sendFile(path.join(viewsDir, 'faceD
app.get('/face_detection_video', (req, res) => res.sendFile(path.join(viewsDir, 'faceDetectionVideo.html'))) app.get('/face_detection_video', (req, res) => res.sendFile(path.join(viewsDir, 'faceDetectionVideo.html')))
app.get('/face_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'faceRecognition.html'))) app.get('/face_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'faceRecognition.html')))
app.get('/face_similarity', (req, res) => res.sendFile(path.join(viewsDir, 'faceSimilarity.html'))) app.get('/face_similarity', (req, res) => res.sendFile(path.join(viewsDir, 'faceSimilarity.html')))
app.get('/face_landmarks', (req, res) => res.sendFile(path.join(viewsDir, 'faceLandmarks.html')))
app.get('/detect_and_draw_faces', (req, res) => res.sendFile(path.join(viewsDir, 'detectAndDrawFaces.html'))) app.get('/detect_and_draw_faces', (req, res) => res.sendFile(path.join(viewsDir, 'detectAndDrawFaces.html')))
app.get('/detect_and_draw_landmarks', (req, res) => res.sendFile(path.join(viewsDir, 'detectAndDrawLandmarks.html')))
app.get('/detect_and_recognize_faces', (req, res) => res.sendFile(path.join(viewsDir, 'detectAndRecognizeFaces.html'))) app.get('/detect_and_recognize_faces', (req, res) => res.sendFile(path.join(viewsDir, 'detectAndRecognizeFaces.html')))
app.listen(3000, () => console.log('Listening on port 3000!')) app.listen(3000, () => console.log('Listening on port 3000!'))
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<script src="face-api.js"></script>
<script src="axios.min.js"></script>
<script src="commons.js"></script>
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css">
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
</head>
<body>
<div class="center-content page-container">
<div id="navbar"></div>
<div class="progress" id="loader">
<div class="indeterminate"></div>
</div>
<div style="position: relative" class="margin">
<img id="inputImg" src="" style="max-width: 800px;" />
<canvas id="overlay" />
</div>
<div class="row side-by-side">
<div id="selectList"></div>
<div class="row">
<label for="minConfidence">Min Confidence:</label>
<input disabled value="0.7" id="minConfidence" type="text" class="bold">
</div>
<button
class="waves-effect waves-light btn"
onclick="onDecreaseMinConfidence()"
>
<i class="material-icons left">-</i>
</button>
<button
class="waves-effect waves-light btn"
onclick="onIncreaseMinConfidence()"
>
<i class="material-icons left">+</i>
</button>
</div>
</div>
<script>
let minConfidence = 0.7
let drawLines = true
let detectionNet, landmarkNet
function onIncreaseMinConfidence() {
minConfidence = Math.min(faceapi.round(minConfidence + 0.1), 1.0)
$('#minConfidence').val(minConfidence)
updateResults()
}
function onDecreaseMinConfidence() {
minConfidence = Math.max(faceapi.round(minConfidence - 0.1), 0.1)
$('#minConfidence').val(minConfidence)
updateResults()
}
async function updateResults() {
const inputImgEl = $('#inputImg').get(0)
const { width, height } = inputImgEl
const canvas = $('#overlay').get(0)
canvas.width = width
canvas.height = height
const input = new faceapi.NetInput(inputImgEl)
const locations = await detectionNet.locateFaces(input, minConfidence)
const faceTensors = (await faceapi.extractFaceTensors(input, locations))
landmarksByFace = await Promise.all(faceTensors.map(t => landmarkNet.detectLandmarks(t)))
// free memory for face image tensors after we computed their descriptors
faceTensors.forEach(t => t.dispose())
landmarksByFace.forEach((landmarks, i) => {
// shift and scale the face landmarks to the face image position in the canvas
const box = locations[i].forSize(width, height).getBox()
faceapi.drawLandmarks(canvas, landmarks.forSize(box.width, box.height).shift(box.x, box.y), { lineWidth: drawLines ? 2 : 4, drawLines, color: 'red' })
})
faceapi.drawDetection('overlay', locations.map(det => det.forSize(width, height)))
}
async function onSelectionChanged(uri) {
const imgBuf = await fetchImage(uri)
$(`#inputImg`).get(0).src = (await faceapi.bufferToImage(imgBuf)).src
updateResults()
}
async function run() {
detectionNet = await initFaceDetectionNet()
landmarkNet = await initFaceLandmarkNet()
$('#loader').hide()
onSelectionChanged($('#selectList select').val())
}
$(document).ready(function() {
renderNavBar('#navbar', 'detect_and_draw_landmarks')
renderImageSelectList(
'#selectList',
async (uri) => {
await onSelectionChanged(uri)
},
'bbt1.jpg'
)
run()
})
</script>
</body>
</html>
\ No newline at end of file
...@@ -108,7 +108,7 @@ ...@@ -108,7 +108,7 @@
descriptors.forEach((descriptor, i) => { descriptors.forEach((descriptor, i) => {
const bestMatch = getBestMatch(trainDescriptorsByClass, descriptor) const bestMatch = getBestMatch(trainDescriptorsByClass, descriptor)
const text = `${bestMatch.distance < maxDistance ? bestMatch.className : 'unkown'} (${bestMatch.distance})` const text = `${bestMatch.distance < maxDistance ? bestMatch.className : 'unkown'} (${bestMatch.distance})`
const { x, y, height: boxHeight } = detectionsForSize[i].box const { x, y, height: boxHeight } = detectionsForSize[i].getBox()
faceapi.drawText( faceapi.drawText(
canvas.getContext('2d'), canvas.getContext('2d'),
x, x,
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
<canvas id="overlay" /> <canvas id="overlay" />
</div> </div>
<div class="row side-by-side"> <div class="row side-by-side">
<div id="selectList"></div>
<div class="row"> <div class="row">
<label for="minConfidence">Min Confidence:</label> <label for="minConfidence">Min Confidence:</label>
<input disabled value="0.7" id="minConfidence" type="text" class="bold"> <input disabled value="0.7" id="minConfidence" type="text" class="bold">
......
<!DOCTYPE html>
<html>
<head>
<script src="face-api.js"></script>
<script src="axios.min.js"></script>
<script src="commons.js"></script>
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css">
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
</head>
<body>
<div class="center-content page-container">
<div id="navbar"></div>
<div>
<div class="progress" id="loader">
<div class="indeterminate"></div>
</div>
<div class="row side-by-side">
<div class="center-content">
<div id="faceContainer"></div>
<div id="selectList"></div>
</div>
</div>
<p>
<input type="checkbox" id="drawLinesCheckbox" checked="checked" onchange="onChangeDrawLines(event)" />
<label for="drawLinesCheckbox">Draw Lines</label>
</p>
</div>
</div>
<script>
let net
let drawLines = true
let landmarks
let currentImg
function onChangeDrawLines(e) {
drawLines = $(e.target).prop('checked')
redraw()
}
function redraw() {
const canvas = faceapi.createCanvasFromMedia(currentImg)
$('#faceContainer').empty()
$('#faceContainer').append(canvas)
faceapi.drawLandmarks(canvas, landmarks, { lineWidth: drawLines ? 2 : 4, drawLines })
}
async function onSelectionChanged(uri) {
const imgBuf = await fetchImage(uri)
currentImg = await faceapi.bufferToImage(imgBuf)
landmarks = await net.detectLandmarks(currentImg)
redraw()
}
async function run() {
net = await initFaceLandmarkNet()
$('#loader').hide()
await onSelectionChanged($('#selectList select').val())
}
$(document).ready(function() {
renderNavBar('#navbar', 'face_landmarks')
renderFaceImageSelectList(
'#selectList',
onSelectionChanged,
{ className: 'sheldon', imageIdx: 1 }
)
run()
})
</script>
</body>
</html>
\ No newline at end of file
import { Dimensions, TMediaElement, TNetInput } from './types'; import { Dimensions, TMediaElement, TNetInput } from './types';
import { createCanvas, getContext2dOrThrow, getElement, getMediaDimensions } from './utils'; import { createCanvasFromMedia, getContext2dOrThrow, getElement, getMediaDimensions } from './utils';
export class NetInput { export class NetInput {
private _canvases: HTMLCanvasElement[] private _canvases: HTMLCanvasElement[]
...@@ -40,11 +40,8 @@ export class NetInput { ...@@ -40,11 +40,8 @@ export class NetInput {
} }
// if input is batch type, make sure every canvas has the same dimensions // if input is batch type, make sure every canvas has the same dimensions
const { width, height } = this.dims || dims || getMediaDimensions(media) const canvasDims = this.dims || dims
this._canvases.push(createCanvasFromMedia(media, canvasDims))
const canvas = createCanvas({ width, height })
getContext2dOrThrow(canvas).drawImage(media, 0, 0, width, height)
this._canvases.push(canvas)
} }
public get canvases() : HTMLCanvasElement[] { public get canvases() : HTMLCanvasElement[] {
......
export interface IPoint {
x: number
y: number
}
export class Point implements IPoint {
public x: number
public y: number
constructor(x: number, y: number) {
this.x = x
this.y = y
}
public add(pt: IPoint): Point {
return new Point(this.x + pt.x, this.y + pt.y)
}
public sub(pt: IPoint): Point {
return new Point(this.x - pt.x, this.y - pt.y)
}
public mul(pt: IPoint): Point {
return new Point(this.x * pt.x, this.y * pt.y)
}
public div(pt: IPoint): Point {
return new Point(this.x / pt.x, this.y / pt.y)
}
}
\ No newline at end of file
export class Rect {
public x: number
public y: number
public width: number
public height: number
constructor(x: number, y: number, width: number, height: number) {
this.x = x
this.y = y
this.width = width
this.height = height
}
public floor(): Rect {
return new Rect(
Math.floor(this.x),
Math.floor(this.y),
Math.floor(this.width),
Math.floor(this.height)
)
}
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { ConvParams } from './types';
export function convLayer(
x: tf.Tensor4D,
params: ConvParams,
padding: 'valid' | 'same' = 'same',
withRelu: boolean = false
): tf.Tensor4D {
return tf.tidy(() => {
const out = tf.add(
tf.conv2d(x, params.filters, [1, 1], padding),
params.bias
) as tf.Tensor4D
return withRelu ? tf.relu(out) : out
})
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { ConvParams, ExtractWeightsFunction } from './types';
export function extractConvParamsFactory(extractWeights: ExtractWeightsFunction) {
return function (
channelsIn: number,
channelsOut: number,
filterSize: number
): ConvParams {
const filters = tf.tensor4d(
extractWeights(channelsIn * channelsOut * filterSize * filterSize),
[filterSize, filterSize, channelsIn, channelsOut]
)
const bias = tf.tensor1d(extractWeights(channelsOut))
return {
filters,
bias
}
}
}
\ No newline at end of file
export function extractWeightsFactory(weights: Float32Array) {
let remainingWeights = weights
function extractWeights(numWeights: number): Float32Array {
const ret = remainingWeights.slice(0, numWeights)
remainingWeights = remainingWeights.slice(numWeights)
return ret
}
function getRemainingWeights(): Float32Array {
return remainingWeights
}
return {
extractWeights,
getRemainingWeights
}
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
export type ConvParams = {
filters: tf.Tensor4D
bias: tf.Tensor1D
}
export type ExtractWeightsFunction = (numWeights: number) => Float32Array
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { FaceDetectionResult } from './faceDetectionNet/FaceDetectionResult'; import { FaceDetection } from './faceDetectionNet/FaceDetection';
import { NetInput } from './NetInput';
import { getImageTensor } from './getImageTensor'; import { getImageTensor } from './getImageTensor';
import { NetInput } from './NetInput';
import { TNetInput } from './types'; import { TNetInput } from './types';
/** /**
...@@ -18,7 +18,7 @@ import { TNetInput } from './types'; ...@@ -18,7 +18,7 @@ import { TNetInput } from './types';
*/ */
export function extractFaceTensors( export function extractFaceTensors(
image: tf.Tensor | NetInput | TNetInput, image: tf.Tensor | NetInput | TNetInput,
detections: FaceDetectionResult[] detections: FaceDetection[]
): tf.Tensor4D[] { ): tf.Tensor4D[] {
return tf.tidy(() => { return tf.tidy(() => {
const imgTensor = getImageTensor(image) const imgTensor = getImageTensor(image)
...@@ -27,7 +27,7 @@ export function extractFaceTensors( ...@@ -27,7 +27,7 @@ export function extractFaceTensors(
const [batchSize, imgHeight, imgWidth, numChannels] = imgTensor.shape const [batchSize, imgHeight, imgWidth, numChannels] = imgTensor.shape
const faceTensors = detections.map(det => { const faceTensors = detections.map(det => {
const { x, y, width, height } = det.forSize(imgWidth, imgHeight).box const { x, y, width, height } = det.forSize(imgWidth, imgHeight).getBox().floor()
return tf.slice(imgTensor, [0, y, x, 0], [1, height, width, numChannels]) return tf.slice(imgTensor, [0, y, x, 0], [1, height, width, numChannels])
}) })
......
import { FaceDetectionResult } from './faceDetectionNet/FaceDetectionResult'; import { FaceDetection } from './faceDetectionNet/FaceDetection';
import { createCanvas, getContext2dOrThrow } from './utils'; import { createCanvas, getContext2dOrThrow } from './utils';
/** /**
...@@ -10,13 +10,12 @@ import { createCanvas, getContext2dOrThrow } from './utils'; ...@@ -10,13 +10,12 @@ import { createCanvas, getContext2dOrThrow } from './utils';
*/ */
export function extractFaces( export function extractFaces(
image: HTMLCanvasElement, image: HTMLCanvasElement,
detections: FaceDetectionResult[] detections: FaceDetection[]
): HTMLCanvasElement[] { ): HTMLCanvasElement[] {
const ctx = getContext2dOrThrow(image) const ctx = getContext2dOrThrow(image)
return detections.map(det => { return detections.map(det => {
const { x, y, width, height } = det.forSize(image.width, image.height).box const { x, y, width, height } = det.forSize(image.width, image.height).getBox().floor()
const faceImg = createCanvas({ width, height }) const faceImg = createCanvas({ width, height })
getContext2dOrThrow(faceImg) getContext2dOrThrow(faceImg)
.putImageData(ctx.getImageData(x, y, width, height), 0, 0) .putImageData(ctx.getImageData(x, y, width, height), 0, 0)
......
import { Rect } from '../Rect';
import { Dimensions } from '../types';
export class FaceDetection {
private _score: number
private _box: Rect
private _imageWidth: number
private _imageHeight: number
constructor(
score: number,
relativeBox: Rect,
imageDims: Dimensions
) {
const { width, height } = imageDims
this._imageWidth = width
this._imageHeight = height
this._score = score
this._box = new Rect(
relativeBox.x * width,
relativeBox.y * height,
relativeBox.width * width,
relativeBox.height * height
)
}
public getScore() {
return this._score
}
public getBox() {
return this._box
}
public getImageWidth() {
return this._imageWidth
}
public getImageHeight() {
return this._imageHeight
}
public getRelativeBox() {
return new Rect(
this._box.x / this._imageWidth,
this._box.y / this._imageHeight,
this._box.width / this._imageWidth,
this._box.height / this._imageHeight
)
}
public forSize(width: number, height: number): FaceDetection {
return new FaceDetection(
this._score,
this.getRelativeBox(),
{ width, height}
)
}
}
\ No newline at end of file
import { FaceDetectionNet } from './types';
export class FaceDetectionResult {
private _score: number
private _topRelative: number
private _leftRelative: number
private _bottomRelative: number
private _rightRelative: number
constructor(
score: number,
topRelative: number,
leftRelative: number,
bottomRelative: number,
rightRelative: number
) {
this._score = score
this._topRelative = Math.max(0, topRelative),
this._leftRelative = Math.max(0, leftRelative),
this._bottomRelative = Math.min(1.0, bottomRelative),
this._rightRelative = Math.min(1.0, rightRelative)
}
public forSize(width: number, height: number): FaceDetectionNet.Detection {
const x = Math.floor(this._leftRelative * width)
const y = Math.floor(this._topRelative * height)
return {
score: this._score,
box: {
x,
y,
width: Math.floor(this._rightRelative * width) - x,
height: Math.floor(this._bottomRelative * height) - y
}
}
}
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { convLayer } from '../commons/convLayer';
import { FaceDetectionNet } from './types'; import { FaceDetectionNet } from './types';
function convWithBias(
x: tf.Tensor4D,
params: FaceDetectionNet.ConvWithBiasParams
) {
return tf.tidy(() =>
tf.add(
tf.conv2d(x, params.filters, [1, 1], 'same'),
params.bias
)
)
}
export function boxPredictionLayer( export function boxPredictionLayer(
x: tf.Tensor4D, x: tf.Tensor4D,
...@@ -23,11 +13,11 @@ export function boxPredictionLayer( ...@@ -23,11 +13,11 @@ export function boxPredictionLayer(
const batchSize = x.shape[0] const batchSize = x.shape[0]
const boxPredictionEncoding = tf.reshape( const boxPredictionEncoding = tf.reshape(
convWithBias(x, params.box_encoding_predictor_params), convLayer(x, params.box_encoding_predictor_params),
[batchSize, -1, 1, 4] [batchSize, -1, 1, 4]
) )
const classPrediction = tf.reshape( const classPrediction = tf.reshape(
convWithBias(x, params.class_predictor_params), convLayer(x, params.class_predictor_params),
[batchSize, -1, 3] [batchSize, -1, 3]
) )
......
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { extractWeightsFactory } from '../commons/extractWeightsFactory';
import { ConvParams } from '../commons/types';
import { FaceDetectionNet } from './types'; import { FaceDetectionNet } from './types';
function extractorsFactory(extractWeights: (numWeights: number) => Float32Array) { function extractorsFactory(extractWeights: (numWeights: number) => Float32Array) {
...@@ -20,11 +22,11 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array) ...@@ -20,11 +22,11 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array)
} }
} }
function extractConvWithBiasParams( function extractConvParams(
channelsIn: number, channelsIn: number,
channelsOut: number, channelsOut: number,
filterSize: number filterSize: number
): FaceDetectionNet.ConvWithBiasParams { ): ConvParams {
const filters = tf.tensor4d( const filters = tf.tensor4d(
extractWeights(channelsIn * channelsOut * filterSize * filterSize), extractWeights(channelsIn * channelsOut * filterSize * filterSize),
[filterSize, filterSize, channelsIn, channelsOut] [filterSize, filterSize, channelsIn, channelsOut]
...@@ -45,7 +47,7 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array) ...@@ -45,7 +47,7 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array)
const { const {
filters, filters,
bias bias
} = extractConvWithBiasParams(channelsIn, channelsOut, filterSize) } = extractConvParams(channelsIn, channelsOut, filterSize)
return { return {
filters, filters,
...@@ -104,18 +106,18 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array) ...@@ -104,18 +106,18 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array)
const conv_6_params = extractPointwiseConvParams(256, 64, 1) const conv_6_params = extractPointwiseConvParams(256, 64, 1)
const conv_7_params = extractPointwiseConvParams(64, 128, 3) const conv_7_params = extractPointwiseConvParams(64, 128, 3)
const box_encoding_0_predictor_params = extractConvWithBiasParams(512, 12, 1) const box_encoding_0_predictor_params = extractConvParams(512, 12, 1)
const class_predictor_0_params = extractConvWithBiasParams(512, 9, 1) const class_predictor_0_params = extractConvParams(512, 9, 1)
const box_encoding_1_predictor_params = extractConvWithBiasParams(1024, 24, 1) const box_encoding_1_predictor_params = extractConvParams(1024, 24, 1)
const class_predictor_1_params = extractConvWithBiasParams(1024, 18, 1) const class_predictor_1_params = extractConvParams(1024, 18, 1)
const box_encoding_2_predictor_params = extractConvWithBiasParams(512, 24, 1) const box_encoding_2_predictor_params = extractConvParams(512, 24, 1)
const class_predictor_2_params = extractConvWithBiasParams(512, 18, 1) const class_predictor_2_params = extractConvParams(512, 18, 1)
const box_encoding_3_predictor_params = extractConvWithBiasParams(256, 24, 1) const box_encoding_3_predictor_params = extractConvParams(256, 24, 1)
const class_predictor_3_params = extractConvWithBiasParams(256, 18, 1) const class_predictor_3_params = extractConvParams(256, 18, 1)
const box_encoding_4_predictor_params = extractConvWithBiasParams(256, 24, 1) const box_encoding_4_predictor_params = extractConvParams(256, 24, 1)
const class_predictor_4_params = extractConvWithBiasParams(256, 18, 1) const class_predictor_4_params = extractConvParams(256, 18, 1)
const box_encoding_5_predictor_params = extractConvWithBiasParams(128, 24, 1) const box_encoding_5_predictor_params = extractConvParams(128, 24, 1)
const class_predictor_5_params = extractConvWithBiasParams(128, 18, 1) const class_predictor_5_params = extractConvParams(128, 18, 1)
const box_predictor_0_params = { const box_predictor_0_params = {
box_encoding_predictor_params: box_encoding_0_predictor_params, box_encoding_predictor_params: box_encoding_0_predictor_params,
...@@ -169,11 +171,10 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array) ...@@ -169,11 +171,10 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array)
} }
export function extractParams(weights: Float32Array): FaceDetectionNet.NetParams { export function extractParams(weights: Float32Array): FaceDetectionNet.NetParams {
const extractWeights = (numWeights: number): Float32Array => { const {
const ret = weights.slice(0, numWeights) extractWeights,
weights = weights.slice(numWeights) getRemainingWeights
return ret } = extractWeightsFactory(weights)
}
const { const {
extractMobilenetV1Params, extractMobilenetV1Params,
...@@ -190,8 +191,8 @@ export function extractParams(weights: Float32Array): FaceDetectionNet.NetParams ...@@ -190,8 +191,8 @@ export function extractParams(weights: Float32Array): FaceDetectionNet.NetParams
extra_dim extra_dim
} }
if (weights.length !== 0) { if (getRemainingWeights().length !== 0) {
throw new Error(`weights remaing after extract: ${weights.length}`) throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`)
} }
return { return {
......
...@@ -3,14 +3,15 @@ import * as tf from '@tensorflow/tfjs-core'; ...@@ -3,14 +3,15 @@ import * as tf from '@tensorflow/tfjs-core';
import { getImageTensor } from '../getImageTensor'; import { getImageTensor } from '../getImageTensor';
import { NetInput } from '../NetInput'; import { NetInput } from '../NetInput';
import { padToSquare } from '../padToSquare'; import { padToSquare } from '../padToSquare';
import { TNetInput } from '../types'; import { TNetInput, Dimensions } from '../types';
import { extractParams } from './extractParams'; import { extractParams } from './extractParams';
import { FaceDetectionResult } from './FaceDetectionResult'; import { FaceDetection } from './FaceDetection';
import { mobileNetV1 } from './mobileNetV1'; import { mobileNetV1 } from './mobileNetV1';
import { nonMaxSuppression } from './nonMaxSuppression'; import { nonMaxSuppression } from './nonMaxSuppression';
import { outputLayer } from './outputLayer'; import { outputLayer } from './outputLayer';
import { predictionLayer } from './predictionLayer'; import { predictionLayer } from './predictionLayer';
import { resizeLayer } from './resizeLayer'; import { resizeLayer } from './resizeLayer';
import { Rect } from '../Rect';
export function faceDetectionNet(weights: Float32Array) { export function faceDetectionNet(weights: Float32Array) {
const params = extractParams(weights) const params = extractParams(weights)
...@@ -40,9 +41,10 @@ export function faceDetectionNet(weights: Float32Array) { ...@@ -40,9 +41,10 @@ export function faceDetectionNet(weights: Float32Array) {
input: tf.Tensor | NetInput, input: tf.Tensor | NetInput,
minConfidence: number = 0.8, minConfidence: number = 0.8,
maxResults: number = 100, maxResults: number = 100,
): Promise<FaceDetectionResult[]> { ): Promise<FaceDetection[]> {
let paddedHeightRelative = 1, paddedWidthRelative = 1 let paddedHeightRelative = 1, paddedWidthRelative = 1
let imageDimensions: Dimensions | undefined
const { const {
boxes: _boxes, boxes: _boxes,
...@@ -51,6 +53,7 @@ export function faceDetectionNet(weights: Float32Array) { ...@@ -51,6 +53,7 @@ export function faceDetectionNet(weights: Float32Array) {
let imgTensor = getImageTensor(input) let imgTensor = getImageTensor(input)
const [height, width] = imgTensor.shape.slice(1) const [height, width] = imgTensor.shape.slice(1)
imageDimensions = { width, height }
imgTensor = padToSquare(imgTensor) imgTensor = padToSquare(imgTensor)
paddedHeightRelative = imgTensor.shape[1] / height paddedHeightRelative = imgTensor.shape[1] / height
...@@ -80,13 +83,26 @@ export function faceDetectionNet(weights: Float32Array) { ...@@ -80,13 +83,26 @@ export function faceDetectionNet(weights: Float32Array) {
) )
const results = indices const results = indices
.map(idx => new FaceDetectionResult( .map(idx => {
scoresData[idx], const [top, bottom] = [
boxes.get(idx, 0) * paddedHeightRelative, Math.max(0, boxes.get(idx, 0)),
boxes.get(idx, 1) * paddedWidthRelative, Math.min(1.0, boxes.get(idx, 2))
boxes.get(idx, 2) * paddedHeightRelative, ].map(val => val * paddedHeightRelative)
boxes.get(idx, 3) * paddedWidthRelative const [left, right] = [
)) Math.max(0, boxes.get(idx, 1)),
Math.min(1.0, boxes.get(idx, 3))
].map(val => val * paddedWidthRelative)
return new FaceDetection(
scoresData[idx],
new Rect(
left,
top,
right - left,
bottom - top
),
imageDimensions as Dimensions
)
})
boxes.dispose() boxes.dispose()
scores.dispose() scores.dispose()
......
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { ConvParams } from '../commons/types';
export namespace FaceDetectionNet { export namespace FaceDetectionNet {
export type PointwiseConvParams = { export type PointwiseConvParams = {
...@@ -29,14 +31,9 @@ export namespace FaceDetectionNet { ...@@ -29,14 +31,9 @@ export namespace FaceDetectionNet {
} }
export type ConvWithBiasParams = {
filters: tf.Tensor4D
bias: tf.Tensor1D
}
export type BoxPredictionParams = { export type BoxPredictionParams = {
box_encoding_predictor_params: ConvWithBiasParams box_encoding_predictor_params: ConvParams
class_predictor_params: ConvWithBiasParams class_predictor_params: ConvParams
} }
export type PredictionLayerParams = { export type PredictionLayerParams = {
...@@ -65,15 +62,4 @@ export namespace FaceDetectionNet { ...@@ -65,15 +62,4 @@ export namespace FaceDetectionNet {
prediction_layer_params: PredictionLayerParams, prediction_layer_params: PredictionLayerParams,
output_layer_params: OutputLayerParams output_layer_params: OutputLayerParams
} }
export type Detection = {
score: number
box: {
x: number,
y: number,
width: number,
height: number
}
}
} }
import { Point, IPoint } from '../Point';
import { Dimensions } from '../types';
export class FaceLandmarks {
private _faceLandmarks: Point[]
private _imageWidth: number
private _imageHeight: number
private _shift: Point
constructor(
relativeFaceLandmarkPositions: Point[],
imageDims: Dimensions,
shift: Point = new Point(0, 0)
) {
const { width, height } = imageDims
this._imageWidth = width
this._imageHeight = height
this._shift = shift
this._faceLandmarks = relativeFaceLandmarkPositions.map(
pt => pt.mul(new Point(width, height)).add(shift)
)
}
public getPositions() {
return this._faceLandmarks
}
public getRelativePositions() {
return this._faceLandmarks.map(
pt => pt.sub(this._shift).div(new Point(this._imageWidth, this._imageHeight))
)
}
public getJawOutline() {
return this._faceLandmarks.slice(0, 17)
}
public getLeftEyeBrow() {
return this._faceLandmarks.slice(17, 22)
}
public getRightEyeBrow() {
return this._faceLandmarks.slice(22, 27)
}
public getNose() {
return this._faceLandmarks.slice(27, 36)
}
public getLeftEye() {
return this._faceLandmarks.slice(36, 42)
}
public getRightEye() {
return this._faceLandmarks.slice(42, 48)
}
public getMouth() {
return this._faceLandmarks.slice(48, 68)
}
public forSize(width: number, height: number): FaceLandmarks {
return new FaceLandmarks(
this.getRelativePositions(),
{ width, height }
)
}
public shift(x: number, y: number): FaceLandmarks {
return new FaceLandmarks(
this.getRelativePositions(),
{ width: this._imageWidth, height: this._imageHeight },
new Point(x, y)
)
}
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { extractConvParamsFactory } from '../commons/extractConvParamsFactory';
import { extractWeightsFactory } from '../commons/extractWeightsFactory';
import { FaceLandmarkNet } from './types';
export function extractParams(weights: Float32Array): FaceLandmarkNet.NetParams {
const {
extractWeights,
getRemainingWeights
} = extractWeightsFactory(weights)
const extractConvParams = extractConvParamsFactory(extractWeights)
function extractFcParams(channelsIn: number, channelsOut: number,): FaceLandmarkNet.FCParams {
const fc_weights = tf.tensor2d(extractWeights(channelsIn * channelsOut), [channelsIn, channelsOut])
const fc_bias = tf.tensor1d(extractWeights(channelsOut))
return {
weights: fc_weights,
bias: fc_bias
}
}
const conv0_params = extractConvParams(3, 32, 3)
const conv1_params = extractConvParams(32, 64, 3)
const conv2_params = extractConvParams(64, 64, 3)
const conv3_params = extractConvParams(64, 64, 3)
const conv4_params = extractConvParams(64, 64, 3)
const conv5_params = extractConvParams(64, 128, 3)
const conv6_params = extractConvParams(128, 128, 3)
const conv7_params = extractConvParams(128, 256, 3)
const fc0_params = extractFcParams(6400, 1024)
const fc1_params = extractFcParams(1024, 136)
if (getRemainingWeights().length !== 0) {
throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`)
}
return {
conv0_params,
conv1_params,
conv2_params,
conv3_params,
conv4_params,
conv5_params,
conv6_params,
conv7_params,
fc0_params,
fc1_params
}
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { FaceLandmarkNet } from './types';
export function fullyConnectedLayer(
x: tf.Tensor2D,
params: FaceLandmarkNet.FCParams
): tf.Tensor2D {
return tf.tidy(() =>
tf.add(
tf.matMul(x, params.weights),
params.bias
)
)
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { convLayer } from '../commons/convLayer';
import { ConvParams } from '../commons/types';
import { getImageTensor } from '../getImageTensor';
import { NetInput } from '../NetInput';
import { Point } from '../Point';
import { Dimensions, TNetInput } from '../types';
import { extractParams } from './extractParams';
import { FaceLandmarks } from './FaceLandmarks';
import { fullyConnectedLayer } from './fullyConnectedLayer';
function conv(x: tf.Tensor4D, params: ConvParams): tf.Tensor4D {
return convLayer(x, params, 'valid', true)
}
function maxPool(x: tf.Tensor4D, strides: [number, number] = [2, 2]): tf.Tensor4D {
return tf.maxPool(x, [2, 2], strides, 'valid')
}
export function faceLandmarkNet(weights: Float32Array) {
const params = extractParams(weights)
async function detectLandmarks(input: tf.Tensor | NetInput | TNetInput) {
let imageDimensions: Dimensions | undefined
const outTensor = tf.tidy(() => {
let imgTensor = getImageTensor(input)
const [height, width] = imgTensor.shape.slice(1)
imageDimensions = { width, height }
// work with 128 x 128 sized face images
if (imgTensor.shape[1] !== 128 || imgTensor.shape[2] !== 128) {
imgTensor = tf.image.resizeBilinear(imgTensor, [128, 128])
}
let out = conv(imgTensor, params.conv0_params)
out = maxPool(out)
out = conv(out, params.conv1_params)
out = conv(out, params.conv2_params)
out = maxPool(out)
out = conv(out, params.conv3_params)
out = conv(out, params.conv4_params)
out = maxPool(out)
out = conv(out, params.conv5_params)
out = conv(out, params.conv6_params)
out = maxPool(out, [1, 1])
out = conv(out, params.conv7_params)
const fc0 = tf.relu(fullyConnectedLayer(out.as2D(out.shape[0], -1), params.fc0_params))
const fc1 = fullyConnectedLayer(fc0, params.fc1_params)
return fc1
})
const faceLandmarksArray = Array.from(await outTensor.data())
outTensor.dispose()
const xCoords = faceLandmarksArray.filter((c, i) => (i - 1) % 2)
const yCoords = faceLandmarksArray.filter((c, i) => i % 2)
return new FaceLandmarks(
Array(68).fill(0).map((_, i) => new Point(xCoords[i], yCoords[i])),
imageDimensions as Dimensions
)
}
return {
detectLandmarks
}
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { ConvParams } from '../commons/types';
export namespace FaceLandmarkNet {
export type FCParams = {
weights: tf.Tensor2D
bias: tf.Tensor1D
}
export type NetParams = {
conv0_params: ConvParams
conv1_params: ConvParams
conv2_params: ConvParams
conv3_params: ConvParams
conv4_params: ConvParams
conv5_params: ConvParams
conv6_params: ConvParams
conv7_params: ConvParams
fc0_params: FCParams
fc1_params: FCParams
}
}
\ No newline at end of file
...@@ -7,26 +7,26 @@ import { FaceRecognitionNet } from './types'; ...@@ -7,26 +7,26 @@ import { FaceRecognitionNet } from './types';
function convLayer( function convLayer(
x: tf.Tensor4D, x: tf.Tensor4D,
params: FaceRecognitionNet.ConvLayerParams, params: FaceRecognitionNet.ConvLayerParams,
stride: number, strides: [number, number],
withRelu: boolean, withRelu: boolean,
padding: 'valid' | 'same' = 'same' padding: 'valid' | 'same' = 'same'
): tf.Tensor4D { ): tf.Tensor4D {
const { filters, biases } = params.conv const { filters, bias } = params.conv
let out = tf.conv2d(x, filters, [stride, stride], padding) let out = tf.conv2d(x, filters, strides, padding)
out = tf.add(out, biases) out = tf.add(out, bias)
out = scale(out, params.scale) out = scale(out, params.scale)
return withRelu ? tf.relu(out) : out return withRelu ? tf.relu(out) : out
} }
export function conv(x: tf.Tensor4D, params: FaceRecognitionNet.ConvLayerParams) { export function conv(x: tf.Tensor4D, params: FaceRecognitionNet.ConvLayerParams) {
return convLayer(x, params, 1, true) return convLayer(x, params, [1, 1], true)
} }
export function convNoRelu(x: tf.Tensor4D, params: FaceRecognitionNet.ConvLayerParams) { export function convNoRelu(x: tf.Tensor4D, params: FaceRecognitionNet.ConvLayerParams) {
return convLayer(x, params, 1, false) return convLayer(x, params, [1, 1], false)
} }
export function convDown(x: tf.Tensor4D, params: FaceRecognitionNet.ConvLayerParams) { export function convDown(x: tf.Tensor4D, params: FaceRecognitionNet.ConvLayerParams) {
return convLayer(x, params, 2, true, 'valid') return convLayer(x, params, [2, 2], true, 'valid')
} }
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { extractWeightsFactory } from '../commons/extractWeightsFactory';
import { ExtractWeightsFunction } from '../commons/types';
import { isFloat } from '../utils'; import { isFloat } from '../utils';
import { FaceRecognitionNet } from './types'; import { FaceRecognitionNet } from './types';
function extractorsFactory(extractWeights: (numWeights: number) => Float32Array) { function extractorsFactory(extractWeights: ExtractWeightsFunction) {
function extractFilterValues(numFilterValues: number, numFilters: number, filterSize: number): tf.Tensor4D { function extractFilterValues(numFilterValues: number, numFilters: number, filterSize: number): tf.Tensor4D {
const weights = extractWeights(numFilterValues) const weights = extractWeights(numFilterValues)
const depth = weights.length / (numFilters * filterSize * filterSize) const depth = weights.length / (numFilters * filterSize * filterSize)
if (isFloat(depth)) { if (isFloat(depth)) {
throw new Error(`depth has to be an integer: ${depth}, weights.length: ${weights.length}, numFilters: ${numFilters}, filterSize: ${filterSize}`) throw new Error(`depth has to be an integer: ${depth}, weights.length: ${weights.length}, numFilters: ${numFilters}, filterSize: ${filterSize}`)
} }
...@@ -29,15 +30,19 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array) ...@@ -29,15 +30,19 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array)
} }
} }
function extractConvLayerParams(numFilterValues: number, numFilters: number, filterSize: number): FaceRecognitionNet.ConvLayerParams { function extractConvLayerParams(
numFilterValues: number,
numFilters: number,
filterSize: number
): FaceRecognitionNet.ConvLayerParams {
const conv_filters = extractFilterValues(numFilterValues, numFilters, filterSize) const conv_filters = extractFilterValues(numFilterValues, numFilters, filterSize)
const conv_biases = tf.tensor1d(extractWeights(numFilters)) const conv_bias = tf.tensor1d(extractWeights(numFilters))
const scale = extractScaleLayerParams(numFilters) const scale = extractScaleLayerParams(numFilters)
return { return {
conv: { conv: {
filters: conv_filters, filters: conv_filters,
biases: conv_biases bias: conv_bias
}, },
scale scale
} }
...@@ -61,11 +66,10 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array) ...@@ -61,11 +66,10 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array)
} }
export function extractParams(weights: Float32Array): FaceRecognitionNet.NetParams { export function extractParams(weights: Float32Array): FaceRecognitionNet.NetParams {
const extractWeights = (numWeights: number): Float32Array => { const {
const ret = weights.slice(0, numWeights) extractWeights,
weights = weights.slice(numWeights) getRemainingWeights
return ret } = extractWeightsFactory(weights)
}
const { const {
extractConvLayerParams, extractConvLayerParams,
...@@ -93,8 +97,8 @@ export function extractParams(weights: Float32Array): FaceRecognitionNet.NetPara ...@@ -93,8 +97,8 @@ export function extractParams(weights: Float32Array): FaceRecognitionNet.NetPara
const fc = tf.transpose(tf.tensor2d(extractWeights(256 * 128), [128, 256]), [1, 0]) const fc = tf.transpose(tf.tensor2d(extractWeights(256 * 128), [128, 256]), [1, 0])
if (weights.length !== 0) { if (getRemainingWeights().length !== 0) {
throw new Error(`weights remaing after extract: ${weights.length}`) throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`)
} }
return { return {
......
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { ConvParams } from '../commons/types';
export namespace FaceRecognitionNet { export namespace FaceRecognitionNet {
export type ScaleLayerParams = { export type ScaleLayerParams = {
...@@ -11,11 +13,6 @@ export namespace FaceRecognitionNet { ...@@ -11,11 +13,6 @@ export namespace FaceRecognitionNet {
conv2: ConvLayerParams conv2: ConvLayerParams
} }
export type ConvParams = {
filters: tf.Tensor4D
biases: tf.Tensor1D
}
export type ConvLayerParams = { export type ConvLayerParams = {
conv: ConvParams conv: ConvParams
scale: ScaleLayerParams scale: ScaleLayerParams
......
...@@ -2,6 +2,7 @@ import * as tf from '@tensorflow/tfjs-core'; ...@@ -2,6 +2,7 @@ import * as tf from '@tensorflow/tfjs-core';
import { euclideanDistance } from './euclideanDistance'; import { euclideanDistance } from './euclideanDistance';
import { faceDetectionNet } from './faceDetectionNet'; import { faceDetectionNet } from './faceDetectionNet';
import { faceLandmarkNet } from './faceLandmarkNet';
import { faceRecognitionNet } from './faceRecognitionNet'; import { faceRecognitionNet } from './faceRecognitionNet';
import { NetInput } from './NetInput'; import { NetInput } from './NetInput';
import { padToSquare } from './padToSquare'; import { padToSquare } from './padToSquare';
...@@ -9,6 +10,7 @@ import { padToSquare } from './padToSquare'; ...@@ -9,6 +10,7 @@ import { padToSquare } from './padToSquare';
export { export {
euclideanDistance, euclideanDistance,
faceDetectionNet, faceDetectionNet,
faceLandmarkNet,
faceRecognitionNet, faceRecognitionNet,
NetInput, NetInput,
tf, tf,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment