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.

228 lines 18.4 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import * as tslib_1 from "tslib"; import { Component, ViewChild, ElementRef, Renderer2, HostListener, } from '@angular/core'; import { Subscription, Subject, combineLatest } from 'rxjs'; import * as faceapi from 'face-api.js'; import { map, startWith } from 'rxjs/operators'; import { DetectTask } from '../../classes/DetectTask'; import { FaceDetectorService } from '../../services/face-detector.service'; 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 = tslib_1.__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 tslib_1.__awaiter(this, void 0, void 0, function () { var target, width, height, detectionsForSize, resizeResults; var _this = this; return tslib_1.__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 = faceapi.resizeResults(results.map((/** * @param {?} result * @return {?} */ function (result) { return result instanceof faceapi.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) { faceapi.draw.drawDetections(this.canvas, detectionsForSize); resizeResults = faceapi.resizeResults(results, { width: width, height: height }); if (this.task.tokens.includes('expressions')) { faceapi.draw.drawFaceExpressions(this.canvas, resizeResults.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')) { faceapi.draw.drawFaceLandmarks(this.canvas, resizeResults.map((/** * @param {?} __0 * @return {?} */ function (_a) { var landmarks = _a.landmarks; return landmarks; }))); } if (this.task.tokens.includes('ageAndGender')) { resizeResults.forEach((/** * @param {?} result * @return {?} */ function (result) { var age = result.age, gender = result.gender, genderProbability = result.genderProbability; /** @type {?} */ var text = new faceapi.draw.DrawTextField([ faceapi.round(age, 0) + " years", gender + " (" + faceapi.round(genderProbability) + ")", ], result.detection.box.bottomLeft); text.draw(_this.canvas); })); } } else { faceapi.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; }()); export { DetectionResultComponent }; if (false) { /** @type {?} */ DetectionResultComponent.prototype.subscription; /** * @type {?} * @private */ DetectionResultComponent.prototype.canvasEl; /** * @type {?} * @private */ DetectionResultComponent.prototype.resize$; /** * @type {?} * @private */ DetectionResultComponent.prototype.task; /** * @type {?} * @private */ DetectionResultComponent.prototype.el; /** * @type {?} * @private */ DetectionResultComponent.prototype.renderer; /** * @type {?} * @private */ DetectionResultComponent.prototype.faceDetector; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV0ZWN0aW9uLXJlc3VsdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtZmFjZS1hcGktanMvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9kZXRlY3Rpb24tcmVzdWx0L2RldGVjdGlvbi1yZXN1bHQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUNMLFNBQVMsRUFFVCxTQUFTLEVBQ1QsVUFBVSxFQUNWLFNBQVMsRUFFVCxZQUFZLEdBQ2IsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRTVELE9BQU8sS0FBSyxPQUFPLE1BQU0sYUFBYSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBRTNFO0lBcUJFLGtDQUNVLElBQWdCLEVBQ2hCLEVBQWMsRUFDZCxRQUFtQixFQUNuQixZQUFpQztRQUhqQyxTQUFJLEdBQUosSUFBSSxDQUFZO1FBQ2hCLE9BQUUsR0FBRixFQUFFLENBQVk7UUFDZCxhQUFRLEdBQVIsUUFBUSxDQUFXO1FBQ25CLGlCQUFZLEdBQVosWUFBWSxDQUFxQjtRQXBCM0MsaUJBQVksR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBUzFCLFlBQU8sR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO0lBWTdCLENBQUM7SUFoQkosc0JBQVksNENBQU07Ozs7O1FBQWxCO1lBQ0UsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQztRQUNyQyxDQUFDOzs7T0FBQTs7OztJQUtNLDJDQUFROzs7SUFEZjtRQUVFLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFD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QUFDLENBQUM7eUJBQzdEOzs7OztLQUNGOztnQkF6R0YsU0FBUyxTQUFDO29CQUNULHVDQUFnRDs7aUJBRWpEOzs7O2dCQU5RLFVBQVU7Z0JBVGpCLFVBQVU7Z0JBQ1YsU0FBUztnQkFTRixtQkFBbUI7OzsyQkFTekIsU0FBUyxTQUFDLFFBQVE7MkJBU2xCLFlBQVksU0FBQyxlQUFlOztJQTBGL0IsK0JBQUM7Q0FBQSxBQTFHRCxJQTBHQztTQXRHWSx3QkFBd0I7OztJQUNuQyxnREFBa0M7Ozs7O0lBRWxDLDRDQUNnRDs7Ozs7SUFNaEQsMkNBQWdDOzs7OztJQVE5Qix3Q0FBd0I7Ozs7O0lBQ3hCLHNDQUFzQjs7Ozs7SUFDdEIsNENBQTJCOzs7OztJQUMzQixnREFBeUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIE9uSW5pdCxcbiAgVmlld0NoaWxkLFxuICBFbGVtZW50UmVmLFxuICBSZW5kZXJlcjIsXG4gIE9uRGVzdHJveSxcbiAgSG9zdExpc3RlbmVyLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiwgU3ViamVjdCwgY29tYmluZUxhdGVzdCB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgKiBhcyBmYWNlYXBpIGZyb20gJ2ZhY2UtYXBpLmpzJztcbmltcG9ydCB7IG1hcCwgc3RhcnRXaXRoIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgRGV0ZWN0VGFzayB9IGZyb20gJy4uLy4uL2NsYXNzZXMvRGV0ZWN0VGFzayc7XG5pbXBvcnQgeyBGYWNlRGV0ZWN0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvZmFjZS1kZXRlY3Rvci5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gIHRlbXBsYXRlVXJsOiAnLi9kZXRlY3Rpb24tcmVzdWx0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vZGV0ZWN0aW9uLXJlc3VsdC5jb21wb25lbnQuc2NzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBEZXRlY3Rpb25SZXN1bHRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIHN1YnNjcmlwdGlvbiA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICBAVmlld0NoaWxkKCdjYW52YXMnKVxuICBwcml2YXRlIGNhbnZhc0VsOiBFbGVtZW50UmVmPEhUTUxDYW52YXNFbGVtZW50PjtcblxuICBwcml2YXRlIGdldCBjYW52YXMoKTogSFRNTENhbnZhc0VsZW1lbnQge1xuICAgIHJldHVybiB0aGlzLmNhbnZhc0VsLm5hdGl2ZUVsZW1lbnQ7XG4gIH1cblxuICBwcml2YXRlIHJlc2l6ZSQgPSBuZXcgU3ViamVjdCgpO1xuXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzpyZXNpemUnKVxuICBwdWJsaWMgb25SZXNpemUoKSB7XG4gICAgdGhpcy5yZXNpemUkLm5leHQoJ29uUmVzaXplJyk7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHRhc2s6IERldGVjdFRhc2ssXG4gICAgcHJpdmF0ZSBlbDogRWxlbWVudFJlZixcbiAgICBwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgcHJpdmF0ZSBmYWNlRGV0ZWN0b3I6IEZhY2VEZXRlY3RvclNlcnZpY2UsXG4gICkge31cblxuICBwcml2YXRlIGNvbnZlcnRSZXN1bHRUb0FycmF5KHJlc3VsdDogYW55KTogYW55W10ge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHJlc3VsdCkpIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICAgIHJldHVybiBbcmVzdWx0XTtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uLmFkZChcbiAgICAgIGNvbWJpbmVMYXRlc3QoXG4gICAgICAgIHRoaXMuZmFjZURldGVjdG9yLmRldGVjdCh0aGlzLnRhc2spLFxuICAgICAgICB0aGlzLnJlc2l6ZSQucGlwZShzdGFydFdpdGgoJ2luaXQnKSksXG4gICAgICApXG4gICAgICAgIC5waXBlKG1hcCgoW3Jlc3VsdF0pID0+IHRoaXMuY29udmVydFJlc3VsdFRvQXJyYXkocmVzdWx0KSkpXG4gICAgICAgIC5zdWJzY3JpYmUocmVzdWx0ID0+IHRoaXMuZHJhdyhyZXN1bHQpKSxcbiAgICApO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuICBwcml2YXRlIGFzeW5jIGRyYXcocmVzdWx0czogYW55W10pIHtcbiAgICBjb25zdCB0YXJnZXQgPSBhd2FpdCB0aGlzLnRhc2sudGFyZ2V0O1xuICAgIGxldCB7IHdpZHRoLCBoZWlnaHQgfSA9IHRhcmdldDtcbiAgICBpZiAodGFyZ2V0IGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCkge1xuICAgICAgaGVpZ2h0ID0gdGFyZ2V0LnZpZGVvSGVpZ2h0O1xuICAgICAgd2lkdGggPSB0YXJnZXQudmlkZW9XaWR0aDtcbiAgICB9XG5cbiAgICBjb25zdCBkZXRlY3Rpb25zRm9yU2l6ZSA9IGZhY2VhcGkucmVzaXplUmVzdWx0cyhcbiAgICAgIHJlc3VsdHMubWFwKHJlc3VsdCA9PlxuICAgICAgICByZXN1bHQgaW5zdGFuY2VvZiBmYWNlYXBpLkZhY2VEZXRlY3Rpb24gPyByZXN1bHQgOiByZXN1bHQuZGV0ZWN0aW9uLFxuICAgICAgKSxcbiAgICAgIHsgd2lkdGgsIGhlaWdodCB9LFxuICAgICk7XG5cbiAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IGhlaWdodDtcbiAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuY2FudmFzLCAnd2lkdGgnLCBgJHt3aWR0aH1weGApO1xuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5jYW52YXMsICdoZWlnaHQnLCBgJHtoZWlnaHR9cHhgKTtcbiAgICBpZiAodGhpcy50YXNrLnRva2Vucy5sZW5ndGggPj0gMSkge1xuICAgICAgZmFjZWFwaS5kcmF3LmRyYXdEZXRlY3Rpb25zKHRoaXMuY2FudmFzLCBkZXRlY3Rpb25zRm9yU2l6ZSk7XG5cbiAgICAgIGNvbnN0IHJlc2l6ZVJlc3VsdHMgPSBmYWNlYXBpLnJlc2l6ZVJlc3VsdHMocmVzdWx0cywgeyB3aWR0aCwgaGVpZ2h0IH0pO1xuICAgICAgaWYgKHRoaXMudGFzay50b2tlbnMuaW5jbHVkZXMoJ2V4cHJlc3Npb25zJykpIHtcbiAgICAgICAgZmFjZWFwaS5kcmF3LmRyYXdGYWNlRXhwcmVzc2lvbnMoXG4gICAgICAgICAgdGhpcy5jYW52YXMsXG4gICAgICAgICAgcmVzaXplUmVzdWx0cy5tYXAoKHsgZGV0ZWN0aW9uLCBleHByZXNzaW9ucyB9KSA9PiAoe1xuICAgICAgICAgICAgcG9zaXRpb246IGRldGVjdGlvbi5ib3gsXG4gICAgICAgICAgICBleHByZXNzaW9ucyxcbiAgICAgICAgICB9KSksXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnRhc2sudG9rZW5zLmluY2x1ZGVzKCdsYW5kbWFya3MnKSkge1xuICAgICAgICBmYWNlYXBpLmRyYXcuZHJhd0ZhY2VMYW5kbWFya3MoXG4gICAgICAgICAgdGhpcy5jYW52YXMsXG4gICAgICAgICAgcmVzaXplUmVzdWx0cy5tYXAoKHsgbGFuZG1hcmtzIH0pID0+IGxhbmRtYXJrcyksXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnRhc2sudG9rZW5zLmluY2x1ZGVzKCdhZ2VBbmRHZW5kZXInKSkge1xuICAgICAgICByZXNpemVSZXN1bHRzLmZvckVhY2gocmVzdWx0ID0+IHtcbiAgICAgICAgICBjb25zdCB7IGFnZSwgZ2VuZGVyLCBnZW5kZXJQcm9iYWJpbGl0eSB9ID0gcmVzdWx0O1xuICAgICAgICAgIGNvbnN0IHRleHQgPSBuZXcgZmFjZWFwaS5kcmF3LkRyYXdUZXh0RmllbGQoXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgIGAke2ZhY2VhcGkucm91bmQoYWdlLCAwKX0geWVhcnNgLFxuICAgICAgICAgICAgICBgJHtnZW5kZXJ9ICgke2ZhY2VhcGkucm91bmQoZ2VuZGVyUHJvYmFiaWxpdHkpfSlgLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIHJlc3VsdC5kZXRlY3Rpb24uYm94LmJvdHRvbUxlZnQsXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0ZXh0LmRyYXcodGhpcy5jYW52YXMpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZmFjZWFwaS5kcmF3LmRyYXdEZXRlY3Rpb25zKHRoaXMuY2FudmFzLCBkZXRlY3Rpb25zRm9yU2l6ZSk7XG4gICAgfVxuICB9XG59XG4iXX0=