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
JavaScript
/**
* @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