Skip to content

Instantly share code, notes, and snippets.

@kamiazya
Created May 24, 2019 01:09
Show Gist options
  • Select an option

  • Save kamiazya/5f2d94b4c1e05272c5f01b149cc27219 to your computer and use it in GitHub Desktop.

Select an option

Save kamiazya/5f2d94b4c1e05272c5f01b149cc27219 to your computer and use it in GitHub Desktop.
import * as faceapi from 'face-api.js';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
interface DetectionRequest {
faceDetectionOptions: faceapi.FaceDetectionOptions;
useTinyLandmarkNet?: boolean;
}
interface DetectionResult {
detection: faceapi.FaceDetection;
face?: HTMLCanvasElement;
landmarks?: faceapi.FaceLandmarks;
unshiftedLandmarks?: faceapi.FaceLandmarks;
alignedRect?: faceapi.FaceDetection;
expressions?: faceapi.FaceExpressions;
ageAndGender?: faceapi.AgeAndGenderPrediction;
descriptor?: Float32Array;
}
export class Detector {
public get resolveTarget(): (el: HTMLImageElement | HTMLVideoElement) => void {
return this.targetResolver;
}
// tslint:disable-next-line:max-line-length
public target: Promise<HTMLImageElement | HTMLVideoElement> = new Promise<HTMLImageElement | HTMLVideoElement>(resolver => this.targetResolver = resolver);
private targetResolver: (el: HTMLImageElement | HTMLVideoElement) => void;
public detect(
scheduler: Observable<DetectionRequest>,
): Observable<DetectionResult[]> {
return scheduler
.pipe(
switchMap(async (request) => {
const input = await this.target;
let detections: faceapi.FaceDetection[];
let landmarks: faceapi.FaceLandmarks[];
if (request.faceDetectionOptions instanceof faceapi.MtcnnOptions) {
const rs = await faceapi.nets.mtcnn.forward(input, request.faceDetectionOptions);
detections = rs.map(r => r.detection);
landmarks = rs.map(r => r.landmarks);
// results.push(...await faceapi.nets.mtcnn.forward(input, request.faceDetectionOptions));
} else {
if (request.faceDetectionOptions instanceof faceapi.TinyFaceDetectorOptions) {
detections = await faceapi.nets.tinyFaceDetector.locateFaces(input, request.faceDetectionOptions);
// results.push(...await faceapi.nets.tinyFaceDetector.locateFaces(input, request.faceDetectionOptions)
// .then(ds => ds.map(detection => ({ detection }))));
} else if (request.faceDetectionOptions instanceof faceapi.SsdMobilenetv1Options) {
detections = await await faceapi.nets.ssdMobilenetv1.locateFaces(input, request.faceDetectionOptions);
// results.push(...await faceapi.nets.ssdMobilenetv1.locateFaces(input, request.faceDetectionOptions)
// .then(ds => ds.map(detection => ({ detection }))));
} else if (request.faceDetectionOptions instanceof faceapi.TfjsImageRecognitionBase.TinyYolov2Options) {
detections = await faceapi.nets.tinyYolov2.locateFaces(input, request.faceDetectionOptions);
// results.push(...await faceapi.nets.tinyYolov2.locateFaces(input, request.faceDetectionOptions)
// .then(ds => ds.map(detection => ({ detection }))));
}
}
const results: DetectionResult[] = detections.map(detection => ({ detection }));
const faces = await faceapi.extractFaces(input, detections);
results.forEach((r, i) => r.face = faces[i]);
if (!landmarks || request.useTinyLandmarkNet === false) {
const landmarkNet = request.useTinyLandmarkNet
? faceapi.nets.faceLandmark68TinyNet
: faceapi.nets.faceLandmark68Net;
const faceLandmarksByFace = await Promise.all(
faces.map(face => landmarkNet.detectLandmarks(face))) as faceapi.FaceLandmarks68[];
results.forEach((r, i) => r.landmarks = faceLandmarksByFace[i]);
}
const faceExpressionsByFace = await Promise.all(
faces.map(face => faceapi.nets.faceExpressionNet.predictExpressions(face) as Promise<faceapi.FaceExpressions>));
results.forEach((r, i) => r.expressions = faceExpressionsByFace[i]);
const ageAndGenderByFace = await Promise.all(faces.map(
face => faceapi.nets.ageGenderNet.predictAgeAndGender(face) as Promise<faceapi.AgeAndGenderPrediction>
));
results.forEach((r, i) => r.ageAndGender = ageAndGenderByFace[i]);
const descriptors = await Promise.all(faces.map(
face => faceapi.nets.faceRecognitionNet.computeFaceDescriptor(face) as Promise<Float32Array>
));
results.forEach((r, i) => r.descriptor = descriptors[i]);
return results;
}),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment