UNPKG

ngx-face-api-js

Version:

Angular directives for face detection and face recognition in the browser. It is a wrapper for face-api.js, so it is not dependent on the browser implementation.

945 lines (927 loc) 34.1 kB
import { BrowserModule } from '@angular/platform-browser'; import { of, fromEvent, interval, Subscription, Subject, combineLatest } from 'rxjs'; import * as faceapi from 'face-api.js'; import { resizeResults, FaceDetection, draw, round, loadSsdMobilenetv1Model, loadMtcnnModel, loadFaceExpressionModel, loadFaceLandmarkModel, loadFaceRecognitionModel, loadTinyFaceDetectorModel, loadAgeGenderModel, DetectSingleFaceTask, DetectAllFacesTask } from 'face-api.js'; import { switchMap, shareReplay, map, startWith } from 'rxjs/operators'; import { ComponentPortal, PortalModule } from '@angular/cdk/portal'; import { __extends, __read, __awaiter, __generator, __spread } from 'tslib'; import { InjectionToken, Injectable, Inject, Optional, Component, ViewChild, ElementRef, Renderer2, HostListener, Injector, Directive, Input, NgModule } from '@angular/core'; import { OverlayConfig, Overlay, OverlayModule } from '@angular/cdk/overlay'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var DetectTask = /** @class */ (function () { function DetectTask(option) { var _this = this; this.type = option.type; this.tokens = option.tokens; this.realtime = option.realtime || false; this.target = new Promise((/** * @param {?} resolver * @return {?} */ function (resolver) { return (_this.targetResolver = resolver); })); } Object.defineProperty(DetectTask.prototype, "resolveTarget", { get: /** * @return {?} */ function () { return this.targetResolver; }, enumerable: true, configurable: true }); /** * @private * @param {?} patten * @param {?} target * @return {?} */ DetectTask.prototype.isMatchPattern = /** * @private * @param {?} patten * @param {?} target * @return {?} */ function (patten, target) { return patten.every((/** * @param {?} item * @return {?} */ function (item) { return target.includes(item); })); }; /** * @template THIS * @this {THIS} * @param {...?} tokens * @return {THIS} */ DetectTask.prototype.with = /** * @template THIS * @this {THIS} * @param {...?} tokens * @return {THIS} */ function () { var tokens = []; for (var _i = 0; _i < arguments.length; _i++) { tokens[_i] = arguments[_i]; } var _a; (_a = (/** @type {?} */ (this)).tokens).push.apply(_a, __spread(tokens)); return (/** @type {?} */ (this)); }; /** * @param {?=} option * @return {?} */ DetectTask.prototype.detect = /** * @param {?=} option * @return {?} */ function (option) { return __awaiter(this, void 0, void 0, function () { var t, _a, _b, _c, _d; return __generator(this, function (_e) { switch (_e.label) { case 0: if (!(this.type === 'all')) return [3 /*break*/, 2]; _b = (_a = faceapi).detectAllFaces; return [4 /*yield*/, this.target]; case 1: t = _b.apply(_a, [_e.sent(), option || undefined]); return [3 /*break*/, 4]; case 2: _d = (_c = faceapi).detectSingleFace; return [4 /*yield*/, this.target]; case 3: t = _d.apply(_c, [_e.sent(), option || undefined]); _e.label = 4; case 4: if (this.isMatchPattern(['expressions', 'landmarks', 'ageAndGender', 'descriptors'], this.tokens)) { if (t instanceof DetectSingleFaceTask) { return [2 /*return*/, t .withFaceLandmarks() .withFaceExpressions() .withAgeAndGender() .withFaceDescriptor() .run()]; } else if (t instanceof DetectAllFacesTask) { return [2 /*return*/, t .withFaceLandmarks() .withFaceExpressions() .withAgeAndGender() .withFaceDescriptors() .run()]; } } else if (this.isMatchPattern(['expressions', 'landmarks', 'descriptors'], this.tokens)) { if (t instanceof DetectSingleFaceTask) { return [2 /*return*/, t .withFaceLandmarks() .withFaceExpressions() .withFaceDescriptor() .run()]; } else if (t instanceof DetectAllFacesTask) { return [2 /*return*/, t .withFaceLandmarks() .withFaceExpressions() .withFaceDescriptors() .run()]; } } else if (this.isMatchPattern(['expressions', 'landmarks', 'ageAndGender'], this.tokens)) { return [2 /*return*/, t .withFaceLandmarks() .withFaceExpressions() .withAgeAndGender() .run()]; } else if (this.isMatchPattern(['expressions', 'landmarks'], this.tokens)) { return [2 /*return*/, t .withFaceLandmarks() .withFaceExpressions() .run()]; } else if (this.isMatchPattern(['expressions', 'ageAndGender'], this.tokens)) { return [2 /*return*/, t .withFaceExpressions() .withAgeAndGender() .run()]; } else if (this.isMatchPattern(['expressions'], this.tokens)) { return [2 /*return*/, t.withFaceExpressions().run()]; } else if (this.isMatchPattern(['landmarks', 'ageAndGender'], this.tokens)) { return [2 /*return*/, t .withFaceLandmarks() .withAgeAndGender() .run()]; } else if (this.isMatchPattern(['landmarks'], this.tokens)) { return [2 /*return*/, t.withFaceLandmarks().run()]; } return [2 /*return*/, t.run()]; } }); }); }; return DetectTask; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var FaceDetectionOptions = new InjectionToken('ngx-face-api-js.face-detection-options'); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var ExpressionsFeatureToken = 'expressions'; /** @type {?} */ var LandmarksFeatureToken = 'landmarks'; /** @type {?} */ var DescriptorsFeatureToken = 'descriptors'; /** @type {?} */ var AgeAndGenderToken = 'ageAndGender'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var SsdMobilenetv1Model = 'SsdMobilenetv1Model'; /** @type {?} */ var MtcnnModel = 'MtcnnModel'; /** @type {?} */ var FaceExpressionModel = 'FaceExpressionModel'; /** @type {?} */ var FaceLandmarkModel = 'FaceLandmarkModel'; /** @type {?} */ var FaceRecognitionModel = 'FaceRecognitionModel'; /** @type {?} */ var TinyFaceDetectorModel = 'TinyFaceDetectorModel'; /** @type {?} */ var AgeAndGenderModel = 'AgeAndGenderModel'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var ModelsUrl = new InjectionToken('ngx-face-api-js.models-url'); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var ModelLoaderService = /** @class */ (function () { function ModelLoaderService(modelUrl) { this.modelUrl = modelUrl; this.loadedModels = []; } /** * @private * @param {?} tokens * @return {?} */ ModelLoaderService.prototype.getReqiredModels = /** * @private * @param {?} tokens * @return {?} */ function (tokens) { var _a; return [SsdMobilenetv1Model].concat(Object.entries((_a = {}, _a[ExpressionsFeatureToken] = [FaceExpressionModel, SsdMobilenetv1Model], _a[LandmarksFeatureToken] = [FaceLandmarkModel, SsdMobilenetv1Model], _a[DescriptorsFeatureToken] = [FaceRecognitionModel], _a[AgeAndGenderToken] = [AgeAndGenderModel], _a)) .map((/** * @param {?} __0 * @return {?} */ function (_a) { var _b = __read(_a, 2), key = _b[0], models = _b[1]; return tokens.includes((/** @type {?} */ (key))) ? models : []; })) .reduce((/** * @param {?} a * @param {?} b * @return {?} */ function (a, b) { return a.concat(b); })) .filter((/** * @param {?} v * @param {?} i * @param {?} arr * @return {?} */ function (v, i, arr) { return arr.indexOf(v) === i; }))); }; /** * @private * @param {?} model * @return {?} */ ModelLoaderService.prototype.mapLoadFunction = /** * @private * @param {?} model * @return {?} */ function (model) { switch (model) { case SsdMobilenetv1Model: return loadSsdMobilenetv1Model; case MtcnnModel: return loadMtcnnModel; case FaceExpressionModel: return loadFaceExpressionModel; case FaceLandmarkModel: return loadFaceLandmarkModel; case FaceRecognitionModel: return loadFaceRecognitionModel; case TinyFaceDetectorModel: return loadTinyFaceDetectorModel; case AgeAndGenderModel: return loadAgeGenderModel; } }; /** * @param {?} model * @return {?} */ ModelLoaderService.prototype.isLoaded = /** * @param {?} model * @return {?} */ function (model) { return this.loadedModels.includes(model); }; /** * @param {...?} models * @return {?} */ ModelLoaderService.prototype.load = /** * @param {...?} models * @return {?} */ function () { var models = []; for (var _i = 0; _i < arguments.length; _i++) { models[_i] = arguments[_i]; } return __awaiter(this, void 0, void 0, function () { var loadTargetModels; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: loadTargetModels = models.filter((/** * @param {?} m * @return {?} */ function (m) { return _this.isLoaded(m) === false; })); return [4 /*yield*/, Promise.all(loadTargetModels .map((/** * @param {?} m * @return {?} */ function (m) { return _this.mapLoadFunction(m); })) .map((/** * @param {?} load * @return {?} */ function (load) { return load(_this.modelUrl); })))]; case 1: _a.sent(); if (loadTargetModels.length >= 0) { this.loadedModels = loadTargetModels.concat(this.loadedModels); } return [2 /*return*/]; } }); }); }; /** * @param {?} tokens * @return {?} */ ModelLoaderService.prototype.loadForFeature = /** * @param {?} tokens * @return {?} */ function (tokens) { return __awaiter(this, void 0, void 0, function () { var reqiredModels; return __generator(this, function (_a) { switch (_a.label) { case 0: reqiredModels = this.getReqiredModels(tokens); console.log({ reqiredModels: reqiredModels }); return [4 /*yield*/, this.load.apply(this, __spread(reqiredModels))]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; ModelLoaderService.decorators = [ { type: Injectable } ]; /** @nocollapse */ ModelLoaderService.ctorParameters = function () { return [ { type: String, decorators: [{ type: Inject, args: [ModelsUrl,] }] } ]; }; return ModelLoaderService; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var FaceDetectorService = /** @class */ (function () { function FaceDetectorService(modelLoader, option) { this.modelLoader = modelLoader; this.option = option; } /** * @param {?} task * @return {?} */ FaceDetectorService.prototype.detect = /** * @param {?} task * @return {?} */ function (task) { var _this = this; if (task.realtime === true) { return of(task).pipe(switchMap((/** * @param {?} t * @return {?} */ function (t) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, t.target]; case 1: return [2 /*return*/, _a.sent()]; } }); }); })), switchMap((/** * @param {?} video * @return {?} */ function (video) { return fromEvent(video, 'loadeddata'); })), switchMap((/** * @return {?} */ function () { return _this.modelLoader.loadForFeature(task.tokens); })), switchMap((/** * @return {?} */ function () { return interval(300); })), switchMap((/** * @return {?} */ function () { return task.detect(_this.option); })), shareReplay(1)); } return of(task).pipe(switchMap((/** * @param {?} t * @return {?} */ function (t) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, t.target]; case 1: return [2 /*return*/, _a.sent()]; } }); }); })), switchMap((/** * @param {?} image * @return {?} */ function (image) { return fromEvent(image, 'load'); })), switchMap((/** * @return {?} */ function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.modelLoader.loadForFeature(task.tokens)]; case 1: return [2 /*return*/, _a.sent()]; } }); }); })), switchMap((/** * @return {?} */ function () { return task.detect(_this.option); })), shareReplay(1)); }; FaceDetectorService.decorators = [ { type: Injectable } ]; /** @nocollapse */ FaceDetectorService.ctorParameters = function () { return [ { type: ModelLoaderService }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [FaceDetectionOptions,] }] } ]; }; return FaceDetectorService; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var DetectionResultComponent = /** @class */ (function () { function DetectionResultComponent(task, el, renderer, faceDetector) { this.task = task; this.el = el; this.renderer = renderer; this.faceDetector = faceDetector; this.subscription = new Subscription(); this.resize$ = new Subject(); } Object.defineProperty(DetectionResultComponent.prototype, "canvas", { get: /** * @private * @return {?} */ function () { return this.canvasEl.nativeElement; }, enumerable: true, configurable: true }); /** * @return {?} */ DetectionResultComponent.prototype.onResize = /** * @return {?} */ function () { this.resize$.next('onResize'); }; /** * @private * @param {?} result * @return {?} */ DetectionResultComponent.prototype.convertResultToArray = /** * @private * @param {?} result * @return {?} */ function (result) { if (Array.isArray(result)) { return result; } return [result]; }; /** * @return {?} */ DetectionResultComponent.prototype.ngOnInit = /** * @return {?} */ function () { var _this = this; this.subscription.add(combineLatest(this.faceDetector.detect(this.task), this.resize$.pipe(startWith('init'))) .pipe(map((/** * @param {?} __0 * @return {?} */ function (_a) { var _b = __read(_a, 1), result = _b[0]; return _this.convertResultToArray(result); }))) .subscribe((/** * @param {?} result * @return {?} */ function (result) { return _this.draw(result); }))); }; /** * @return {?} */ DetectionResultComponent.prototype.ngOnDestroy = /** * @return {?} */ function () { this.subscription.unsubscribe(); }; /** * @private * @param {?} results * @return {?} */ DetectionResultComponent.prototype.draw = /** * @private * @param {?} results * @return {?} */ function (results) { return __awaiter(this, void 0, void 0, function () { var target, width, height, detectionsForSize, resizeResults$$1; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.task.target]; case 1: target = _a.sent(); width = target.width, height = target.height; if (target instanceof HTMLVideoElement) { height = target.videoHeight; width = target.videoWidth; } detectionsForSize = resizeResults(results.map((/** * @param {?} result * @return {?} */ function (result) { return result instanceof FaceDetection ? result : result.detection; })), { width: width, height: height }); this.canvas.width = width; this.canvas.height = height; this.renderer.setStyle(this.canvas, 'width', width + "px"); this.renderer.setStyle(this.canvas, 'height', height + "px"); if (this.task.tokens.length >= 1) { draw.drawDetections(this.canvas, detectionsForSize); resizeResults$$1 = resizeResults(results, { width: width, height: height }); if (this.task.tokens.includes('expressions')) { draw.drawFaceExpressions(this.canvas, resizeResults$$1.map((/** * @param {?} __0 * @return {?} */ function (_a) { var detection = _a.detection, expressions = _a.expressions; return ({ position: detection.box, expressions: expressions, }); }))); } if (this.task.tokens.includes('landmarks')) { draw.drawFaceLandmarks(this.canvas, resizeResults$$1.map((/** * @param {?} __0 * @return {?} */ function (_a) { var landmarks = _a.landmarks; return landmarks; }))); } if (this.task.tokens.includes('ageAndGender')) { resizeResults$$1.forEach((/** * @param {?} result * @return {?} */ function (result) { var age = result.age, gender = result.gender, genderProbability = result.genderProbability; /** @type {?} */ var text = new draw.DrawTextField([ round(age, 0) + " years", gender + " (" + round(genderProbability) + ")", ], result.detection.box.bottomLeft); text.draw(_this.canvas); })); } } else { draw.drawDetections(this.canvas, detectionsForSize); } return [2 /*return*/]; } }); }); }; DetectionResultComponent.decorators = [ { type: Component, args: [{ template: "<canvas #canvas></canvas>\n", styles: ["canvas{width:100%;height:100%}"] }] } ]; /** @nocollapse */ DetectionResultComponent.ctorParameters = function () { return [ { type: DetectTask }, { type: ElementRef }, { type: Renderer2 }, { type: FaceDetectorService } ]; }; DetectionResultComponent.propDecorators = { canvasEl: [{ type: ViewChild, args: ['canvas',] }], onResize: [{ type: HostListener, args: ['window:resize',] }] }; return DetectionResultComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @abstract */ var /** * @abstract */ AbstractDetectDirective = /** @class */ (function () { function AbstractDetectDirective(el, overlay, injector) { this.el = el; this.overlay = overlay; this.injector = injector; this.with = []; } /** * @return {?} */ AbstractDetectDirective.prototype.ngOnInit = /** * @return {?} */ function () { this.task = new DetectTask({ type: this.type, tokens: this.with, realtime: this.stream, }); }; Object.defineProperty(AbstractDetectDirective.prototype, "orverlayPositionStrategy", { get: /** * @private * @return {?} */ function () { return this.overlay .position() .flexibleConnectedTo(this.el) .withPositions([ { overlayX: 'start', overlayY: 'top', originX: 'start', originY: 'top', }, ]) .withFlexibleDimensions(false) .withLockedPosition(true); }, enumerable: true, configurable: true }); /** * @private * @return {?} */ AbstractDetectDirective.prototype.createOverlay = /** * @private * @return {?} */ function () { /** @type {?} */ var scrollStrategy = this.overlay.scrollStrategies.reposition(); /** @type {?} */ var config = new OverlayConfig({ positionStrategy: this.orverlayPositionStrategy, scrollStrategy: scrollStrategy, hasBackdrop: false, }); return this.overlay.create(config); }; /** * @private * @return {?} */ AbstractDetectDirective.prototype.createInjector = /** * @private * @return {?} */ function () { return Injector.create({ parent: this.injector, providers: [ { provide: DetectTask, useValue: this.task, }, ], }); }; /** * @return {?} */ AbstractDetectDirective.prototype.ngAfterViewInit = /** * @return {?} */ function () { this.task.resolveTarget(this.el.nativeElement); /** @type {?} */ var overlayRef = this.createOverlay(); /** @type {?} */ var injector = this.createInjector(); /** @type {?} */ var portal = new ComponentPortal(DetectionResultComponent, undefined, injector); overlayRef.attach(portal); }; return AbstractDetectDirective; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var DetectAllFacesImgDirective = /** @class */ (function (_super) { __extends(DetectAllFacesImgDirective, _super); function DetectAllFacesImgDirective(el, overlay, injector) { var _this = _super.call(this, el, overlay, injector) || this; _this.with = []; _this.type = 'all'; _this.stream = false; return _this; } DetectAllFacesImgDirective.decorators = [ { type: Directive, args: [{ selector: 'img[allFaces]', exportAs: 'faces', },] } ]; /** @nocollapse */ DetectAllFacesImgDirective.ctorParameters = function () { return [ { type: ElementRef }, { type: Overlay }, { type: Injector } ]; }; DetectAllFacesImgDirective.propDecorators = { with: [{ type: Input }] }; return DetectAllFacesImgDirective; }(AbstractDetectDirective)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var DetectSingleFaceImgDirective = /** @class */ (function (_super) { __extends(DetectSingleFaceImgDirective, _super); function DetectSingleFaceImgDirective(el, overlay, injector) { var _this = _super.call(this, el, overlay, injector) || this; _this.with = []; _this.type = 'single'; _this.stream = false; return _this; } /** * @return {?} */ DetectSingleFaceImgDirective.prototype.ngOnInit = /** * @return {?} */ function () { this.task = new DetectTask({ type: this.type, tokens: this.with, realtime: this.stream, }); }; DetectSingleFaceImgDirective.decorators = [ { type: Directive, args: [{ selector: 'img[singleFace]', exportAs: 'face', },] } ]; /** @nocollapse */ DetectSingleFaceImgDirective.ctorParameters = function () { return [ { type: ElementRef }, { type: Overlay }, { type: Injector } ]; }; DetectSingleFaceImgDirective.propDecorators = { with: [{ type: Input }] }; return DetectSingleFaceImgDirective; }(AbstractDetectDirective)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var DetectAllFacesVideoDirective = /** @class */ (function (_super) { __extends(DetectAllFacesVideoDirective, _super); function DetectAllFacesVideoDirective(el, overlay, injector) { var _this = _super.call(this, el, overlay, injector) || this; _this.with = []; _this.type = 'all'; _this.stream = true; return _this; } DetectAllFacesVideoDirective.decorators = [ { type: Directive, args: [{ selector: 'video[allFaces]', exportAs: 'faces', },] } ]; /** @nocollapse */ DetectAllFacesVideoDirective.ctorParameters = function () { return [ { type: ElementRef }, { type: Overlay }, { type: Injector } ]; }; DetectAllFacesVideoDirective.propDecorators = { with: [{ type: Input }] }; return DetectAllFacesVideoDirective; }(AbstractDetectDirective)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var NgxFaceApiJsModule = /** @class */ (function () { function NgxFaceApiJsModule() { } /** * @param {?} options * @return {?} */ NgxFaceApiJsModule.forRoot = /** * @param {?} options * @return {?} */ function (options) { return { ngModule: NgxFaceApiJsModule, providers: __spread([ { provide: ModelsUrl, useValue: options.modelsUrl, }, ModelLoaderService, FaceDetectorService ], [ options.faceDetectionOptions ? { provide: FaceDetectionOptions, useValue: options.faceDetectionOptions, } : [], ]), }; }; NgxFaceApiJsModule.decorators = [ { type: NgModule, args: [{ declarations: [ DetectionResultComponent, DetectAllFacesImgDirective, DetectSingleFaceImgDirective, DetectAllFacesVideoDirective, ], imports: [BrowserModule, OverlayModule, PortalModule], exports: [ DetectAllFacesImgDirective, DetectSingleFaceImgDirective, DetectAllFacesVideoDirective, ], entryComponents: [DetectionResultComponent], },] } ]; return NgxFaceApiJsModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { DetectTask, FaceDetectionOptions, ExpressionsFeatureToken, LandmarksFeatureToken, DescriptorsFeatureToken, AgeAndGenderToken, SsdMobilenetv1Model, MtcnnModel, FaceExpressionModel, FaceLandmarkModel, FaceRecognitionModel, TinyFaceDetectorModel, AgeAndGenderModel, ModelsUrl, FaceDetectorService, ModelLoaderService, NgxFaceApiJsModule, DetectionResultComponent as ɵa, AbstractDetectDirective as ɵc, DetectAllFacesImgDirective as ɵb, DetectAllFacesVideoDirective as ɵe, DetectSingleFaceImgDirective as ɵd }; //# sourceMappingURL=ngx-face-api-js.js.map