Unverified Commit f7c90389 by justadudewhohacks Committed by GitHub

Merge pull request #2 from justadudewhohacks/ssd_mobilenet_facedetector

Ssd mobilenet facedetector
parents 0387fd20 b5463d66
import { Dimensions, TNetInput } from './types';
export declare class NetInput {
private _canvases;
constructor(mediaArg: TNetInput, dims?: Dimensions);
private initCanvas(media, dims?);
readonly canvases: HTMLCanvasElement[];
readonly width: number;
readonly height: number;
readonly dims: Dimensions | null;
}
import { getContext2dOrThrow, getElement, getMediaDimensions } from './utils';
var NetInput = /** @class */ (function () {
function NetInput(mediaArg, dims) {
var _this = this;
var mediaArgArray = Array.isArray(mediaArg)
? mediaArg
: [mediaArg];
if (!mediaArgArray.length) {
throw new Error('NetInput - empty array passed as input');
}
var medias = mediaArgArray.map(getElement);
medias.forEach(function (media, i) {
if (!(media instanceof HTMLImageElement || media instanceof HTMLVideoElement || media instanceof HTMLCanvasElement)) {
var idxHint = Array.isArray(mediaArg) ? " at input index " + i + ":" : '';
if (typeof mediaArgArray[i] === 'string') {
throw new Error("NetInput -" + idxHint + " string passed, but could not resolve HTMLElement for element id");
}
throw new Error("NetInput -" + idxHint + " expected media to be of type HTMLImageElement | HTMLVideoElement | HTMLCanvasElement, or to be an element id");
}
});
this._canvases = [];
medias.forEach(function (m) { return _this.initCanvas(m, dims); });
}
NetInput.prototype.initCanvas = function (media, dims) {
if (media instanceof HTMLCanvasElement) {
this._canvases.push(media);
return;
}
// 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 canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
getContext2dOrThrow(canvas).drawImage(media, 0, 0, width, height);
this._canvases.push(canvas);
};
Object.defineProperty(NetInput.prototype, "canvases", {
get: function () {
return this._canvases;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NetInput.prototype, "width", {
get: function () {
return (this._canvases[0] || {}).width;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NetInput.prototype, "height", {
get: function () {
return (this._canvases[0] || {}).height;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NetInput.prototype, "dims", {
get: function () {
var _a = this, width = _a.width, height = _a.height;
return (width > 0 && height > 0) ? { width: width, height: height } : null;
},
enumerable: true,
configurable: true
});
return NetInput;
}());
export { NetInput };
//# sourceMappingURL=NetInput.js.map
\ No newline at end of file
{"version":3,"file":"NetInput.js","sourceRoot":"","sources":["../src/NetInput.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE9E;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,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;QAC/C,MAAM,CAAC,KAAK,GAAG,KAAK,CAAA;QACpB,MAAM,CAAC,MAAM,GAAG,MAAM,CAAA;QAEtB,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,AAjED,IAiEC"}
\ 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 { FaceDetectionNet } from './types';
export declare class FaceDetectionResult {
private score;
private top;
private left;
private bottom;
private right;
constructor(score: number, top: number, left: number, bottom: number, right: number);
forSize(width: number, height: number): FaceDetectionNet.Detection;
}
var FaceDetectionResult = /** @class */ (function () {
function FaceDetectionResult(score, top, left, bottom, right) {
this.score = score;
this.top = Math.max(0, top),
this.left = Math.max(0, left),
this.bottom = Math.min(1.0, bottom),
this.right = Math.min(1.0, right);
}
FaceDetectionResult.prototype.forSize = function (width, height) {
return {
score: this.score,
box: {
top: this.top * height,
left: this.left * width,
bottom: this.bottom * height,
right: this.right * width
}
};
};
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,GAAW,EACX,IAAY,EACZ,MAAc,EACd,KAAa;QAEb,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC;YAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC;YAC7B,IAAI,CAAC,MAAM,GAAI,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC;YACpC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACnC,CAAC;IAEM,qCAAO,GAAd,UAAe,KAAa,EAAE,MAAc;QAC1C,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,GAAG,EAAE;gBACH,GAAG,EAAE,IAAI,CAAC,GAAG,GAAG,MAAM;gBACtB,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,KAAK;gBACvB,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM;gBAC5B,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,KAAK;aAC1B;SACF,CAAA;IACH,CAAC;IACH,0BAAC;AAAD,CAAC,AAhCD,IAgCC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { FaceDetectionNet } from './types';
export declare function boxPredictionLayer(x: tf.Tensor4D, params: FaceDetectionNet.BoxPredictionParams): {
boxPredictionEncoding: tf.Tensor<tf.Rank>;
classPrediction: tf.Tensor<tf.Rank>;
};
import * as tf from '@tensorflow/tfjs-core';
function convWithBias(x, params) {
return tf.tidy(function () {
return tf.add(tf.conv2d(x, params.filters, [1, 1], 'same'), params.bias);
});
}
export function boxPredictionLayer(x, params) {
return tf.tidy(function () {
var batchSize = x.shape[0];
var boxPredictionEncoding = tf.reshape(convWithBias(x, params.box_encoding_predictor_params), [batchSize, -1, 1, 4]);
var classPrediction = tf.reshape(convWithBias(x, params.class_predictor_params), [batchSize, -1, 3]);
return {
boxPredictionEncoding: boxPredictionEncoding,
classPrediction: classPrediction
};
});
}
//# sourceMappingURL=boxPredictionLayer.js.map
\ No newline at end of file
{"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"}
\ No newline at end of file
import { FaceDetectionNet } from './types';
export declare function extractParams(weights: Float32Array): FaceDetectionNet.NetParams;
import * as tf from '@tensorflow/tfjs-core';
function extractorsFactory(extractWeights) {
function extractDepthwiseConvParams(numChannels) {
var filters = tf.tensor4d(extractWeights(3 * 3 * numChannels), [3, 3, numChannels, 1]);
var batch_norm_scale = tf.tensor1d(extractWeights(numChannels));
var batch_norm_offset = tf.tensor1d(extractWeights(numChannels));
var batch_norm_mean = tf.tensor1d(extractWeights(numChannels));
var batch_norm_variance = tf.tensor1d(extractWeights(numChannels));
return {
filters: filters,
batch_norm_scale: batch_norm_scale,
batch_norm_offset: batch_norm_offset,
batch_norm_mean: batch_norm_mean,
batch_norm_variance: batch_norm_variance
};
}
function extractConvWithBiasParams(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
};
}
function extractPointwiseConvParams(channelsIn, channelsOut, filterSize) {
var _a = extractConvWithBiasParams(channelsIn, channelsOut, filterSize), filters = _a.filters, bias = _a.bias;
return {
filters: filters,
batch_norm_offset: bias
};
}
function extractConvPairParams(channelsIn, channelsOut) {
var depthwise_conv_params = extractDepthwiseConvParams(channelsIn);
var pointwise_conv_params = extractPointwiseConvParams(channelsIn, channelsOut, 1);
return {
depthwise_conv_params: depthwise_conv_params,
pointwise_conv_params: pointwise_conv_params
};
}
function extractMobilenetV1Params() {
var conv_0_params = extractPointwiseConvParams(3, 32, 3);
var channelNumPairs = [
[32, 64],
[64, 128],
[128, 128],
[128, 256],
[256, 256],
[256, 512],
[512, 512],
[512, 512],
[512, 512],
[512, 512],
[512, 512],
[512, 1024],
[1024, 1024]
];
var conv_pair_params = channelNumPairs.map(function (_a) {
var channelsIn = _a[0], channelsOut = _a[1];
return extractConvPairParams(channelsIn, channelsOut);
});
return {
conv_0_params: conv_0_params,
conv_pair_params: conv_pair_params
};
}
function extractPredictionLayerParams() {
var conv_0_params = extractPointwiseConvParams(1024, 256, 1);
var conv_1_params = extractPointwiseConvParams(256, 512, 3);
var conv_2_params = extractPointwiseConvParams(512, 128, 1);
var conv_3_params = extractPointwiseConvParams(128, 256, 3);
var conv_4_params = extractPointwiseConvParams(256, 128, 1);
var conv_5_params = extractPointwiseConvParams(128, 256, 3);
var conv_6_params = extractPointwiseConvParams(256, 64, 1);
var conv_7_params = extractPointwiseConvParams(64, 128, 3);
var box_encoding_0_predictor_params = extractConvWithBiasParams(512, 12, 1);
var class_predictor_0_params = extractConvWithBiasParams(512, 9, 1);
var box_encoding_1_predictor_params = extractConvWithBiasParams(1024, 24, 1);
var class_predictor_1_params = extractConvWithBiasParams(1024, 18, 1);
var box_encoding_2_predictor_params = extractConvWithBiasParams(512, 24, 1);
var class_predictor_2_params = extractConvWithBiasParams(512, 18, 1);
var box_encoding_3_predictor_params = extractConvWithBiasParams(256, 24, 1);
var class_predictor_3_params = extractConvWithBiasParams(256, 18, 1);
var box_encoding_4_predictor_params = extractConvWithBiasParams(256, 24, 1);
var class_predictor_4_params = extractConvWithBiasParams(256, 18, 1);
var box_encoding_5_predictor_params = extractConvWithBiasParams(128, 24, 1);
var class_predictor_5_params = extractConvWithBiasParams(128, 18, 1);
var box_predictor_0_params = {
box_encoding_predictor_params: box_encoding_0_predictor_params,
class_predictor_params: class_predictor_0_params
};
var box_predictor_1_params = {
box_encoding_predictor_params: box_encoding_1_predictor_params,
class_predictor_params: class_predictor_1_params
};
var box_predictor_2_params = {
box_encoding_predictor_params: box_encoding_2_predictor_params,
class_predictor_params: class_predictor_2_params
};
var box_predictor_3_params = {
box_encoding_predictor_params: box_encoding_3_predictor_params,
class_predictor_params: class_predictor_3_params
};
var box_predictor_4_params = {
box_encoding_predictor_params: box_encoding_4_predictor_params,
class_predictor_params: class_predictor_4_params
};
var box_predictor_5_params = {
box_encoding_predictor_params: box_encoding_5_predictor_params,
class_predictor_params: class_predictor_5_params
};
return {
conv_0_params: conv_0_params,
conv_1_params: conv_1_params,
conv_2_params: conv_2_params,
conv_3_params: conv_3_params,
conv_4_params: conv_4_params,
conv_5_params: conv_5_params,
conv_6_params: conv_6_params,
conv_7_params: conv_7_params,
box_predictor_0_params: box_predictor_0_params,
box_predictor_1_params: box_predictor_1_params,
box_predictor_2_params: box_predictor_2_params,
box_predictor_3_params: box_predictor_3_params,
box_predictor_4_params: box_predictor_4_params,
box_predictor_5_params: box_predictor_5_params
};
}
return {
extractMobilenetV1Params: extractMobilenetV1Params,
extractPredictionLayerParams: extractPredictionLayerParams
};
}
export function extractParams(weights) {
var extractWeights = function (numWeights) {
var ret = weights.slice(0, numWeights);
weights = weights.slice(numWeights);
return ret;
};
var _a = extractorsFactory(extractWeights), extractMobilenetV1Params = _a.extractMobilenetV1Params, extractPredictionLayerParams = _a.extractPredictionLayerParams;
var mobilenetv1_params = extractMobilenetV1Params();
var prediction_layer_params = extractPredictionLayerParams();
var extra_dim = tf.tensor3d(extractWeights(5118 * 4), [1, 5118, 4]);
var output_layer_params = {
extra_dim: extra_dim
};
if (weights.length !== 0) {
throw new Error("weights remaing after extract: " + weights.length);
}
return {
mobilenetv1_params: mobilenetv1_params,
prediction_layer_params: prediction_layer_params,
output_layer_params: output_layer_params
};
}
//# sourceMappingURL=extractParams.js.map
\ No newline at end of file
{"version":3,"file":"extractParams.js","sourceRoot":"","sources":["../../src/faceDetectionNet/extractParams.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { NetInput } from '../NetInput';
import { FaceDetectionResult } from './FaceDetectionResult';
export declare function faceDetectionNet(weights: Float32Array): {
forward: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | tf.Tensor<tf.Rank> | NetInput) => {
boxes: tf.Tensor<tf.Rank.R2>[];
scores: tf.Tensor<tf.Rank.R1>[];
};
locateFaces: (input: tf.Tensor<tf.Rank> | NetInput, minConfidence?: number, maxResults?: number) => Promise<FaceDetectionResult[]>;
};
import * as tslib_1 from "tslib";
import * as tf from '@tensorflow/tfjs-core';
import { getImageTensor, padToSquare } from '../transformInputs';
import { extractParams } from './extractParams';
import { FaceDetectionResult } from './FaceDetectionResult';
import { mobileNetV1 } from './mobileNetV1';
import { nonMaxSuppression } from './nonMaxSuppression';
import { outputLayer } from './outputLayer';
import { predictionLayer } from './predictionLayer';
import { resizeLayer } from './resizeLayer';
export function faceDetectionNet(weights) {
var params = extractParams(weights);
function forwardTensor(imgTensor) {
return tf.tidy(function () {
var resized = resizeLayer(imgTensor);
var features = mobileNetV1(resized, params.mobilenetv1_params);
var _a = predictionLayer(features.out, features.conv11, params.prediction_layer_params), boxPredictions = _a.boxPredictions, classPredictions = _a.classPredictions;
return outputLayer(boxPredictions, classPredictions, params.output_layer_params);
});
}
function forward(input) {
return tf.tidy(function () { return forwardTensor(padToSquare(getImageTensor(input))); });
}
function locateFaces(input, minConfidence, maxResults) {
if (minConfidence === void 0) { minConfidence = 0.8; }
if (maxResults === void 0) { maxResults = 100; }
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;
return tslib_1.__generator(this, function (_d) {
switch (_d.label) {
case 0:
paddedHeightRelative = 1, paddedWidthRelative = 1;
_a = tf.tidy(function () {
var imgTensor = getImageTensor(input);
var _a = imgTensor.shape, _ = _a[0], height = _a[1], width = _a[2];
imgTensor = padToSquare(imgTensor);
paddedHeightRelative = imgTensor.shape[1] / height;
paddedWidthRelative = imgTensor.shape[2] / width;
return forwardTensor(imgTensor);
}), _boxes = _a.boxes, _scores = _a.scores;
boxes = _boxes[0];
scores = _scores[0];
for (i = 1; i < _boxes.length; i++) {
_boxes[i].dispose();
_scores[i].dispose();
}
_c = (_b = Array).from;
return [4 /*yield*/, scores.data()];
case 1:
scoresData = _c.apply(_b, [_d.sent()]);
iouThreshold = 0.5;
indices = nonMaxSuppression(boxes, scoresData, maxResults, iouThreshold, minConfidence);
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); });
boxes.dispose();
scores.dispose();
return [2 /*return*/, results];
}
});
});
}
return {
forward: forward,
locateFaces: locateFaces
};
}
//# sourceMappingURL=index.js.map
\ No newline at end of file
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/faceDetectionNet/index.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { FaceDetectionNet } from './types';
export declare function mobileNetV1(x: tf.Tensor4D, params: FaceDetectionNet.MobileNetV1.Params): {
out: tf.Tensor<tf.Rank.R4>;
conv11: any;
};
import * as tf from '@tensorflow/tfjs-core';
import { pointwiseConvLayer } from './pointwiseConvLayer';
var epsilon = 0.0010000000474974513;
function depthwiseConvLayer(x, params, strides) {
return tf.tidy(function () {
var out = tf.depthwiseConv2d(x, params.filters, strides, 'same');
out = tf.batchNormalization(out, params.batch_norm_mean, params.batch_norm_variance, epsilon, params.batch_norm_scale, params.batch_norm_offset);
return tf.clipByValue(out, 0, 6);
});
}
function getStridesForLayerIdx(layerIdx) {
return [2, 4, 6, 12].some(function (idx) { return idx === layerIdx; }) ? [2, 2] : [1, 1];
}
export function mobileNetV1(x, params) {
return tf.tidy(function () {
var conv11 = null;
var out = pointwiseConvLayer(x, params.conv_0_params, [2, 2]);
params.conv_pair_params.forEach(function (param, i) {
var layerIdx = i + 1;
var depthwiseConvStrides = getStridesForLayerIdx(layerIdx);
out = depthwiseConvLayer(out, param.depthwise_conv_params, depthwiseConvStrides);
out = pointwiseConvLayer(out, param.pointwise_conv_params, [1, 1]);
if (layerIdx === 11) {
conv11 = out;
}
});
if (conv11 === null) {
throw new Error('mobileNetV1 - output of conv layer 11 is null');
}
return {
out: out,
conv11: conv11
};
});
}
//# sourceMappingURL=mobileNetV1.js.map
\ No newline at end of file
{"version":3,"file":"mobileNetV1.js","sourceRoot":"","sources":["../../src/faceDetectionNet/mobileNetV1.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,IAAM,OAAO,GAAG,qBAAqB,CAAA;AAErC,4BACE,CAAc,EACd,MAAwD,EACxD,OAAyB;IAEzB,OAAO,EAAE,CAAC,IAAI,CAAC;QAEb,IAAI,GAAG,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;QAChE,GAAG,GAAG,EAAE,CAAC,kBAAkB,CACzB,GAAG,EACH,MAAM,CAAC,eAAe,EACtB,MAAM,CAAC,mBAAmB,EAC1B,OAAO,EACP,MAAM,CAAC,gBAAgB,EACvB,MAAM,CAAC,iBAAiB,CACzB,CAAA;QACD,OAAO,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IAElC,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,+BAA+B,QAAgB;IAC7C,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,UAAA,GAAG,IAAI,OAAA,GAAG,KAAK,QAAQ,EAAhB,CAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AACtE,CAAC;AAED,MAAM,sBAAsB,CAAc,EAAE,MAA2C;IACrF,OAAO,EAAE,CAAC,IAAI,CAAC;QAEb,IAAI,MAAM,GAAG,IAAI,CAAA;QACjB,IAAI,GAAG,GAAG,kBAAkB,CAAC,CAAC,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QAE7D,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,UAAC,KAAK,EAAE,CAAC;YACvC,IAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAA;YACtB,IAAM,oBAAoB,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAA;YAC5D,GAAG,GAAG,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,qBAAqB,EAAE,oBAAoB,CAAC,CAAA;YAChF,GAAG,GAAG,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,qBAAqB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YAClE,IAAI,QAAQ,KAAK,EAAE,EAAE;gBACnB,MAAM,GAAG,GAAG,CAAA;aACb;QACH,CAAC,CAAC,CAAA;QAEF,IAAI,MAAM,KAAK,IAAI,EAAE;YACnB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;SACjE;QAED,OAAO;YACL,GAAG,KAAA;YACH,MAAM,EAAE,MAAa;SACtB,CAAA;IAEH,CAAC,CAAC,CAAA;AACJ,CAAC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
export declare function nonMaxSuppression(boxes: tf.Tensor2D, scores: number[], maxOutputSize: number, iouThreshold: number, scoreThreshold: number): number[];
export function nonMaxSuppression(boxes, scores, maxOutputSize, iouThreshold, scoreThreshold) {
var numBoxes = boxes.shape[0];
var outputSize = Math.min(maxOutputSize, numBoxes);
var candidates = scores
.map(function (score, boxIndex) { return ({ score: score, boxIndex: boxIndex }); })
.filter(function (c) { return c.score > scoreThreshold; })
.sort(function (c1, c2) { return c2.score - c1.score; });
var suppressFunc = function (x) { return x <= iouThreshold ? 1 : 0; };
var selected = [];
candidates.forEach(function (c) {
if (selected.length >= outputSize) {
return;
}
var originalScore = c.score;
for (var j = selected.length - 1; j >= 0; --j) {
var iou = IOU(boxes, c.boxIndex, selected[j]);
if (iou === 0.0) {
continue;
}
c.score *= suppressFunc(iou);
if (c.score <= scoreThreshold) {
break;
}
}
if (originalScore === c.score) {
selected.push(c.boxIndex);
}
});
return selected;
}
function IOU(boxes, i, j) {
var yminI = Math.min(boxes.get(i, 0), boxes.get(i, 2));
var xminI = Math.min(boxes.get(i, 1), boxes.get(i, 3));
var ymaxI = Math.max(boxes.get(i, 0), boxes.get(i, 2));
var xmaxI = Math.max(boxes.get(i, 1), boxes.get(i, 3));
var yminJ = Math.min(boxes.get(j, 0), boxes.get(j, 2));
var xminJ = Math.min(boxes.get(j, 1), boxes.get(j, 3));
var ymaxJ = Math.max(boxes.get(j, 0), boxes.get(j, 2));
var xmaxJ = Math.max(boxes.get(j, 1), boxes.get(j, 3));
var areaI = (ymaxI - yminI) * (xmaxI - xminI);
var areaJ = (ymaxJ - yminJ) * (xmaxJ - xminJ);
if (areaI <= 0 || areaJ <= 0) {
return 0.0;
}
var intersectionYmin = Math.max(yminI, yminJ);
var intersectionXmin = Math.max(xminI, xminJ);
var intersectionYmax = Math.min(ymaxI, ymaxJ);
var intersectionXmax = Math.min(xmaxI, xmaxJ);
var intersectionArea = Math.max(intersectionYmax - intersectionYmin, 0.0) *
Math.max(intersectionXmax - intersectionXmin, 0.0);
return intersectionArea / (areaI + areaJ - intersectionArea);
}
//# sourceMappingURL=nonMaxSuppression.js.map
\ No newline at end of file
{"version":3,"file":"nonMaxSuppression.js","sourceRoot":"","sources":["../../src/faceDetectionNet/nonMaxSuppression.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { FaceDetectionNet } from './types';
export declare function outputLayer(boxPredictions: tf.Tensor4D, classPredictions: tf.Tensor4D, params: FaceDetectionNet.OutputLayerParams): {
boxes: tf.Tensor<tf.Rank.R2>[];
scores: tf.Tensor<tf.Rank.R1>[];
};
import * as tf from '@tensorflow/tfjs-core';
function getCenterCoordinatesAndSizesLayer(x) {
var vec = tf.unstack(tf.transpose(x, [1, 0]));
var sizes = [
tf.sub(vec[2], vec[0]),
tf.sub(vec[3], vec[1])
];
var centers = [
tf.add(vec[0], tf.div(sizes[0], tf.scalar(2))),
tf.add(vec[1], tf.div(sizes[1], tf.scalar(2)))
];
return {
sizes: sizes,
centers: centers
};
}
function decodeBoxesLayer(x0, x1) {
var _a = getCenterCoordinatesAndSizesLayer(x0), sizes = _a.sizes, centers = _a.centers;
var vec = tf.unstack(tf.transpose(x1, [1, 0]));
var div0_out = tf.div(tf.mul(tf.exp(tf.div(vec[2], tf.scalar(5))), sizes[0]), tf.scalar(2));
var add0_out = tf.add(tf.mul(tf.div(vec[0], tf.scalar(10)), sizes[0]), centers[0]);
var div1_out = tf.div(tf.mul(tf.exp(tf.div(vec[3], tf.scalar(5))), sizes[1]), tf.scalar(2));
var add1_out = tf.add(tf.mul(tf.div(vec[1], tf.scalar(10)), sizes[1]), centers[1]);
return tf.transpose(tf.stack([
tf.sub(add0_out, div0_out),
tf.sub(add1_out, div1_out),
tf.add(add0_out, div0_out),
tf.add(add1_out, div1_out)
]), [1, 0]);
}
export function outputLayer(boxPredictions, classPredictions, params) {
return tf.tidy(function () {
var batchSize = boxPredictions.shape[0];
var boxes = decodeBoxesLayer(tf.reshape(tf.tile(params.extra_dim, [batchSize, 1, 1]), [-1, 4]), tf.reshape(boxPredictions, [-1, 4]));
boxes = tf.reshape(boxes, [batchSize, (boxes.shape[0] / batchSize), 4]);
var scoresAndClasses = tf.sigmoid(tf.slice(classPredictions, [0, 0, 1], [-1, -1, -1]));
var scores = tf.slice(scoresAndClasses, [0, 0, 0], [-1, -1, 1]);
scores = tf.reshape(scores, [batchSize, scores.shape[1]]);
var boxesByBatch = tf.unstack(boxes);
var scoresByBatch = tf.unstack(scores);
return {
boxes: boxesByBatch,
scores: scoresByBatch
};
});
}
//# sourceMappingURL=outputLayer.js.map
\ No newline at end of file
{"version":3,"file":"outputLayer.js","sourceRoot":"","sources":["../../src/faceDetectionNet/outputLayer.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { FaceDetectionNet } from './types';
export declare function pointwiseConvLayer(x: tf.Tensor4D, params: FaceDetectionNet.PointwiseConvParams, strides: [number, number]): tf.Tensor<tf.Rank.R4>;
import * as tf from '@tensorflow/tfjs-core';
export function pointwiseConvLayer(x, params, strides) {
return tf.tidy(function () {
var out = tf.conv2d(x, params.filters, strides, 'same');
out = tf.add(out, params.batch_norm_offset);
return tf.clipByValue(out, 0, 6);
});
}
//# sourceMappingURL=pointwiseConvLayer.js.map
\ No newline at end of file
{"version":3,"file":"pointwiseConvLayer.js","sourceRoot":"","sources":["../../src/faceDetectionNet/pointwiseConvLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAI5C,MAAM,6BACJ,CAAc,EACd,MAA4C,EAC5C,OAAyB;IAEzB,OAAO,EAAE,CAAC,IAAI,CAAC;QAEb,IAAI,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;QACvD,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,iBAAiB,CAAC,CAAA;QAC3C,OAAO,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IAElC,CAAC,CAAC,CAAA;AACJ,CAAC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { FaceDetectionNet } from './types';
export declare function predictionLayer(x: tf.Tensor4D, conv11: tf.Tensor4D, params: FaceDetectionNet.PredictionLayerParams): {
boxPredictions: tf.Tensor<tf.Rank.R4>;
classPredictions: tf.Tensor<tf.Rank.R4>;
};
import * as tf from '@tensorflow/tfjs-core';
import { boxPredictionLayer } from './boxPredictionLayer';
import { pointwiseConvLayer } from './pointwiseConvLayer';
export function predictionLayer(x, conv11, params) {
return tf.tidy(function () {
var conv0 = pointwiseConvLayer(x, params.conv_0_params, [1, 1]);
var conv1 = pointwiseConvLayer(conv0, params.conv_1_params, [2, 2]);
var conv2 = pointwiseConvLayer(conv1, params.conv_2_params, [1, 1]);
var conv3 = pointwiseConvLayer(conv2, params.conv_3_params, [2, 2]);
var conv4 = pointwiseConvLayer(conv3, params.conv_4_params, [1, 1]);
var conv5 = pointwiseConvLayer(conv4, params.conv_5_params, [2, 2]);
var conv6 = pointwiseConvLayer(conv5, params.conv_6_params, [1, 1]);
var conv7 = pointwiseConvLayer(conv6, params.conv_7_params, [2, 2]);
var boxPrediction0 = boxPredictionLayer(conv11, params.box_predictor_0_params);
var boxPrediction1 = boxPredictionLayer(x, params.box_predictor_1_params);
var boxPrediction2 = boxPredictionLayer(conv1, params.box_predictor_2_params);
var boxPrediction3 = boxPredictionLayer(conv3, params.box_predictor_3_params);
var boxPrediction4 = boxPredictionLayer(conv5, params.box_predictor_4_params);
var boxPrediction5 = boxPredictionLayer(conv7, params.box_predictor_5_params);
var boxPredictions = tf.concat([
boxPrediction0.boxPredictionEncoding,
boxPrediction1.boxPredictionEncoding,
boxPrediction2.boxPredictionEncoding,
boxPrediction3.boxPredictionEncoding,
boxPrediction4.boxPredictionEncoding,
boxPrediction5.boxPredictionEncoding
], 1);
var classPredictions = tf.concat([
boxPrediction0.classPrediction,
boxPrediction1.classPrediction,
boxPrediction2.classPrediction,
boxPrediction3.classPrediction,
boxPrediction4.classPrediction,
boxPrediction5.classPrediction
], 1);
return {
boxPredictions: boxPredictions,
classPredictions: classPredictions
};
});
}
//# sourceMappingURL=predictionLayer.js.map
\ No newline at end of file
{"version":3,"file":"predictionLayer.js","sourceRoot":"","sources":["../../src/faceDetectionNet/predictionLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,MAAM,0BACJ,CAAc,EACd,MAAmB,EACnB,MAA8C;IAE9C,OAAO,EAAE,CAAC,IAAI,CAAC;QAEb,IAAM,KAAK,GAAG,kBAAkB,CAAC,CAAC,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACjE,IAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACrE,IAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACrE,IAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACrE,IAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACrE,IAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACrE,IAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACrE,IAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QAErE,IAAM,cAAc,GAAG,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,sBAAsB,CAAC,CAAA;QAChF,IAAM,cAAc,GAAG,kBAAkB,CAAC,CAAC,EAAE,MAAM,CAAC,sBAAsB,CAAC,CAAA;QAC3E,IAAM,cAAc,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,sBAAsB,CAAC,CAAA;QAC/E,IAAM,cAAc,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,sBAAsB,CAAC,CAAA;QAC/E,IAAM,cAAc,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,sBAAsB,CAAC,CAAA;QAC/E,IAAM,cAAc,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,sBAAsB,CAAC,CAAA;QAE/E,IAAM,cAAc,GAAG,EAAE,CAAC,MAAM,CAAC;YAC/B,cAAc,CAAC,qBAAqB;YACpC,cAAc,CAAC,qBAAqB;YACpC,cAAc,CAAC,qBAAqB;YACpC,cAAc,CAAC,qBAAqB;YACpC,cAAc,CAAC,qBAAqB;YACpC,cAAc,CAAC,qBAAqB;SACrC,EAAE,CAAC,CAAgB,CAAA;QAEpB,IAAM,gBAAgB,GAAG,EAAE,CAAC,MAAM,CAAC;YACjC,cAAc,CAAC,eAAe;YAC9B,cAAc,CAAC,eAAe;YAC9B,cAAc,CAAC,eAAe;YAC9B,cAAc,CAAC,eAAe;YAC9B,cAAc,CAAC,eAAe;YAC9B,cAAc,CAAC,eAAe;SAC/B,EAAE,CAAC,CAAgB,CAAA;QAEpB,OAAO;YACL,cAAc,gBAAA;YACd,gBAAgB,kBAAA;SACjB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
export declare function normalize(input: number[] | ImageData): tf.Tensor4D;
export declare function resizeLayer(x: tf.Tensor4D): tf.Tensor<tf.Rank>;
import * as tf from '@tensorflow/tfjs-core';
var resizedImageSize = [512, 512];
var weight = tf.scalar(0.007843137718737125);
var bias = tf.scalar(1);
export function resizeLayer(x) {
return tf.tidy(function () {
var resized = tf.image.resizeBilinear(x, resizedImageSize, false);
return tf.sub(tf.mul(resized, weight), bias);
});
}
//# sourceMappingURL=resizeLayer.js.map
\ No newline at end of file
{"version":3,"file":"resizeLayer.js","sourceRoot":"","sources":["../../src/faceDetectionNet/resizeLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,IAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,GAAG,CAAqB,CAAA;AACvD,IAAM,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAA;AAC9C,IAAM,IAAI,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;AAEzB,MAAM,sBAAsB,CAAc;IACxC,OAAO,EAAE,CAAC,IAAI,CAAC;QAEb,IAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAA;QACnE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAA;IAE9C,CAAC,CAAC,CAAA;AACJ,CAAC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
export declare namespace FaceDetectionNet {
type PointwiseConvParams = {
filters: tf.Tensor4D;
batch_norm_offset: tf.Tensor1D;
};
namespace MobileNetV1 {
type DepthwiseConvParams = {
filters: tf.Tensor4D;
batch_norm_scale: tf.Tensor1D;
batch_norm_offset: tf.Tensor1D;
batch_norm_mean: tf.Tensor1D;
batch_norm_variance: tf.Tensor1D;
};
type ConvPairParams = {
depthwise_conv_params: DepthwiseConvParams;
pointwise_conv_params: PointwiseConvParams;
};
type Params = {
conv_0_params: PointwiseConvParams;
conv_pair_params: ConvPairParams[];
};
}
type ConvWithBiasParams = {
filters: tf.Tensor4D;
bias: tf.Tensor1D;
};
type BoxPredictionParams = {
box_encoding_predictor_params: ConvWithBiasParams;
class_predictor_params: ConvWithBiasParams;
};
type PredictionLayerParams = {
conv_0_params: PointwiseConvParams;
conv_1_params: PointwiseConvParams;
conv_2_params: PointwiseConvParams;
conv_3_params: PointwiseConvParams;
conv_4_params: PointwiseConvParams;
conv_5_params: PointwiseConvParams;
conv_6_params: PointwiseConvParams;
conv_7_params: PointwiseConvParams;
box_predictor_0_params: BoxPredictionParams;
box_predictor_1_params: BoxPredictionParams;
box_predictor_2_params: BoxPredictionParams;
box_predictor_3_params: BoxPredictionParams;
box_predictor_4_params: BoxPredictionParams;
box_predictor_5_params: BoxPredictionParams;
};
type OutputLayerParams = {
extra_dim: tf.Tensor3D;
};
type NetParams = {
mobilenetv1_params: MobileNetV1.Params;
prediction_layer_params: PredictionLayerParams;
output_layer_params: OutputLayerParams;
};
type Detection = {
score: number;
box: {
top: number;
left: number;
right: number;
bottom: number;
};
};
}
//# sourceMappingURL=types.js.map
\ No newline at end of file
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/faceDetectionNet/types.ts"],"names":[],"mappings":""}
\ No newline at end of file
//# sourceMappingURL=FaceRecognitionNetParams.js.map
\ No newline at end of file
{"version":3,"file":"FaceRecognitionNetParams.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/FaceRecognitionNetParams.ts"],"names":[],"mappings":""}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { ScaleLayerParams } from './scaleLayer';
export declare type ConvParams = {
filters: tf.Tensor4D;
biases: tf.Tensor1D;
};
export declare type ConvLayerParams = {
conv: ConvParams;
scale: ScaleLayerParams;
};
export declare function conv(x: tf.Tensor4D, params: ConvLayerParams): tf.Tensor<tf.Rank.R4>;
export declare function convNoRelu(x: tf.Tensor4D, params: ConvLayerParams): tf.Tensor<tf.Rank.R4>;
export declare function convDown(x: tf.Tensor4D, params: ConvLayerParams): tf.Tensor<tf.Rank.R4>;
import { FaceRecognitionNet } from './types';
export declare function conv(x: tf.Tensor4D, params: FaceRecognitionNet.ConvLayerParams): tf.Tensor<tf.Rank.R4>;
export declare function convNoRelu(x: tf.Tensor4D, params: FaceRecognitionNet.ConvLayerParams): tf.Tensor<tf.Rank.R4>;
export declare function convDown(x: tf.Tensor4D, params: FaceRecognitionNet.ConvLayerParams): tf.Tensor<tf.Rank.R4>;
{"version":3,"file":"convLayer.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/convLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,KAAK,EAAoB,MAAM,cAAc,CAAC;AAYvD,mBACE,CAAc,EACd,MAAuB,EACvB,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,MAAuB;IAC1D,OAAO,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;AACtC,CAAC;AAED,MAAM,qBAAqB,CAAc,EAAE,MAAuB;IAChE,OAAO,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,mBAAmB,CAAc,EAAE,MAAuB;IAC9D,OAAO,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;AAC/C,CAAC"}
\ 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"}
\ No newline at end of file
import { FaceRecognitionNetParams } from './FaceRecognitionNetParams';
export declare function extractParams(weights: Float32Array): FaceRecognitionNetParams;
import { FaceRecognitionNet } from './types';
export declare function extractParams(weights: Float32Array): FaceRecognitionNet.NetParams;
import * as tf from '@tensorflow/tfjs-core';
function isFloat(num) {
return num % 1 !== 0;
}
import { isFloat } from '../utils';
function extractorsFactory(extractWeights) {
function extractFilterValues(numFilterValues, numFilters, filterSize) {
var weights = extractWeights(numFilterValues);
......
{"version":3,"file":"extractParams.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/extractParams.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
{"version":3,"file":"extractParams.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/extractParams.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { NetInput } from '../NetInput';
export declare function faceRecognitionNet(weights: Float32Array): {
computeFaceDescriptor: (input: number[] | ImageData) => Promise<Int32Array | Uint8Array | Float32Array>;
computeFaceDescriptorSync: (input: number[] | ImageData) => Int32Array | Uint8Array | Float32Array;
forward: (input: number[] | ImageData) => tf.Tensor<tf.Rank.R2>;
computeFaceDescriptor: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | tf.Tensor<tf.Rank> | NetInput) => Promise<Int32Array | Uint8Array | Float32Array>;
computeFaceDescriptorSync: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | tf.Tensor<tf.Rank> | NetInput) => Int32Array | Uint8Array | Float32Array;
forward: (input: string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | (string | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement)[] | tf.Tensor<tf.Rank> | NetInput) => tf.Tensor<tf.Rank.R2>;
};
import * as tslib_1 from "tslib";
import * as tf from '@tensorflow/tfjs-core';
import { normalize } from '../normalize';
import { getImageTensor, padToSquare } from '../transformInputs';
import { convDown } from './convLayer';
import { extractParams } from './extractParams';
import { normalize } from './normalize';
import { residual, residualDown } from './residualLayer';
export function faceRecognitionNet(weights) {
var _this = this;
var params = extractParams(weights);
function forward(input) {
return tf.tidy(function () {
var x = normalize(input);
var x = normalize(padToSquare(getImageTensor(input)));
var out = convDown(x, params.conv32_down);
out = tf.maxPool(out, 3, 2, 'valid');
out = residual(out, params.conv32_1);
......@@ -29,8 +32,26 @@ export function faceRecognitionNet(weights) {
return fullyConnected;
});
}
var computeFaceDescriptor = function (input) { return forward(input).data(); };
var computeFaceDescriptorSync = function (input) { return forward(input).dataSync(); };
var computeFaceDescriptor = function (input) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var result, data;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
result = forward(input);
return [4 /*yield*/, result.data()];
case 1:
data = _a.sent();
result.dispose();
return [2 /*return*/, data];
}
});
}); };
var computeFaceDescriptorSync = function (input) {
var result = forward(input);
var data = result.dataSync();
result.dispose();
return data;
};
return {
computeFaceDescriptor: computeFaceDescriptor,
computeFaceDescriptorSync: computeFaceDescriptorSync,
......
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,6BAA6B,OAAqB;IACtD,IAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;IAErC,iBAAiB,KAA2B;QAE1C,OAAO,EAAE,CAAC,IAAI,CAAC;YAEb,IAAM,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;YAE1B,IAAI,GAAG,GAAG,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;YACzC,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;YAEpC,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;YACpC,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;YACpC,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;YAEpC,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;YAC3C,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;YACpC,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;YACpC,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;YAEpC,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;YAC5C,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;YACrC,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;YAErC,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;YAC5C,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;YACrC,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;YACrC,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAA;YAEhD,IAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAgB,CAAA;YACjD,IAAM,cAAc,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,CAAA;YAEtD,OAAO,cAAc,CAAA;QACvB,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,IAAM,qBAAqB,GAAG,UAAC,KAA2B,IAAK,OAAA,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAArB,CAAqB,CAAA;IACpF,IAAM,yBAAyB,GAAG,UAAC,KAA2B,IAAK,OAAA,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAzB,CAAyB,CAAA;IAE5F,OAAO;QACL,qBAAqB,uBAAA;QACrB,yBAAyB,2BAAA;QACzB,OAAO,SAAA;KACR,CAAA;AACH,CAAC"}
\ No newline at end of file
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/index.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
export declare function normalize(x: tf.Tensor4D): tf.Tensor4D;
import * as tf from '@tensorflow/tfjs-core';
export function normalize(input) {
export function normalize(x) {
return tf.tidy(function () {
var avg_r = tf.fill([1, 150, 150, 1], 122.782);
var avg_g = tf.fill([1, 150, 150, 1], 117.001);
var avg_b = tf.fill([1, 150, 150, 1], 104.298);
var avg_rgb = tf.concat([avg_r, avg_g, avg_b], 3);
var x = input instanceof ImageData
? tf.cast(tf.reshape(tf.fromPixels(input), [1, 150, 150, 3]), 'float32')
: tf.tensor4d(input, [1, 150, 150, 3]);
return tf.div(tf.sub(x, avg_rgb), tf.fill(x.shape, 256));
return tf.div(tf.sub(x, avg_rgb), tf.scalar(256));
});
}
//# sourceMappingURL=normalize.js.map
\ No newline at end of file
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,MAAM,oBAAoB,CAAc;IACtC,OAAO,EAAE,CAAC,IAAI,CAAC;QACb,IAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACjD,IAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACjD,IAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACjD,IAAM,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAA;QAEnD,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;AACJ,CAAC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { ConvLayerParams } from './convLayer';
export declare type ResidualLayerParams = {
conv1: ConvLayerParams;
conv2: ConvLayerParams;
};
export declare function residual(x: tf.Tensor4D, params: ResidualLayerParams): tf.Tensor4D;
export declare function residualDown(x: tf.Tensor4D, params: ResidualLayerParams): tf.Tensor4D;
import { FaceRecognitionNet } from './types';
export declare function residual(x: tf.Tensor4D, params: FaceRecognitionNet.ResidualLayerParams): tf.Tensor4D;
export declare function residualDown(x: tf.Tensor4D, params: FaceRecognitionNet.ResidualLayerParams): tf.Tensor4D;
import * as tf from '@tensorflow/tfjs-core';
import { conv, convNoRelu, convDown } from './convLayer';
import { conv, convDown, convNoRelu } from './convLayer';
export function residual(x, params) {
var out = conv(x, params.conv1);
out = convNoRelu(out, params.conv2);
......
{"version":3,"file":"residualLayer.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/residualLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAmB,QAAQ,EAAE,MAAM,aAAa,CAAC;AAO1E,MAAM,mBAAmB,CAAc,EAAE,MAA2B;IAClE,IAAI,GAAG,GAAG,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IAC/B,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IACnC,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IACpB,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAClB,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,uBAAuB,CAAc,EAAE,MAA2B;IACtE,IAAI,GAAG,GAAG,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IACnC,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IAEnC,IAAI,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,CAAgB,CAAA;IACxD,IAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAa,MAAM,CAAC,KAAK,CAAC,CAAA;IAChD,IAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC9C,IAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAE1F,IAAI,aAAa,EAAE;QACjB,IAAM,SAAS,GAAO,GAAG,CAAC,KAAK,QAAqC,CAAA;QACpE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QAChB,IAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAa,SAAS,CAAC,CAAA;QAC9C,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;QAEjC,IAAM,SAAS,GAAO,GAAG,CAAC,KAAK,QAAqC,CAAA;QACpE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QAChB,IAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAa,SAAS,CAAC,CAAA;QAC9C,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;KAClC;IAED,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IACvD,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAgB,CAAA;IAExC,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAClB,OAAO,GAAG,CAAA;AACZ,CAAC"}
\ No newline at end of file
{"version":3,"file":"residualLayer.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/residualLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzD,MAAM,mBAAmB,CAAc,EAAE,MAA8C;IACrF,IAAI,GAAG,GAAG,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IAC/B,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IACnC,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IACpB,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAClB,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,uBAAuB,CAAc,EAAE,MAA8C;IACzF,IAAI,GAAG,GAAG,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IACnC,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IAEnC,IAAI,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,CAAgB,CAAA;IACxD,IAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAa,MAAM,CAAC,KAAK,CAAC,CAAA;IAChD,IAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC9C,IAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAE1F,IAAI,aAAa,EAAE;QACjB,IAAM,SAAS,GAAO,GAAG,CAAC,KAAK,QAAqC,CAAA;QACpE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QAChB,IAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAa,SAAS,CAAC,CAAA;QAC9C,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;QAEjC,IAAM,SAAS,GAAO,GAAG,CAAC,KAAK,QAAqC,CAAA;QACpE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QAChB,IAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAa,SAAS,CAAC,CAAA;QAC9C,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;KAClC;IAED,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IACvD,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAgB,CAAA;IAExC,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAClB,OAAO,GAAG,CAAA;AACZ,CAAC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
export declare type ScaleLayerParams = {
weights: tf.Tensor1D;
biases: tf.Tensor1D;
};
export declare function scale(x: tf.Tensor4D, params: ScaleLayerParams): tf.Tensor4D;
import { FaceRecognitionNet } from './types';
export declare function scale(x: tf.Tensor4D, params: FaceRecognitionNet.ScaleLayerParams): tf.Tensor4D;
{"version":3,"file":"scaleLayer.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/scaleLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAO5C,MAAM,gBAAgB,CAAc,EAAE,MAAwB;IAC5D,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;AACzD,CAAC"}
\ No newline at end of file
{"version":3,"file":"scaleLayer.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/scaleLayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAG5C,MAAM,gBAAgB,CAAc,EAAE,MAA2C;IAC/E,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;AACzD,CAAC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { ConvLayerParams } from './convLayer';
import { ResidualLayerParams } from './residualLayer';
export declare type FaceRecognitionNetParams = {
conv32_down: ConvLayerParams;
conv32_1: ResidualLayerParams;
conv32_2: ResidualLayerParams;
conv32_3: ResidualLayerParams;
conv64_down: ResidualLayerParams;
conv64_1: ResidualLayerParams;
conv64_2: ResidualLayerParams;
conv64_3: ResidualLayerParams;
conv128_down: ResidualLayerParams;
conv128_1: ResidualLayerParams;
conv128_2: ResidualLayerParams;
conv256_down: ResidualLayerParams;
conv256_1: ResidualLayerParams;
conv256_2: ResidualLayerParams;
conv256_down_out: ResidualLayerParams;
fc: tf.Tensor2D;
};
export declare namespace FaceRecognitionNet {
type ScaleLayerParams = {
weights: tf.Tensor1D;
biases: tf.Tensor1D;
};
type ResidualLayerParams = {
conv1: ConvLayerParams;
conv2: ConvLayerParams;
};
type ConvParams = {
filters: tf.Tensor4D;
biases: tf.Tensor1D;
};
type ConvLayerParams = {
conv: ConvParams;
scale: ScaleLayerParams;
};
type NetParams = {
conv32_down: ConvLayerParams;
conv32_1: ResidualLayerParams;
conv32_2: ResidualLayerParams;
conv32_3: ResidualLayerParams;
conv64_down: ResidualLayerParams;
conv64_1: ResidualLayerParams;
conv64_2: ResidualLayerParams;
conv64_3: ResidualLayerParams;
conv128_down: ResidualLayerParams;
conv128_1: ResidualLayerParams;
conv128_2: ResidualLayerParams;
conv256_down: ResidualLayerParams;
conv256_1: ResidualLayerParams;
conv256_2: ResidualLayerParams;
conv256_down_out: ResidualLayerParams;
fc: tf.Tensor2D;
};
}
//# sourceMappingURL=types.js.map
\ No newline at end of file
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/faceRecognitionNet/types.ts"],"names":[],"mappings":""}
\ No newline at end of file
import { euclideanDistance } from './euclideanDistance';
import { faceDetectionNet } from './faceDetectionNet';
import { faceRecognitionNet } from './faceRecognitionNet';
import { normalize } from './normalize';
export { euclideanDistance, faceRecognitionNet, normalize };
import { NetInput } from './NetInput';
export { euclideanDistance, faceDetectionNet, faceRecognitionNet, NetInput };
export * from './utils';
import { euclideanDistance } from './euclideanDistance';
import { faceDetectionNet } from './faceDetectionNet';
import { faceRecognitionNet } from './faceRecognitionNet';
import { normalize } from './normalize';
export { euclideanDistance, faceRecognitionNet, normalize };
import { NetInput } from './NetInput';
export { euclideanDistance, faceDetectionNet, faceRecognitionNet, NetInput };
export * from './utils';
//# sourceMappingURL=index.js.map
\ No newline at end of file
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACV,CAAA"}
\ No newline at end of file
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,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;AAEtC,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,QAAQ,EACT,CAAA;AAED,cAAc,SAAS,CAAA"}
\ No newline at end of file
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,MAAM,oBAAoB,KAA2B;IACnD,OAAO,EAAE,CAAC,IAAI,CAAC;QACb,IAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACjD,IAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACjD,IAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACjD,IAAM,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAA;QAEnD,IAAM,CAAC,GAAG,KAAK,YAAY,SAAS;YAClC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;YACxE,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;QACxC,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;AACJ,CAAC"}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { NetInput } from './NetInput';
import { TNetInput } from './types';
export declare function padToSquare(imgTensor: tf.Tensor4D): tf.Tensor4D;
export declare function getImageTensor(input: tf.Tensor | NetInput | TNetInput): tf.Tensor4D;
import * as tf from '@tensorflow/tfjs-core';
import { NetInput } from './NetInput';
export function padToSquare(imgTensor) {
return tf.tidy(function () {
var _a = imgTensor.shape, _ = _a[0], height = _a[1], width = _a[2];
if (height === width) {
return imgTensor;
}
if (height > width) {
var pad_1 = tf.fill([1, height, height - width, 3], 0);
return tf.concat([imgTensor, pad_1], 2);
}
var pad = tf.fill([1, width - height, width, 3], 0);
return tf.concat([imgTensor, pad], 1);
});
}
export function getImageTensor(input) {
return tf.tidy(function () {
if (input instanceof tf.Tensor) {
var rank = input.shape.length;
if (rank !== 3 && rank !== 4) {
throw new Error('input tensor must be of rank 3 or 4');
}
return (rank === 3 ? input.expandDims(0) : input).toFloat();
}
var netInput = input instanceof NetInput ? input : new NetInput(input);
return tf.concat(netInput.canvases.map(function (canvas) {
return tf.fromPixels(canvas).expandDims(0).toFloat();
}));
});
}
//# sourceMappingURL=transformInputs.js.map
\ No newline at end of file
{"version":3,"file":"transformInputs.js","sourceRoot":"","sources":["../src/transformInputs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,MAAM,sBAAsB,SAAsB;IAChD,OAAO,EAAE,CAAC,IAAI,CAAC;QAEP,IAAA,oBAAoC,EAAnC,SAAC,EAAE,cAAM,EAAE,aAAK,CAAmB;QAC1C,IAAI,MAAM,KAAK,KAAK,EAAE;YACpB,OAAO,SAAS,CAAA;SACjB;QAED,IAAI,MAAM,GAAG,KAAK,EAAE;YAClB,IAAM,KAAG,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAgB,CAAA;YACrE,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,KAAG,CAAC,EAAE,CAAC,CAAC,CAAA;SACtC;QACD,IAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAgB,CAAA;QACpE,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,yBAAyB,KAAuC;IACpE,OAAO,EAAE,CAAC,IAAI,CAAC;QACb,IAAI,KAAK,YAAY,EAAE,CAAC,MAAM,EAAE;YAC9B,IAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAA;YAC/B,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE;gBAC5B,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;aACvD;YAED,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,EAAiB,CAAA;SAC3E;QAED,IAAM,QAAQ,GAAG,KAAK,YAAY,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAA;QACxE,OAAO,EAAE,CAAC,MAAM,CACd,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAA,MAAM;YAC1B,OAAA,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE;QAA7C,CAA6C,CAC9C,CACa,CAAA;IAClB,CAAC,CAAC,CAAA;AACJ,CAAC"}
\ No newline at end of file
export declare type TMediaElement = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;
export declare type TNetInputArg = string | TMediaElement;
export declare type TNetInput = TNetInputArg | Array<TNetInputArg>;
export declare type Dimensions = {
width: number;
height: number;
};
export declare type DrawBoxOptions = {
lineWidth: number;
color: string;
};
export declare type DrawTextOptions = {
fontSize: number;
fontStyle: string;
color: string;
};
//# sourceMappingURL=types.js.map
\ No newline at end of file
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
\ No newline at end of file
import { FaceDetectionNet } from './faceDetectionNet/types';
import { DrawBoxOptions, DrawTextOptions } from './types';
export declare function isFloat(num: number): boolean;
export declare function round(num: number): number;
export declare function getElement(arg: string | any): any;
export declare function getContext2dOrThrow(canvas: HTMLCanvasElement): CanvasRenderingContext2D;
export declare function getMediaDimensions(media: HTMLImageElement | HTMLVideoElement): HTMLImageElement | {
width: number;
height: number;
};
export declare function bufferToImage(buf: Blob): Promise<HTMLImageElement>;
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 drawDetection(canvasArg: string | HTMLCanvasElement, detection: FaceDetectionNet.Detection | FaceDetectionNet.Detection[], options?: DrawBoxOptions & DrawTextOptions & {
withScore: boolean;
}): void;
export function isFloat(num) {
return num % 1 !== 0;
}
export function round(num) {
return Math.floor(num * 100) / 100;
}
export function getElement(arg) {
if (typeof arg === 'string') {
return document.getElementById(arg);
}
return arg;
}
export function getContext2dOrThrow(canvas) {
var ctx = canvas.getContext('2d');
if (!ctx) {
throw new Error('canvas 2d context is null');
}
return ctx;
}
export function getMediaDimensions(media) {
if (media instanceof HTMLVideoElement) {
return { width: media.videoWidth, height: media.videoHeight };
}
return media;
}
export function bufferToImage(buf) {
return new Promise(function (resolve, reject) {
if (!(buf instanceof Blob)) {
return reject('bufferToImage - expected buf to be of type: Blob');
}
var reader = new FileReader();
reader.onload = function () {
var img = new Image();
img.onload = function () { return resolve(img); };
img.onerror = reject;
img.src = reader.result;
};
reader.onerror = reject;
reader.readAsDataURL(buf);
});
}
export function drawBox(ctx, x, y, w, h, options) {
ctx.strokeStyle = options.color;
ctx.lineWidth = options.lineWidth;
ctx.strokeRect(x, y, w, h);
}
export function drawText(ctx, x, y, text, options) {
ctx.fillStyle = options.color;
ctx.font = options.fontSize + "px " + options.fontStyle;
ctx.fillText(text, x, y);
}
export function drawDetection(canvasArg, detection, options) {
var canvas = getElement(canvasArg);
if (!(canvas instanceof HTMLCanvasElement)) {
throw new Error('drawBox - expected canvas to be of type: HTMLCanvasElement');
}
var detectionArray = Array.isArray(detection)
? detection
: [detection];
detectionArray.forEach(function (det) {
var score = det.score, box = det.box;
var left = box.left, right = box.right, top = box.top, bottom = box.bottom;
var _a = (options || {}), _b = _a.color, color = _b === void 0 ? 'blue' : _b, _c = _a.lineWidth, lineWidth = _c === void 0 ? 2 : _c, _d = _a.fontSize, fontSize = _d === void 0 ? 20 : _d, _e = _a.fontStyle, fontStyle = _e === void 0 ? 'Georgia' : _e, _f = _a.withScore, withScore = _f === void 0 ? true : _f;
var padText = 2 + lineWidth;
var ctx = getContext2dOrThrow(canvas);
drawBox(ctx, left, top, right - left, bottom - top, { lineWidth: lineWidth, color: color });
if (withScore) {
drawText(ctx, left + padText, top + (fontSize * 0.6) + padText, "" + round(score), { fontSize: fontSize, fontStyle: fontStyle, color: color });
}
});
}
//# 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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"}
\ No newline at end of file
const classes = ['amy', 'bernadette', 'howard', 'leonard', 'penny', 'raj', 'sheldon', 'stuart']
function getImageUri(className, idx) {
return `/${className}/${className}${idx}.png`
}
async function initNet() {
const res = await axios.get('face_recognition_model.weights', { responseType: 'arraybuffer' })
const weights = new Float32Array(res.data)
return facerecognition.faceRecognitionNet(weights)
}
function bufferToImgSrc(buf) {
return new Promise((resolve, reject) => {
const reader = new window.FileReader()
reader.onload = () => resolve(reader.result)
reader.onerror = reject
reader.readAsDataURL(buf)
})
}
function imgSrcToData(src) {
return new Promise((resolve, reject) => {
const canvas = document.createElement('canvas')
canvas.width = 150
canvas.height = 150
const ctx = canvas.getContext('2d')
const img = new Image()
img.onload = function() {
ctx.drawImage(img, 0, 0)
resolve(ctx.getImageData(0, 0, 150, 150))
}
img.onerror = reject
img.src = src
})
}
async function bufferToImageData(buf) {
return imgSrcToData(await bufferToImgSrc(buf))
}
async function fetchImage(uri) {
return (await axios.get(uri, { responseType: 'blob' })).data
}
function round(num) {
return Math.floor(num * 100) / 100
}
\ No newline at end of file
const express = require('express')
const path = require('path')
const app = express()
const viewsDir = path.join(__dirname, 'views')
app.use(express.static(path.join(__dirname, '../images')))
app.use(express.static(path.join(__dirname, '../../weights')))
app.use(express.static(path.join(__dirname, '../../dist')))
app.use(express.static(path.join(__dirname, './node_modules/axios/dist')))
app.use(express.static(viewsDir))
app.use(express.static(path.join(__dirname, './public')))
app.get('/', (req, res) => res.redirect('/faceRecognition'))
app.get('/faceRecognition', (req, res) => res.sendFile(path.join(viewsDir, 'faceRecognition.html')))
app.get('/faceSimilarity', (req, res) => res.sendFile(path.join(viewsDir, 'faceSimilarity.html')))
app.listen(3000, () => console.log('Listening on port 3000!'))
\ No newline at end of file
const classes = ['amy', 'bernadette', 'howard', 'leonard', 'penny', 'raj', 'sheldon', 'stuart']
function getImageUri(imageName) {
return `images/${imageName}`
}
function getFaceImageUri(className, idx) {
return `images/${className}/${className}${idx}.png`
}
async function fetchImage(uri) {
return (await axios.get(uri, { responseType: 'blob' })).data
}
async function initFaceDetectionNet() {
const res = await axios.get('face_detection_model.weights', { responseType: 'arraybuffer' })
const weights = new Float32Array(res.data)
return facerecognition.faceDetectionNet(weights)
}
async function initFaceRecognitionNet() {
const res = await axios.get('face_recognition_model.weights', { responseType: 'arraybuffer' })
const weights = new Float32Array(res.data)
return facerecognition.faceRecognitionNet(weights)
}
function renderNavBar(navbarId, exampleUri) {
const examples = [
{
uri: 'face_detection',
name: 'Face Detection'
},
{
uri: 'face_detection_video',
name: 'Face Detection Video'
},
{
uri: 'face_recognition',
name: 'Face Recognition'
},
{
uri: 'face_similarity',
name: 'Face Similarity'
}
]
const navbar = $(navbarId).get(0)
navbar.classList.add('row')
examples
.filter(ex => ex.uri !== exampleUri)
.forEach(ex => {
const a = document.createElement('a')
navbar.appendChild(a)
a.classList.add('waves-effect', 'waves-light', 'btn', 'margin-sm')
a.href = ex.uri
a.innerHTML = ex.name
})
}
function renderSelectList(selectListId, onChange, initialValue, renderChildren) {
const select = document.createElement('select')
$(selectListId).get(0).appendChild(select)
renderChildren(select)
$(select).val(initialValue)
$(select).on('change', (e) => onChange(e.target.value))
$(select).material_select()
}
function renderOption(parent, text, value) {
const option = document.createElement('option')
option.innerHTML = text
option.value = value
parent.appendChild(option)
}
function renderFaceImageSelectList(selectListId, onChange, initialValue) {
const indices = [1, 2, 3, 4, 5]
function renderChildren(select) {
classes.forEach(className => {
const optgroup = document.createElement('optgroup')
optgroup.label = className
select.appendChild(optgroup)
indices.forEach(imageIdx =>
renderOption(
optgroup,
`${className} ${imageIdx}`,
getFaceImageUri(className, imageIdx)
)
)
})
}
renderSelectList(
selectListId,
onChange,
getFaceImageUri(initialValue.className, initialValue.imageIdx),
renderChildren
)
}
function renderImageSelectList(selectListId, onChange, initialValue) {
const images = [1, 2, 3, 4, 5].map(idx => `bbt${idx}.jpg`)
function renderChildren(select) {
images.forEach(imageName =>
renderOption(
select,
imageName,
getImageUri(imageName)
)
)
}
renderSelectList(
selectListId,
onChange,
getImageUri(initialValue),
renderChildren
)
}
\ No newline at end of file
.page-container {
position: fixed;
left: 0;
right: 0;
margin: auto;
......@@ -18,16 +17,24 @@
justify-content: center;
align-items: center;
}
.side-by-side >* {
margin: 0 5px;
}
.bold {
font-weight: bold;
}
.margin-sm {
margin: 5px;
}
.margin {
margin: 20px;
}
img {
width: 150px;
height: 150px;
#overlay {
position: absolute;
top: 0;
left: 0;
}
\ No newline at end of file
const express = require('express')
const path = require('path')
const app = express()
const viewsDir = path.join(__dirname, 'views')
app.use(express.static(viewsDir))
app.use(express.static(path.join(__dirname, './public')))
app.use(express.static(path.join(__dirname, '../weights')))
app.use(express.static(path.join(__dirname, '../dist')))
app.use(express.static(path.join(__dirname, './node_modules/axios/dist')))
app.get('/', (req, res) => res.redirect('/face_detection'))
app.get('/face_detection', (req, res) => res.sendFile(path.join(viewsDir, 'faceDetection.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_similarity', (req, res) => res.sendFile(path.join(viewsDir, 'faceSimilarity.html')))
app.listen(3000, () => console.log('Listening on port 3000!'))
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<script src="face-recognition.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="onDecreaseThreshold()"
>
<i class="material-icons left">-</i>
</button>
<button
class="waves-effect waves-light btn"
onclick="onIncreaseThreshold()"
>
<i class="material-icons left">+</i>
</button>
</div>
</div>
<script>
let minConfidence = 0.7
let net, result
function onIncreaseThreshold() {
minConfidence = Math.min(facerecognition.round(minConfidence + 0.1), 1.0)
$('#minConfidence').val(minConfidence)
updateResults()
}
function onDecreaseThreshold() {
minConfidence = Math.max(facerecognition.round(minConfidence - 0.1), 0.1)
$('#minConfidence').val(minConfidence)
updateResults()
}
async function updateResults() {
const input = new facerecognition.NetInput('inputImg')
const { width, height } = input
const canvas = $('#overlay').get(0)
canvas.width = width
canvas.height = height
result = await net.locateFaces(input, minConfidence)
facerecognition.drawDetection('overlay', result.map(det => det.forSize(width, height)))
}
async function onSelectionChanged(uri) {
const imgBuf = await fetchImage(uri)
$(`#inputImg`).get(0).src = (await facerecognition.bufferToImage(imgBuf)).src
updateResults()
}
async function run() {
net = await initFaceDetectionNet()
$('#loader').hide()
onSelectionChanged($('#selectList select').val())
}
$(document).ready(function() {
renderNavBar('#navbar', 'face_detection')
renderImageSelectList(
'#selectList',
async (uri) => {
await onSelectionChanged(uri)
},
'bbt1.jpg'
)
run()
})
</script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<script src="face-recognition.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">
<video src="media/bbt.mp4" onplay="onPlay(this)" autoplay muted></video>
<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="onDecreaseThreshold()"
>
<i class="material-icons left">-</i>
</button>
<button
class="waves-effect waves-light btn"
onclick="onIncreaseThreshold()"
>
<i class="material-icons left">+</i>
</button>
</div>
<div class="row side-by-side">
<div class="row">
<label for="time">Time:</label>
<input disabled value="-" id="time" type="text" class="bold">
</div>
<div class="row">
<label for="fps">Estimated Fps:</label>
<input disabled value="-" id="fps" type="text" class="bold">
</div>
</div>
</div>
<script>
let minConfidence = 0.7
let net, result
function onIncreaseThreshold() {
minConfidence = Math.min(facerecognition.round(minConfidence + 0.1), 1.0)
$('#minConfidence').val(minConfidence)
}
function onDecreaseThreshold() {
minConfidence = Math.max(facerecognition.round(minConfidence - 0.1), 0.1)
$('#minConfidence').val(minConfidence)
}
function displayTimeStats(timeInMs) {
$('#time').val(`${timeInMs} ms`)
$('#fps').val(`${facerecognition.round(1000 / timeInMs)}`)
}
async function onPlay(videoEl) {
if(videoEl.paused || videoEl.ended)
return false
const input = new facerecognition.NetInput(videoEl)
const { width, height } = input
const canvas = $('#overlay').get(0)
canvas.width = width
canvas.height = height
const ts = Date.now()
result = await net.locateFaces(input, minConfidence)
displayTimeStats(Date.now() - ts)
facerecognition.drawDetection('overlay', result.map(det => det.forSize(width, height)))
setTimeout(() => onPlay(videoEl))
}
async function run() {
net = await initFaceDetectionNet()
$('#loader').hide()
}
$(document).ready(function() {
renderNavBar('#navbar', 'face_detection_video')
run()
})
</script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<script src="face-recognition.min.js"></script>
<script src="face-recognition.js"></script>
<script src="axios.min.js"></script>
<script src="commons.js"></script>
<link rel="stylesheet" href="styles.css">
......@@ -11,14 +11,8 @@
</head>
<body>
<div class="center-content page-container">
<div class="row">
<a
class="waves-effect waves-light btn"
href="faceSimilarity.html"
>
Go To Face Similarity Example
</a>
</div>
<div id="navbar"></div>
<div>
<div class="row center-content" id="loader">
<input disabled value="" id="status" type="text" class="bold">
......@@ -53,7 +47,7 @@
class="waves-effect waves-light btn"
onclick="onSlower()"
>
<i class="material-icons left">-</i> Slower
<i class="material-icons left">-</i> Slower
</button>
<button
class="waves-effect waves-light btn"
......@@ -77,17 +71,17 @@
let isStop = false
let trainDescriptorsByClass = []
let net = {}
let net
let currImageIdx = 2, currClassIdx = 0
let to = null
function onSlower() {
interval = Math.max(interval + 100, 0)
interval = Math.min(interval + 100, 2000)
$('#interval').val(interval)
}
function onFaster() {
interval = Math.min(interval - 100, 2000)
interval = Math.max(interval - 100, 0)
$('#interval').val(interval)
}
......@@ -107,18 +101,18 @@
function displayTimeStats(timeInMs) {
$('#time').val(`${timeInMs} ms`)
$('#fps').val(`${round(1000 / timeInMs)}`)
$('#fps').val(`${facerecognition.round(1000 / timeInMs)}`)
}
function displayImage(src) {
getImg().src = src
}
async function loadTrainingData(cb) {
async function loadTrainingImages() {
return await Promise.all(classes.map(
async className => ({
imgData: await bufferToImageData(
await fetchImage(getImageUri(className, 1))
img: await facerecognition.bufferToImage(
await fetchImage(getFaceImageUri(className, 1))
),
className
})
......@@ -129,7 +123,9 @@
return trainDescriptorsByClass
.map(
({ descriptor, className }) => ({
distance: round(facerecognition.euclideanDistance(descriptor, queryDescriptor)),
distance: facerecognition.round(
facerecognition.euclideanDistance(descriptor, queryDescriptor)
),
className
})
)
......@@ -138,17 +134,15 @@
async function runFaceRecognition() {
async function next() {
const imgBuf = await fetchImage(getImageUri(classes[currClassIdx], currImageIdx))
const imgBuf = await fetchImage(getFaceImageUri(classes[currClassIdx], currImageIdx))
const input = await facerecognition.bufferToImage(imgBuf)
const imgEl = $('#face').get(0)
imgEl.src = await bufferToImgSrc(imgBuf)
const imageData = await imgSrcToData(imgEl.src)
imgEl.src = input.src
const ts = Date.now()
const result = await net.forward(imageData)
const descriptor = await net.computeFaceDescriptor(input)
displayTimeStats(Date.now() - ts)
const descriptor = await result.data()
const bestMatch = getBestMatch(descriptor)
$('#prediction').val(`${bestMatch.distance < threshold ? bestMatch.className : 'unkown'} (${bestMatch.distance})`)
......@@ -167,13 +161,13 @@
try {
setStatusText('loading model file...')
net = await initNet()
net = await initFaceRecognitionNet()
setStatusText('computing initial descriptors...')
const trainImgDatas = await loadTrainingData()
trainDescriptorsByClass = await Promise.all(trainImgDatas.map(
async ({ className, imgData }) => ({
descriptor: await net.computeFaceDescriptor(imgData),
const trainImgs = await loadTrainingImages()
trainDescriptorsByClass = await Promise.all(trainImgs.map(
async ({ className, img }) => ({
descriptor: await net.computeFaceDescriptor(img),
className
})
))
......@@ -185,7 +179,11 @@
}
}
run()
$(document).ready(function() {
renderNavBar('#navbar', 'face_recognition')
run()
})
</script>
</body>
......
<!DOCTYPE html>
<html>
<head>
<script src="face-recognition.min.js"></script>
<script src="face-recognition.js"></script>
<script src="axios.min.js"></script>
<script src="commons.js"></script>
<link rel="stylesheet" href="styles.css">
......@@ -11,14 +11,8 @@
</head>
<body>
<div class="center-content page-container">
<div class="row">
<a
class="waves-effect waves-light btn"
href="faceRecognition"
>
Go To Face Recognition Example
</a>
</div>
<div id="navbar"></div>
<div>
<div class="progress" id="loader">
<div class="indeterminate"></div>
......@@ -26,11 +20,11 @@
<div class="row side-by-side">
<div class="center-content">
<img id="face1" src="" class="margin"/>
<div id="selectList1" class="input-field"></div>
<div id="selectList1"></div>
</div>
<div class="center-content">
<img id="face2" src="" class="margin"/>
<div id="selectList2" class="input-field"></div>
<div id="selectList2"></div>
</div>
</div>
<div class="row">
......@@ -45,27 +39,10 @@
const threshold = 0.6
let net, descriptors = { desc1: null, desc2: null }
function renderSelectList(parent) {
const select = document.createElement('select')
parent.appendChild(select)
classes.forEach((className) => {
const optgroup = document.createElement('optgroup')
optgroup.label = className
select.appendChild(optgroup)
const indices = [1, 2, 3, 4, 5]
indices.forEach((imageIdx) => {
const option = document.createElement('option')
option.innerHTML = `${className} ${imageIdx}`
option.value = getImageUri(className, imageIdx)
optgroup.appendChild(option)
})
})
}
function updateResult() {
const distance = round(facerecognition.euclideanDistance(descriptors.desc1, descriptors.desc2))
const distance = facerecognition.round(
facerecognition.euclideanDistance(descriptors.desc1, descriptors.desc2)
)
let text = distance
let bgColor = '#ffffff'
if (distance > threshold) {
......@@ -76,48 +53,41 @@
$('#distance').css('background-color', bgColor)
}
async function computeDescriptorFromSrc(imgEl) {
return net.computeFaceDescriptor(await imgSrcToData(imgEl.src))
}
async function onSelectionChanged(which) {
const selectElSelector = `#selectList${which} select`
const imgElSelector = `#face${which}`
const whichDesc = `desc${which}`
const uri = $(selectElSelector).val()
const imgEl = $(imgElSelector).get(0)
async function onSelectionChanged(which, uri) {
const imgBuf = await fetchImage(uri)
imgEl.src = await bufferToImgSrc(imgBuf)
descriptors[whichDesc] = await computeDescriptorFromSrc($(imgElSelector).get(0))
const input = await facerecognition.bufferToImage(imgBuf)
const imgEl = $(`#face${which}`).get(0)
imgEl.src = input.src
descriptors[`desc${which}`] = await net.computeFaceDescriptor(input)
}
async function run() {
$('#selectList1 select').val(getImageUri('sheldon', 1))
$('#selectList1 select').material_select()
$('#selectList2 select').val(getImageUri('howard', 1))
$('#selectList2 select').material_select()
net = await initNet()
net = await initFaceRecognitionNet()
$('#loader').hide()
await onSelectionChanged(1)
await onSelectionChanged(2)
await onSelectionChanged(1, $('#selectList1 select').val())
await onSelectionChanged(2, $('#selectList2 select').val())
updateResult()
}
$(document).ready(function() {
renderSelectList($('#selectList1').get(0))
renderSelectList($('#selectList2').get(0))
$('select').material_select()
$('#selectList1 select').on('change', async () => {
await onSelectionChanged(1)
updateResult()
})
$('#selectList2 select').on('change', async () => {
await onSelectionChanged(2)
updateResult()
})
renderNavBar('#navbar', 'face_similarity')
renderFaceImageSelectList(
'#selectList1',
async (uri) => {
await onSelectionChanged(1, uri)
updateResult()
},
{ className: 'sheldon', imageIdx: 1 }
)
renderFaceImageSelectList(
'#selectList2',
async (uri) => {
await onSelectionChanged(2, uri)
updateResult()
},
{ className: 'howard', imageIdx: 1 }
)
run()
})
......
......@@ -5,7 +5,9 @@
"main": "./dist/index.js",
"typings": "./dist/index.d.ts",
"scripts": {
"build": "rollup -c rollup.config.js && tsc"
"rollup-min": "rollup -c rollup.config.js --environment minify:true",
"rollup": "rollup -c rollup.config.js",
"build": "npm run rollup && npm run rollup-min && tsc"
},
"keywords": [
"face",
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -4,17 +4,18 @@ import typescript from 'rollup-plugin-typescript2';
import uglify from 'rollup-plugin-uglify';
import path from 'path';
const { minify } = process.env
export default {
input: 'src/index.ts',
plugins: [
typescript(),
node(),
uglify(),
commonjs(),
],
commonjs()
].concat(minify ? uglify() : []),
output: {
extend: true,
file: 'dist/face-recognition.min.js',
file: `dist/face-recognition${minify ? '.min' : ''}.js`,
format: 'umd',
name: 'facerecognition',
globals: {
......
import { Dimensions, TMediaElement, TNetInput } from './types';
import { getContext2dOrThrow, getElement, getMediaDimensions } from './utils';
export class NetInput {
private _canvases: HTMLCanvasElement[]
constructor(
mediaArg: TNetInput,
dims?: Dimensions
) {
const mediaArgArray = Array.isArray(mediaArg)
? mediaArg
: [mediaArg]
if (!mediaArgArray.length) {
throw new Error('NetInput - empty array passed as input')
}
const medias = mediaArgArray.map(getElement)
medias.forEach((media, i) => {
if (!(media instanceof HTMLImageElement || media instanceof HTMLVideoElement || media instanceof HTMLCanvasElement)) {
const idxHint = Array.isArray(mediaArg) ? ` at input index ${i}:` : ''
if (typeof mediaArgArray[i] === 'string') {
throw new Error(`NetInput -${idxHint} string passed, but could not resolve HTMLElement for element id`)
}
throw new Error(`NetInput -${idxHint} expected media to be of type HTMLImageElement | HTMLVideoElement | HTMLCanvasElement, or to be an element id`)
}
})
this._canvases = []
medias.forEach(m => this.initCanvas(m, dims))
}
private initCanvas(media: TMediaElement, dims?: Dimensions) {
if (media instanceof HTMLCanvasElement) {
this._canvases.push(media)
return
}
// if input is batch type, make sure every canvas has the same dimensions
const { width, height } = this.dims || dims || getMediaDimensions(media)
const canvas = document.createElement('canvas')
canvas.width = width
canvas.height = height
getContext2dOrThrow(canvas).drawImage(media, 0, 0, width, height)
this._canvases.push(canvas)
}
public get canvases() : HTMLCanvasElement[] {
return this._canvases
}
public get width() : number {
return (this._canvases[0] || {}).width
}
public get height() : number {
return (this._canvases[0] || {}).height
}
public get dims() : Dimensions | null {
const { width, height } = this
return (width > 0 && height > 0) ? { width, height } : null
}
}
\ No newline at end of file
import { FaceDetectionNet } from './types';
export class FaceDetectionResult {
private score: number
private top: number
private left: number
private bottom: number
private right: number
constructor(
score: number,
top: number,
left: number,
bottom: number,
right: number
) {
this.score = score
this.top = Math.max(0, top),
this.left = Math.max(0, left),
this.bottom = Math.min(1.0, bottom),
this.right = Math.min(1.0, right)
}
public forSize(width: number, height: number): FaceDetectionNet.Detection {
return {
score: this.score,
box: {
top: this.top * height,
left: this.left * width,
bottom: this.bottom * height,
right: this.right * width
}
}
}
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
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(
x: tf.Tensor4D,
params: FaceDetectionNet.BoxPredictionParams
) {
return tf.tidy(() => {
const batchSize = x.shape[0]
const boxPredictionEncoding = tf.reshape(
convWithBias(x, params.box_encoding_predictor_params),
[batchSize, -1, 1, 4]
)
const classPrediction = tf.reshape(
convWithBias(x, params.class_predictor_params),
[batchSize, -1, 3]
)
return {
boxPredictionEncoding,
classPrediction
}
})
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { FaceDetectionNet } from './types';
function extractorsFactory(extractWeights: (numWeights: number) => Float32Array) {
function extractDepthwiseConvParams(numChannels: number): FaceDetectionNet.MobileNetV1.DepthwiseConvParams {
const filters = tf.tensor4d(extractWeights(3 * 3 * numChannels), [3, 3, numChannels, 1])
const batch_norm_scale = tf.tensor1d(extractWeights(numChannels))
const batch_norm_offset = tf.tensor1d(extractWeights(numChannels))
const batch_norm_mean = tf.tensor1d(extractWeights(numChannels))
const batch_norm_variance = tf.tensor1d(extractWeights(numChannels))
return {
filters,
batch_norm_scale,
batch_norm_offset,
batch_norm_mean,
batch_norm_variance
}
}
function extractConvWithBiasParams(
channelsIn: number,
channelsOut: number,
filterSize: number
): FaceDetectionNet.ConvWithBiasParams {
const filters = tf.tensor4d(
extractWeights(channelsIn * channelsOut * filterSize * filterSize),
[filterSize, filterSize, channelsIn, channelsOut]
)
const bias = tf.tensor1d(extractWeights(channelsOut))
return {
filters,
bias
}
}
function extractPointwiseConvParams(
channelsIn: number,
channelsOut: number,
filterSize: number
): FaceDetectionNet.PointwiseConvParams {
const {
filters,
bias
} = extractConvWithBiasParams(channelsIn, channelsOut, filterSize)
return {
filters,
batch_norm_offset: bias
}
}
function extractConvPairParams(channelsIn: number, channelsOut: number): FaceDetectionNet.MobileNetV1.ConvPairParams {
const depthwise_conv_params = extractDepthwiseConvParams(channelsIn)
const pointwise_conv_params = extractPointwiseConvParams(channelsIn, channelsOut, 1)
return {
depthwise_conv_params,
pointwise_conv_params
}
}
function extractMobilenetV1Params(): FaceDetectionNet.MobileNetV1.Params {
const conv_0_params = extractPointwiseConvParams(3, 32, 3)
const channelNumPairs = [
[32, 64],
[64, 128],
[128, 128],
[128, 256],
[256, 256],
[256, 512],
[512, 512],
[512, 512],
[512, 512],
[512, 512],
[512, 512],
[512, 1024],
[1024, 1024]
]
const conv_pair_params = channelNumPairs.map(
([channelsIn, channelsOut]) => extractConvPairParams(channelsIn, channelsOut)
)
return {
conv_0_params,
conv_pair_params
}
}
function extractPredictionLayerParams(): FaceDetectionNet.PredictionLayerParams {
const conv_0_params = extractPointwiseConvParams(1024, 256, 1)
const conv_1_params = extractPointwiseConvParams(256, 512, 3)
const conv_2_params = extractPointwiseConvParams(512, 128, 1)
const conv_3_params = extractPointwiseConvParams(128, 256, 3)
const conv_4_params = extractPointwiseConvParams(256, 128, 1)
const conv_5_params = extractPointwiseConvParams(128, 256, 3)
const conv_6_params = extractPointwiseConvParams(256, 64, 1)
const conv_7_params = extractPointwiseConvParams(64, 128, 3)
const box_encoding_0_predictor_params = extractConvWithBiasParams(512, 12, 1)
const class_predictor_0_params = extractConvWithBiasParams(512, 9, 1)
const box_encoding_1_predictor_params = extractConvWithBiasParams(1024, 24, 1)
const class_predictor_1_params = extractConvWithBiasParams(1024, 18, 1)
const box_encoding_2_predictor_params = extractConvWithBiasParams(512, 24, 1)
const class_predictor_2_params = extractConvWithBiasParams(512, 18, 1)
const box_encoding_3_predictor_params = extractConvWithBiasParams(256, 24, 1)
const class_predictor_3_params = extractConvWithBiasParams(256, 18, 1)
const box_encoding_4_predictor_params = extractConvWithBiasParams(256, 24, 1)
const class_predictor_4_params = extractConvWithBiasParams(256, 18, 1)
const box_encoding_5_predictor_params = extractConvWithBiasParams(128, 24, 1)
const class_predictor_5_params = extractConvWithBiasParams(128, 18, 1)
const box_predictor_0_params = {
box_encoding_predictor_params: box_encoding_0_predictor_params,
class_predictor_params: class_predictor_0_params
}
const box_predictor_1_params = {
box_encoding_predictor_params: box_encoding_1_predictor_params,
class_predictor_params: class_predictor_1_params
}
const box_predictor_2_params = {
box_encoding_predictor_params: box_encoding_2_predictor_params,
class_predictor_params: class_predictor_2_params
}
const box_predictor_3_params = {
box_encoding_predictor_params: box_encoding_3_predictor_params,
class_predictor_params: class_predictor_3_params
}
const box_predictor_4_params = {
box_encoding_predictor_params: box_encoding_4_predictor_params,
class_predictor_params: class_predictor_4_params
}
const box_predictor_5_params = {
box_encoding_predictor_params: box_encoding_5_predictor_params,
class_predictor_params: class_predictor_5_params
}
return {
conv_0_params,
conv_1_params,
conv_2_params,
conv_3_params,
conv_4_params,
conv_5_params,
conv_6_params,
conv_7_params,
box_predictor_0_params,
box_predictor_1_params,
box_predictor_2_params,
box_predictor_3_params,
box_predictor_4_params,
box_predictor_5_params
}
}
return {
extractMobilenetV1Params,
extractPredictionLayerParams
}
}
export function extractParams(weights: Float32Array): FaceDetectionNet.NetParams {
const extractWeights = (numWeights: number): Float32Array => {
const ret = weights.slice(0, numWeights)
weights = weights.slice(numWeights)
return ret
}
const {
extractMobilenetV1Params,
extractPredictionLayerParams
} = extractorsFactory(extractWeights)
const mobilenetv1_params = extractMobilenetV1Params()
const prediction_layer_params = extractPredictionLayerParams()
const extra_dim = tf.tensor3d(
extractWeights(5118 * 4),
[1, 5118, 4]
)
const output_layer_params = {
extra_dim
}
if (weights.length !== 0) {
throw new Error(`weights remaing after extract: ${weights.length}`)
}
return {
mobilenetv1_params,
prediction_layer_params,
output_layer_params
}
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { NetInput } from '../NetInput';
import { getImageTensor, padToSquare } from '../transformInputs';
import { TNetInput } from '../types';
import { extractParams } from './extractParams';
import { FaceDetectionResult } from './FaceDetectionResult';
import { mobileNetV1 } from './mobileNetV1';
import { nonMaxSuppression } from './nonMaxSuppression';
import { outputLayer } from './outputLayer';
import { predictionLayer } from './predictionLayer';
import { resizeLayer } from './resizeLayer';
export function faceDetectionNet(weights: Float32Array) {
const params = extractParams(weights)
function forwardTensor(imgTensor: tf.Tensor4D) {
return tf.tidy(() => {
const resized = resizeLayer(imgTensor) as tf.Tensor4D
const features = mobileNetV1(resized, params.mobilenetv1_params)
const {
boxPredictions,
classPredictions
} = predictionLayer(features.out, features.conv11, params.prediction_layer_params)
return outputLayer(boxPredictions, classPredictions, params.output_layer_params)
})
}
function forward(input: tf.Tensor | NetInput | TNetInput) {
return tf.tidy(
() => forwardTensor(padToSquare(getImageTensor(input)))
)
}
async function locateFaces(
input: tf.Tensor | NetInput,
minConfidence: number = 0.8,
maxResults: number = 100,
): Promise<FaceDetectionResult[]> {
let paddedHeightRelative = 1, paddedWidthRelative = 1
const {
boxes: _boxes,
scores: _scores
} = tf.tidy(() => {
let imgTensor = getImageTensor(input)
const [_, height, width] = imgTensor.shape
imgTensor = padToSquare(imgTensor)
paddedHeightRelative = imgTensor.shape[1] / height
paddedWidthRelative = imgTensor.shape[2] / width
return forwardTensor(imgTensor)
})
// TODO batches
const boxes = _boxes[0]
const scores = _scores[0]
for (let i = 1; i < _boxes.length; i++) {
_boxes[i].dispose()
_scores[i].dispose()
}
// TODO find a better way to filter by minConfidence
const scoresData = Array.from(await scores.data())
const iouThreshold = 0.5
const indices = nonMaxSuppression(
boxes,
scoresData,
maxResults,
iouThreshold,
minConfidence
)
const results = indices
.map(idx => new FaceDetectionResult(
scoresData[idx],
boxes.get(idx, 0) * paddedHeightRelative,
boxes.get(idx, 1) * paddedWidthRelative,
boxes.get(idx, 2) * paddedHeightRelative,
boxes.get(idx, 3) * paddedWidthRelative
))
boxes.dispose()
scores.dispose()
return results
}
return {
forward,
locateFaces
}
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { pointwiseConvLayer } from './pointwiseConvLayer';
import { FaceDetectionNet } from './types';
const epsilon = 0.0010000000474974513
function depthwiseConvLayer(
x: tf.Tensor4D,
params: FaceDetectionNet.MobileNetV1.DepthwiseConvParams,
strides: [number, number]
) {
return tf.tidy(() => {
let out = tf.depthwiseConv2d(x, params.filters, strides, 'same')
out = tf.batchNormalization<tf.Rank.R4>(
out,
params.batch_norm_mean,
params.batch_norm_variance,
epsilon,
params.batch_norm_scale,
params.batch_norm_offset
)
return tf.clipByValue(out, 0, 6)
})
}
function getStridesForLayerIdx(layerIdx: number): [number, number] {
return [2, 4, 6, 12].some(idx => idx === layerIdx) ? [2, 2] : [1, 1]
}
export function mobileNetV1(x: tf.Tensor4D, params: FaceDetectionNet.MobileNetV1.Params) {
return tf.tidy(() => {
let conv11 = null
let out = pointwiseConvLayer(x, params.conv_0_params, [2, 2])
params.conv_pair_params.forEach((param, i) => {
const layerIdx = i + 1
const depthwiseConvStrides = getStridesForLayerIdx(layerIdx)
out = depthwiseConvLayer(out, param.depthwise_conv_params, depthwiseConvStrides)
out = pointwiseConvLayer(out, param.pointwise_conv_params, [1, 1])
if (layerIdx === 11) {
conv11 = out
}
})
if (conv11 === null) {
throw new Error('mobileNetV1 - output of conv layer 11 is null')
}
return {
out,
conv11: conv11 as any
}
})
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'
export function nonMaxSuppression(
boxes: tf.Tensor2D,
scores: number[],
maxOutputSize: number,
iouThreshold: number,
scoreThreshold: number
): number[] {
const numBoxes = boxes.shape[0]
const outputSize = Math.min(
maxOutputSize,
numBoxes
)
const candidates = scores
.map((score, boxIndex) => ({ score, boxIndex }))
.filter(c => c.score > scoreThreshold)
.sort((c1, c2) => c2.score - c1.score)
const suppressFunc = (x: number) => x <= iouThreshold ? 1 : 0
const selected: number[] = []
candidates.forEach(c => {
if (selected.length >= outputSize) {
return
}
const originalScore = c.score
for (let j = selected.length - 1; j >= 0; --j) {
const iou = IOU(boxes, c.boxIndex, selected[j])
if (iou === 0.0) {
continue
}
c.score *= suppressFunc(iou)
if (c.score <= scoreThreshold) {
break
}
}
if (originalScore === c.score) {
selected.push(c.boxIndex)
}
})
return selected
}
function IOU(boxes: tf.Tensor2D, i: number, j: number) {
const yminI = Math.min(boxes.get(i, 0), boxes.get(i, 2))
const xminI = Math.min(boxes.get(i, 1), boxes.get(i, 3))
const ymaxI = Math.max(boxes.get(i, 0), boxes.get(i, 2))
const xmaxI = Math.max(boxes.get(i, 1), boxes.get(i, 3))
const yminJ = Math.min(boxes.get(j, 0), boxes.get(j, 2))
const xminJ = Math.min(boxes.get(j, 1), boxes.get(j, 3))
const ymaxJ = Math.max(boxes.get(j, 0), boxes.get(j, 2))
const xmaxJ = Math.max(boxes.get(j, 1), boxes.get(j, 3))
const areaI = (ymaxI - yminI) * (xmaxI - xminI)
const areaJ = (ymaxJ - yminJ) * (xmaxJ - xminJ)
if (areaI <= 0 || areaJ <= 0) {
return 0.0
}
const intersectionYmin = Math.max(yminI, yminJ)
const intersectionXmin = Math.max(xminI, xminJ)
const intersectionYmax = Math.min(ymaxI, ymaxJ)
const intersectionXmax = Math.min(xmaxI, xmaxJ)
const intersectionArea =
Math.max(intersectionYmax - intersectionYmin, 0.0) *
Math.max(intersectionXmax - intersectionXmin, 0.0)
return intersectionArea / (areaI + areaJ - intersectionArea)
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { FaceDetectionNet } from './types';
function getCenterCoordinatesAndSizesLayer(x: tf.Tensor2D) {
const vec = tf.unstack(tf.transpose(x, [1, 0]))
const sizes = [
tf.sub(vec[2], vec[0]),
tf.sub(vec[3], vec[1])
]
const centers = [
tf.add(vec[0], tf.div(sizes[0], tf.scalar(2))),
tf.add(vec[1], tf.div(sizes[1], tf.scalar(2)))
]
return {
sizes,
centers
}
}
function decodeBoxesLayer(x0: tf.Tensor2D, x1: tf.Tensor2D) {
const {
sizes,
centers
} = getCenterCoordinatesAndSizesLayer(x0)
const vec = tf.unstack(tf.transpose(x1, [1, 0]))
const div0_out = tf.div(tf.mul(tf.exp(tf.div(vec[2], tf.scalar(5))), sizes[0]), tf.scalar(2))
const add0_out = tf.add(tf.mul(tf.div(vec[0], tf.scalar(10)), sizes[0]), centers[0])
const div1_out = tf.div(tf.mul(tf.exp(tf.div(vec[3], tf.scalar(5))), sizes[1]), tf.scalar(2))
const add1_out = tf.add(tf.mul(tf.div(vec[1], tf.scalar(10)), sizes[1]), centers[1])
return tf.transpose(
tf.stack([
tf.sub(add0_out, div0_out),
tf.sub(add1_out, div1_out),
tf.add(add0_out, div0_out),
tf.add(add1_out, div1_out)
]),
[1, 0]
)
}
export function outputLayer(
boxPredictions: tf.Tensor4D,
classPredictions: tf.Tensor4D,
params: FaceDetectionNet.OutputLayerParams
) {
return tf.tidy(() => {
const batchSize = boxPredictions.shape[0]
let boxes = decodeBoxesLayer(
tf.reshape(tf.tile(params.extra_dim, [batchSize, 1, 1]), [-1, 4]) as tf.Tensor2D,
tf.reshape(boxPredictions, [-1, 4]) as tf.Tensor2D
)
boxes = tf.reshape(
boxes,
[batchSize, (boxes.shape[0] / batchSize), 4]
)
const scoresAndClasses = tf.sigmoid(tf.slice(classPredictions, [0, 0, 1], [-1, -1, -1]))
let scores = tf.slice(scoresAndClasses, [0, 0, 0], [-1, -1, 1]) as tf.Tensor
scores = tf.reshape(
scores,
[batchSize, scores.shape[1]]
)
const boxesByBatch = tf.unstack(boxes) as tf.Tensor2D[]
const scoresByBatch = tf.unstack(scores) as tf.Tensor1D[]
return {
boxes: boxesByBatch,
scores: scoresByBatch
}
})
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { FaceDetectionNet } from './types';
export function pointwiseConvLayer(
x: tf.Tensor4D,
params: FaceDetectionNet.PointwiseConvParams,
strides: [number, number]
) {
return tf.tidy(() => {
let out = tf.conv2d(x, params.filters, strides, 'same')
out = tf.add(out, params.batch_norm_offset)
return tf.clipByValue(out, 0, 6)
})
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { boxPredictionLayer } from './boxPredictionLayer';
import { pointwiseConvLayer } from './pointwiseConvLayer';
import { FaceDetectionNet } from './types';
export function predictionLayer(
x: tf.Tensor4D,
conv11: tf.Tensor4D,
params: FaceDetectionNet.PredictionLayerParams
) {
return tf.tidy(() => {
const conv0 = pointwiseConvLayer(x, params.conv_0_params, [1, 1])
const conv1 = pointwiseConvLayer(conv0, params.conv_1_params, [2, 2])
const conv2 = pointwiseConvLayer(conv1, params.conv_2_params, [1, 1])
const conv3 = pointwiseConvLayer(conv2, params.conv_3_params, [2, 2])
const conv4 = pointwiseConvLayer(conv3, params.conv_4_params, [1, 1])
const conv5 = pointwiseConvLayer(conv4, params.conv_5_params, [2, 2])
const conv6 = pointwiseConvLayer(conv5, params.conv_6_params, [1, 1])
const conv7 = pointwiseConvLayer(conv6, params.conv_7_params, [2, 2])
const boxPrediction0 = boxPredictionLayer(conv11, params.box_predictor_0_params)
const boxPrediction1 = boxPredictionLayer(x, params.box_predictor_1_params)
const boxPrediction2 = boxPredictionLayer(conv1, params.box_predictor_2_params)
const boxPrediction3 = boxPredictionLayer(conv3, params.box_predictor_3_params)
const boxPrediction4 = boxPredictionLayer(conv5, params.box_predictor_4_params)
const boxPrediction5 = boxPredictionLayer(conv7, params.box_predictor_5_params)
const boxPredictions = tf.concat([
boxPrediction0.boxPredictionEncoding,
boxPrediction1.boxPredictionEncoding,
boxPrediction2.boxPredictionEncoding,
boxPrediction3.boxPredictionEncoding,
boxPrediction4.boxPredictionEncoding,
boxPrediction5.boxPredictionEncoding
], 1) as tf.Tensor4D
const classPredictions = tf.concat([
boxPrediction0.classPrediction,
boxPrediction1.classPrediction,
boxPrediction2.classPrediction,
boxPrediction3.classPrediction,
boxPrediction4.classPrediction,
boxPrediction5.classPrediction
], 1) as tf.Tensor4D
return {
boxPredictions,
classPredictions
}
})
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
const resizedImageSize = [512, 512] as [number, number]
const weight = tf.scalar(0.007843137718737125)
const bias = tf.scalar(1)
export function resizeLayer(x: tf.Tensor4D) {
return tf.tidy(() => {
const resized = tf.image.resizeBilinear(x, resizedImageSize, false)
return tf.sub(tf.mul(resized, weight), bias)
})
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
export namespace FaceDetectionNet {
export type PointwiseConvParams = {
filters: tf.Tensor4D
batch_norm_offset: tf.Tensor1D
}
export namespace MobileNetV1 {
export type DepthwiseConvParams = {
filters: tf.Tensor4D
batch_norm_scale: tf.Tensor1D
batch_norm_offset: tf.Tensor1D
batch_norm_mean: tf.Tensor1D
batch_norm_variance: tf.Tensor1D
}
export type ConvPairParams = {
depthwise_conv_params: DepthwiseConvParams
pointwise_conv_params: PointwiseConvParams
}
export type Params = {
conv_0_params: PointwiseConvParams
conv_pair_params: ConvPairParams[]
}
}
export type ConvWithBiasParams = {
filters: tf.Tensor4D
bias: tf.Tensor1D
}
export type BoxPredictionParams = {
box_encoding_predictor_params: ConvWithBiasParams
class_predictor_params: ConvWithBiasParams
}
export type PredictionLayerParams = {
conv_0_params: PointwiseConvParams
conv_1_params: PointwiseConvParams
conv_2_params: PointwiseConvParams
conv_3_params: PointwiseConvParams
conv_4_params: PointwiseConvParams
conv_5_params: PointwiseConvParams
conv_6_params: PointwiseConvParams
conv_7_params: PointwiseConvParams
box_predictor_0_params: BoxPredictionParams
box_predictor_1_params: BoxPredictionParams
box_predictor_2_params: BoxPredictionParams
box_predictor_3_params: BoxPredictionParams
box_predictor_4_params: BoxPredictionParams
box_predictor_5_params: BoxPredictionParams
}
export type OutputLayerParams = {
extra_dim: tf.Tensor3D
}
export type NetParams = {
mobilenetv1_params: MobileNetV1.Params,
prediction_layer_params: PredictionLayerParams,
output_layer_params: OutputLayerParams
}
export type Detection = {
score: number
box: {
top: number,
left: number,
right: number,
bottom: number
}
}
}
import * as tf from '@tensorflow/tfjs-core';
import { scale, ScaleLayerParams } from './scaleLayer';
import { scale } from './scaleLayer';
import { FaceRecognitionNet } from './types';
export type ConvParams = {
filters: tf.Tensor4D
biases: tf.Tensor1D
}
export type ConvLayerParams = {
conv: ConvParams
scale: ScaleLayerParams
}
function convLayer(
x: tf.Tensor4D,
params: ConvLayerParams,
params: FaceRecognitionNet.ConvLayerParams,
stride: number,
withRelu: boolean,
padding: 'valid' | 'same' = 'same'
......@@ -27,14 +19,14 @@ function convLayer(
return withRelu ? tf.relu(out) : out
}
export function conv(x: tf.Tensor4D, params: ConvLayerParams) {
export function conv(x: tf.Tensor4D, params: FaceRecognitionNet.ConvLayerParams) {
return convLayer(x, params, 1, true)
}
export function convNoRelu(x: tf.Tensor4D, params: ConvLayerParams) {
export function convNoRelu(x: tf.Tensor4D, params: FaceRecognitionNet.ConvLayerParams) {
return convLayer(x, params, 1, false)
}
export function convDown(x: tf.Tensor4D, params: ConvLayerParams) {
export function convDown(x: tf.Tensor4D, params: FaceRecognitionNet.ConvLayerParams) {
return convLayer(x, params, 2, true, 'valid')
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { ConvLayerParams } from './convLayer';
import { FaceRecognitionNetParams } from './FaceRecognitionNetParams';
import { ResidualLayerParams } from './residualLayer';
import { ScaleLayerParams } from './scaleLayer';
function isFloat(num: number) {
return num % 1 !== 0
}
import { isFloat } from '../utils';
import { FaceRecognitionNet } from './types';
function extractorsFactory(extractWeights: (numWeights: number) => Float32Array) {
......@@ -26,7 +20,7 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array)
)
}
function extractScaleLayerParams(numWeights: number): ScaleLayerParams {
function extractScaleLayerParams(numWeights: number): FaceRecognitionNet.ScaleLayerParams {
const weights = tf.tensor1d(extractWeights(numWeights))
const biases = tf.tensor1d(extractWeights(numWeights))
return {
......@@ -35,7 +29,7 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array)
}
}
function extractConvLayerParams(numFilterValues: number, numFilters: number, filterSize: number): ConvLayerParams {
function extractConvLayerParams(numFilterValues: number, numFilters: number, filterSize: number): FaceRecognitionNet.ConvLayerParams {
const conv_filters = extractFilterValues(numFilterValues, numFilters, filterSize)
const conv_biases = tf.tensor1d(extractWeights(numFilters))
const scale = extractScaleLayerParams(numFilters)
......@@ -49,9 +43,9 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array)
}
}
function extractResidualLayerParams(numFilterValues: number, numFilters: number, filterSize: number, isDown: boolean = false): ResidualLayerParams {
const conv1: ConvLayerParams = extractConvLayerParams((isDown ? 0.5 : 1) * numFilterValues, numFilters, filterSize)
const conv2: ConvLayerParams = extractConvLayerParams(numFilterValues, numFilters, filterSize)
function extractResidualLayerParams(numFilterValues: number, numFilters: number, filterSize: number, isDown: boolean = false): FaceRecognitionNet.ResidualLayerParams {
const conv1: FaceRecognitionNet.ConvLayerParams = extractConvLayerParams((isDown ? 0.5 : 1) * numFilterValues, numFilters, filterSize)
const conv2: FaceRecognitionNet.ConvLayerParams = extractConvLayerParams(numFilterValues, numFilters, filterSize)
return {
conv1,
......@@ -66,7 +60,7 @@ function extractorsFactory(extractWeights: (numWeights: number) => Float32Array)
}
export function extractParams(weights: Float32Array): FaceRecognitionNetParams {
export function extractParams(weights: Float32Array): FaceRecognitionNet.NetParams {
const extractWeights = (numWeights: number): Float32Array => {
const ret = weights.slice(0, numWeights)
weights = weights.slice(numWeights)
......
import * as tf from '@tensorflow/tfjs-core';
import { normalize } from '../normalize';
import { NetInput } from '../NetInput';
import { getImageTensor, padToSquare } from '../transformInputs';
import { TNetInput } from '../types';
import { convDown } from './convLayer';
import { extractParams } from './extractParams';
import { normalize } from './normalize';
import { residual, residualDown } from './residualLayer';
export function faceRecognitionNet(weights: Float32Array) {
const params = extractParams(weights)
function forward(input: number[] | ImageData) {
function forward(input: tf.Tensor | NetInput | TNetInput) {
return tf.tidy(() => {
const x = normalize(input)
const x = normalize(padToSquare(getImageTensor(input)))
let out = convDown(x, params.conv32_down)
out = tf.maxPool(out, 3, 2, 'valid')
......@@ -42,8 +44,19 @@ export function faceRecognitionNet(weights: Float32Array) {
})
}
const computeFaceDescriptor = (input: number[] | ImageData) => forward(input).data()
const computeFaceDescriptorSync = (input: number[] | ImageData) => forward(input).dataSync()
const computeFaceDescriptor = async (input: tf.Tensor | NetInput | TNetInput) => {
const result = forward(input)
const data = await result.data()
result.dispose()
return data
}
const computeFaceDescriptorSync = (input: tf.Tensor | NetInput | TNetInput) => {
const result = forward(input)
const data = result.dataSync()
result.dispose()
return data
}
return {
computeFaceDescriptor,
......
import * as tf from '@tensorflow/tfjs-core';
export function normalize(input: number[] | ImageData): tf.Tensor4D {
export function normalize(x: tf.Tensor4D): tf.Tensor4D {
return tf.tidy(() => {
const avg_r = tf.fill([1, 150, 150, 1], 122.782);
const avg_g = tf.fill([1, 150, 150, 1], 117.001);
const avg_b = tf.fill([1, 150, 150, 1], 104.298);
const avg_rgb = tf.concat([avg_r, avg_g, avg_b], 3)
const x = input instanceof ImageData
? tf.cast(tf.reshape(tf.fromPixels(input), [1, 150, 150, 3]), 'float32')
: tf.tensor4d(input, [1, 150, 150, 3])
return tf.div(tf.sub(x, avg_rgb), tf.fill(x.shape, 256))
return tf.div(tf.sub(x, avg_rgb), tf.scalar(256))
})
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { conv, convNoRelu, ConvLayerParams, convDown } from './convLayer';
import { conv, convDown, convNoRelu } from './convLayer';
import { FaceRecognitionNet } from './types';
export type ResidualLayerParams = {
conv1: ConvLayerParams
conv2: ConvLayerParams
}
export function residual(x: tf.Tensor4D, params: ResidualLayerParams): tf.Tensor4D {
export function residual(x: tf.Tensor4D, params: FaceRecognitionNet.ResidualLayerParams): tf.Tensor4D {
let out = conv(x, params.conv1)
out = convNoRelu(out, params.conv2)
out = tf.add(out, x)
......@@ -15,7 +11,7 @@ export function residual(x: tf.Tensor4D, params: ResidualLayerParams): tf.Tensor
return out
}
export function residualDown(x: tf.Tensor4D, params: ResidualLayerParams): tf.Tensor4D {
export function residualDown(x: tf.Tensor4D, params: FaceRecognitionNet.ResidualLayerParams): tf.Tensor4D {
let out = convDown(x, params.conv1)
out = convNoRelu(out, params.conv2)
......
import * as tf from '@tensorflow/tfjs-core';
import { FaceRecognitionNet } from './types';
export type ScaleLayerParams = {
weights: tf.Tensor1D
biases: tf.Tensor1D
}
export function scale(x: tf.Tensor4D, params: ScaleLayerParams): tf.Tensor4D {
export function scale(x: tf.Tensor4D, params: FaceRecognitionNet.ScaleLayerParams): tf.Tensor4D {
return tf.add(tf.mul(x, params.weights), params.biases)
}
\ No newline at end of file
}
import * as tf from '@tensorflow/tfjs-core';
import { ConvLayerParams } from './convLayer';
import { ResidualLayerParams } from './residualLayer';
export namespace FaceRecognitionNet {
export type ScaleLayerParams = {
weights: tf.Tensor1D
biases: tf.Tensor1D
}
export type ResidualLayerParams = {
conv1: ConvLayerParams
conv2: ConvLayerParams
}
export type ConvParams = {
filters: tf.Tensor4D
biases: tf.Tensor1D
}
export type ConvLayerParams = {
conv: ConvParams
scale: ScaleLayerParams
}
export type NetParams = {
conv32_down: ConvLayerParams
conv32_1: ResidualLayerParams
conv32_2: ResidualLayerParams
conv32_3: ResidualLayerParams
conv64_down: ResidualLayerParams
conv64_1: ResidualLayerParams
conv64_2: ResidualLayerParams
conv64_3: ResidualLayerParams
conv128_down: ResidualLayerParams
conv128_1: ResidualLayerParams
conv128_2: ResidualLayerParams
conv256_down: ResidualLayerParams
conv256_1: ResidualLayerParams
conv256_2: ResidualLayerParams
conv256_down_out: ResidualLayerParams
fc: tf.Tensor2D
}
export type FaceRecognitionNetParams = {
conv32_down: ConvLayerParams
conv32_1: ResidualLayerParams
conv32_2: ResidualLayerParams
conv32_3: ResidualLayerParams
conv64_down: ResidualLayerParams
conv64_1: ResidualLayerParams
conv64_2: ResidualLayerParams
conv64_3: ResidualLayerParams
conv128_down: ResidualLayerParams
conv128_1: ResidualLayerParams
conv128_2: ResidualLayerParams
conv256_down: ResidualLayerParams
conv256_1: ResidualLayerParams
conv256_2: ResidualLayerParams
conv256_down_out: ResidualLayerParams
fc: tf.Tensor2D
}
\ No newline at end of file
import { euclideanDistance } from './euclideanDistance';
import { faceDetectionNet } from './faceDetectionNet';
import { faceRecognitionNet } from './faceRecognitionNet';
import { normalize } from './normalize';
import { NetInput } from './NetInput';
export {
euclideanDistance,
faceDetectionNet,
faceRecognitionNet,
normalize
}
\ No newline at end of file
NetInput
}
export * from './utils'
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { NetInput } from './NetInput';
import { TNetInput } from './types';
export function padToSquare(imgTensor: tf.Tensor4D): tf.Tensor4D {
return tf.tidy(() => {
const [_, height, width] = imgTensor.shape
if (height === width) {
return imgTensor
}
if (height > width) {
const pad = tf.fill([1, height, height - width, 3], 0) as tf.Tensor4D
return tf.concat([imgTensor, pad], 2)
}
const pad = tf.fill([1, width - height, width, 3], 0) as tf.Tensor4D
return tf.concat([imgTensor, pad], 1)
})
}
export function getImageTensor(input: tf.Tensor | NetInput | TNetInput): tf.Tensor4D {
return tf.tidy(() => {
if (input instanceof tf.Tensor) {
const rank = input.shape.length
if (rank !== 3 && rank !== 4) {
throw new Error('input tensor must be of rank 3 or 4')
}
return (rank === 3 ? input.expandDims(0) : input).toFloat() as tf.Tensor4D
}
const netInput = input instanceof NetInput ? input : new NetInput(input)
return tf.concat(
netInput.canvases.map(canvas =>
tf.fromPixels(canvas).expandDims(0).toFloat()
)
) as tf.Tensor4D
})
}
\ No newline at end of file
export type TMediaElement = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement
export type TNetInputArg = string | TMediaElement
export type TNetInput = TNetInputArg | Array<TNetInputArg>
export type Dimensions = {
width: number
height: number
}
export type DrawBoxOptions = {
lineWidth: number
color: string
}
export type DrawTextOptions = {
fontSize: number
fontStyle: string
color: string
}
\ No newline at end of file
import { FaceDetectionNet } from './faceDetectionNet/types';
import { DrawBoxOptions, DrawTextOptions } from './types';
export function isFloat(num: number) {
return num % 1 !== 0
}
export function round(num: number) {
return Math.floor(num * 100) / 100
}
export function getElement(arg: string | any) {
if (typeof arg === 'string') {
return document.getElementById(arg)
}
return arg
}
export function getContext2dOrThrow(canvas: HTMLCanvasElement): CanvasRenderingContext2D {
const ctx = canvas.getContext('2d')
if (!ctx) {
throw new Error('canvas 2d context is null')
}
return ctx
}
export function getMediaDimensions(media: HTMLImageElement | HTMLVideoElement) {
if (media instanceof HTMLVideoElement) {
return { width: media.videoWidth, height: media.videoHeight }
}
return media
}
export function bufferToImage(buf: Blob): Promise<HTMLImageElement> {
return new Promise((resolve, reject) => {
if (!(buf instanceof Blob)) {
return reject('bufferToImage - expected buf to be of type: Blob')
}
const reader = new FileReader()
reader.onload = () => {
const img = new Image()
img.onload = () => resolve(img)
img.onerror = reject
img.src = reader.result
}
reader.onerror = reject
reader.readAsDataURL(buf)
})
}
export function drawBox(
ctx: CanvasRenderingContext2D,
x: number,
y: number,
w: number,
h: number,
options: DrawBoxOptions
) {
ctx.strokeStyle = options.color
ctx.lineWidth = options.lineWidth
ctx.strokeRect(x, y, w, h)
}
export function drawText(
ctx: CanvasRenderingContext2D,
x: number,
y: number,
text: string,
options: DrawTextOptions
) {
ctx.fillStyle = options.color
ctx.font = `${options.fontSize}px ${options.fontStyle}`
ctx.fillText(text, x, y)
}
export function drawDetection(
canvasArg: string | HTMLCanvasElement,
detection: FaceDetectionNet.Detection | FaceDetectionNet.Detection[],
options?: DrawBoxOptions & DrawTextOptions & { withScore: boolean }
) {
const canvas = getElement(canvasArg)
if (!(canvas instanceof HTMLCanvasElement)) {
throw new Error('drawBox - expected canvas to be of type: HTMLCanvasElement')
}
const detectionArray = Array.isArray(detection)
? detection
: [detection]
detectionArray.forEach((det) => {
const {
score,
box
} = det
const {
left,
right,
top,
bottom
} = box
const {
color = 'blue',
lineWidth = 2,
fontSize = 20,
fontStyle = 'Georgia',
withScore = true
} = (options || {})
const padText = 2 + lineWidth
const ctx = getContext2dOrThrow(canvas)
drawBox(
ctx,
left,
top,
right - left,
bottom - top,
{ lineWidth, color }
)
if (withScore) {
drawText(
ctx,
left + padText,
top + (fontSize * 0.6) + padText,
`${round(score)}`,
{ fontSize, fontStyle, color }
)
}
})
}
\ No newline at end of file
{
"compilerOptions": {
//"allowUnreachableCode": true,
//"noUnusedLocals": false,
//"noUnusedParameters": false,
"removeComments": false,
"preserveConstEnums": true,
"emitDecoratorMetadata": true,
......@@ -7,8 +12,6 @@
"sourceMap": true,
"declaration": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noFallthroughCasesInSwitch": true,
......@@ -30,6 +33,10 @@
"indentSize": 2,
"tabSize": 2
},
"exclude": [
"node_modules",
"dist"
],
"include": [
"src"
]
......
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