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.

191 lines 15.8 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'; export class DetectionResultComponent { /** * @param {?} task * @param {?} el * @param {?} renderer * @param {?} faceDetector */ constructor(task, el, renderer, faceDetector) { this.task = task; this.el = el; this.renderer = renderer; this.faceDetector = faceDetector; this.subscription = new Subscription(); this.resize$ = new Subject(); } /** * @private * @return {?} */ get canvas() { return this.canvasEl.nativeElement; } /** * @return {?} */ onResize() { this.resize$.next('onResize'); } /** * @private * @param {?} result * @return {?} */ convertResultToArray(result) { if (Array.isArray(result)) { return result; } return [result]; } /** * @return {?} */ ngOnInit() { this.subscription.add(combineLatest(this.faceDetector.detect(this.task), this.resize$.pipe(startWith('init'))) .pipe(map((/** * @param {?} __0 * @return {?} */ ([result]) => this.convertResultToArray(result)))) .subscribe((/** * @param {?} result * @return {?} */ result => this.draw(result)))); } /** * @return {?} */ ngOnDestroy() { this.subscription.unsubscribe(); } /** * @private * @param {?} results * @return {?} */ draw(results) { return tslib_1.__awaiter(this, void 0, void 0, function* () { /** @type {?} */ const target = yield this.task.target; let { width, height } = target; if (target instanceof HTMLVideoElement) { height = target.videoHeight; width = target.videoWidth; } /** @type {?} */ const detectionsForSize = faceapi.resizeResults(results.map((/** * @param {?} result * @return {?} */ result => result instanceof faceapi.FaceDetection ? result : result.detection)), { width, 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); /** @type {?} */ const resizeResults = faceapi.resizeResults(results, { width, height }); if (this.task.tokens.includes('expressions')) { faceapi.draw.drawFaceExpressions(this.canvas, resizeResults.map((/** * @param {?} __0 * @return {?} */ ({ detection, expressions }) => ({ position: detection.box, expressions, })))); } if (this.task.tokens.includes('landmarks')) { faceapi.draw.drawFaceLandmarks(this.canvas, resizeResults.map((/** * @param {?} __0 * @return {?} */ ({ landmarks }) => landmarks))); } if (this.task.tokens.includes('ageAndGender')) { resizeResults.forEach((/** * @param {?} result * @return {?} */ result => { const { age, gender, genderProbability } = result; /** @type {?} */ const 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); } }); } } DetectionResultComponent.decorators = [ { type: Component, args: [{ template: "<canvas #canvas></canvas>\n", styles: ["canvas{width:100%;height:100%}"] }] } ]; /** @nocollapse */ DetectionResultComponent.ctorParameters = () => [ { type: DetectTask }, { type: ElementRef }, { type: Renderer2 }, { type: FaceDetectorService } ]; DetectionResultComponent.propDecorators = { canvasEl: [{ type: ViewChild, args: ['canvas',] }], onResize: [{ type: HostListener, args: ['window:resize',] }] }; 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV0ZWN0aW9uLXJlc3VsdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtZmFjZS1hcGktanMvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9kZXRlY3Rpb24tcmVzdWx0L2RldGVjdGlvbi1yZXN1bHQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUNMLFNBQVMsRUFFVCxTQUFTLEVBQ1QsVUFBVSxFQUNWLFNBQVMsRUFFVCxZQUFZLEdBQ2IsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRTVELE9BQU8sS0FBSyxPQUFPLE1BQU0sYUFBYSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBTTNFLE1BQU0sT0FBTyx3QkFBd0I7Ozs7Ozs7SUFpQm5DLFlBQ1UsSUFBZ0IsRUFDaEIsRUFBYyxFQUNkLFFBQW1CLEVBQ25CLFlBQWlDO1FBSGpDLFNBQUksR0FBSixJQUFJLENBQVk7UUFDaEIsT0FBRSxHQUFGLEVBQUUsQ0FBWTtRQUNkLGFBQVEsR0FBUixRQUFRLENBQVc7UUFDbkIsaUJBQVksR0FBWixZQUFZLENBQXFCO1FBcEIzQyxpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFTMUIsWUFBTyxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7SUFZN0IsQ0FBQzs7Ozs7SUFoQkosSUFBWSxNQUFNO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUM7SUFDckMsQ0FBQzs7OztJQUtNLFFBQVE7UUFDYixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FB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WUFBWSxTQUFDLGVBQWU7Ozs7SUFYN0IsZ0RBQWtDOzs7OztJQUVsQyw0Q0FDZ0Q7Ozs7O0lBTWhELDJDQUFnQzs7Ozs7SUFROUIsd0NBQXdCOzs7OztJQUN4QixzQ0FBc0I7Ozs7O0lBQ3RCLDRDQUEyQjs7Ozs7SUFDM0IsZ0RBQXlDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBPbkluaXQsXG4gIFZpZXdDaGlsZCxcbiAgRWxlbWVudFJlZixcbiAgUmVuZGVyZXIyLFxuICBPbkRlc3Ryb3ksXG4gIEhvc3RMaXN0ZW5lcixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24sIFN1YmplY3QsIGNvbWJpbmVMYXRlc3QgfSBmcm9tICdyeGpzJztcblxuaW1wb3J0ICogYXMgZmFjZWFwaSBmcm9tICdmYWNlLWFwaS5qcyc7XG5pbXBvcnQgeyBtYXAsIHN0YXJ0V2l0aCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IERldGVjdFRhc2sgfSBmcm9tICcuLi8uLi9jbGFzc2VzL0RldGVjdFRhc2snO1xuaW1wb3J0IHsgRmFjZURldGVjdG9yU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2ZhY2UtZGV0ZWN0b3Iuc2VydmljZSc7XG5cbkBDb21wb25lbnQoe1xuICB0ZW1wbGF0ZVVybDogJy4vZGV0ZWN0aW9uLXJlc3VsdC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2RldGVjdGlvbi1yZXN1bHQuY29tcG9uZW50LnNjc3MnXSxcbn0pXG5leHBvcnQgY2xhc3MgRGV0ZWN0aW9uUmVzdWx0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICBzdWJzY3JpcHRpb24gPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG5cbiAgQFZpZXdDaGlsZCgnY2FudmFzJylcbiAgcHJpdmF0ZSBjYW52YXNFbDogRWxlbWVudFJlZjxIVE1MQ2FudmFzRWxlbWVudD47XG5cbiAgcHJpdmF0ZSBnZXQgY2FudmFzKCk6IEhUTUxDYW52YXNFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5jYW52YXNFbC5uYXRpdmVFbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSByZXNpemUkID0gbmV3IFN1YmplY3QoKTtcblxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6cmVzaXplJylcbiAgcHVibGljIG9uUmVzaXplKCkge1xuICAgIHRoaXMucmVzaXplJC5uZXh0KCdvblJlc2l6ZScpO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSB0YXNrOiBEZXRlY3RUYXNrLFxuICAgIHByaXZhdGUgZWw6IEVsZW1lbnRSZWYsXG4gICAgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgIHByaXZhdGUgZmFjZURldGVjdG9yOiBGYWNlRGV0ZWN0b3JTZXJ2aWNlLFxuICApIHt9XG5cbiAgcHJpdmF0ZSBjb252ZXJ0UmVzdWx0VG9BcnJheShyZXN1bHQ6IGFueSk6IGFueVtdIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICByZXR1cm4gW3Jlc3VsdF07XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbi5hZGQoXG4gICAgICBjb21iaW5lTGF0ZXN0KFxuICAgICAgICB0aGlzLmZhY2VEZXRlY3Rvci5kZXRlY3QodGhpcy50YXNrKSxcbiAgICAgICAgdGhpcy5yZXNpemUkLnBpcGUoc3RhcnRXaXRoKCdpbml0JykpLFxuICAgICAgKVxuICAgICAgICAucGlwZShtYXAoKFtyZXN1bHRdKSA9PiB0aGlzLmNvbnZlcnRSZXN1bHRUb0FycmF5KHJlc3VsdCkpKVxuICAgICAgICAuc3Vic2NyaWJlKHJlc3VsdCA9PiB0aGlzLmRyYXcocmVzdWx0KSksXG4gICAgKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gIH1cbiAgcHJpdmF0ZSBhc3luYyBkcmF3KHJlc3VsdHM6IGFueVtdKSB7XG4gICAgY29uc3QgdGFyZ2V0ID0gYXdhaXQgdGhpcy50YXNrLnRhcmdldDtcbiAgICBsZXQgeyB3aWR0aCwgaGVpZ2h0IH0gPSB0YXJnZXQ7XG4gICAgaWYgKHRhcmdldCBpbnN0YW5jZW9mIEhUTUxWaWRlb0VsZW1lbnQpIHtcbiAgICAgIGhlaWdodCA9IHRhcmdldC52aWRlb0hlaWdodDtcbiAgICAgIHdpZHRoID0gdGFyZ2V0LnZpZGVvV2lkdGg7XG4gICAgfVxuXG4gICAgY29uc3QgZGV0ZWN0aW9uc0ZvclNpemUgPSBmYWNlYXBpLnJlc2l6ZVJlc3VsdHMoXG4gICAgICByZXN1bHRzLm1hcChyZXN1bHQgPT5cbiAgICAgICAgcmVzdWx0IGluc3RhbmNlb2YgZmFjZWFwaS5GYWNlRGV0ZWN0aW9uID8gcmVzdWx0IDogcmVzdWx0LmRldGVjdGlvbixcbiAgICAgICksXG4gICAgICB7IHdpZHRoLCBoZWlnaHQgfSxcbiAgICApO1xuXG4gICAgdGhpcy5jYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICB0aGlzLmNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmNhbnZhcywgJ3dpZHRoJywgYCR7d2lkdGh9cHhgKTtcbiAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuY2FudmFzLCAnaGVpZ2h0JywgYCR7aGVpZ2h0fXB4YCk7XG4gICAgaWYgKHRoaXMudGFzay50b2tlbnMubGVuZ3RoID49IDEpIHtcbiAgICAgIGZhY2VhcGkuZHJhdy5kcmF3RGV0ZWN0aW9ucyh0aGlzLmNhbnZhcywgZGV0ZWN0aW9uc0ZvclNpemUpO1xuXG4gICAgICBjb25zdCByZXNpemVSZXN1bHRzID0gZmFjZWFwaS5yZXNpemVSZXN1bHRzKHJlc3VsdHMsIHsgd2lkdGgsIGhlaWdodCB9KTtcbiAgICAgIGlmICh0aGlzLnRhc2sudG9rZW5zLmluY2x1ZGVzKCdleHByZXNzaW9ucycpKSB7XG4gICAgICAgIGZhY2VhcGkuZHJhdy5kcmF3RmFjZUV4cHJlc3Npb25zKFxuICAgICAgICAgIHRoaXMuY2FudmFzLFxuICAgICAgICAgIHJlc2l6ZVJlc3VsdHMubWFwKCh7IGRldGVjdGlvbiwgZXhwcmVzc2lvbnMgfSkgPT4gKHtcbiAgICAgICAgICAgIHBvc2l0aW9uOiBkZXRlY3Rpb24uYm94LFxuICAgICAgICAgICAgZXhwcmVzc2lvbnMsXG4gICAgICAgICAgfSkpLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy50YXNrLnRva2Vucy5pbmNsdWRlcygnbGFuZG1hcmtzJykpIHtcbiAgICAgICAgZmFjZWFwaS5kcmF3LmRyYXdGYWNlTGFuZG1hcmtzKFxuICAgICAgICAgIHRoaXMuY2FudmFzLFxuICAgICAgICAgIHJlc2l6ZVJlc3VsdHMubWFwKCh7IGxhbmRtYXJrcyB9KSA9PiBsYW5kbWFya3MpLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy50YXNrLnRva2Vucy5pbmNsdWRlcygnYWdlQW5kR2VuZGVyJykpIHtcbiAgICAgICAgcmVzaXplUmVzdWx0cy5mb3JFYWNoKHJlc3VsdCA9PiB7XG4gICAgICAgICAgY29uc3QgeyBhZ2UsIGdlbmRlciwgZ2VuZGVyUHJvYmFiaWxpdHkgfSA9IHJlc3VsdDtcbiAgICAgICAgICBjb25zdCB0ZXh0ID0gbmV3IGZhY2VhcGkuZHJhdy5EcmF3VGV4dEZpZWxkKFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICBgJHtmYWNlYXBpLnJvdW5kKGFnZSwgMCl9IHllYXJzYCxcbiAgICAgICAgICAgICAgYCR7Z2VuZGVyfSAoJHtmYWNlYXBpLnJvdW5kKGdlbmRlclByb2JhYmlsaXR5KX0pYCxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICByZXN1bHQuZGV0ZWN0aW9uLmJveC5ib3R0b21MZWZ0LFxuICAgICAgICAgICk7XG4gICAgICAgICAgdGV4dC5kcmF3KHRoaXMuY2FudmFzKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZhY2VhcGkuZHJhdy5kcmF3RGV0ZWN0aW9ucyh0aGlzLmNhbnZhcywgZGV0ZWN0aW9uc0ZvclNpemUpO1xuICAgIH1cbiAgfVxufVxuIl19