face-api/src/draw/DrawFaceLandmarks.ts

110 lines
3.4 KiB
TypeScript
Raw Normal View History

2020-12-23 17:26:55 +01:00
/* eslint-disable max-classes-per-file */
2020-12-19 17:46:41 +01:00
import { IPoint } from '../classes/index';
2020-08-18 13:54:53 +02:00
import { FaceLandmarks } from '../classes/FaceLandmarks';
import { FaceLandmarks68 } from '../classes/FaceLandmarks68';
import { getContext2dOrThrow } from '../dom/getContext2dOrThrow';
import { WithFaceDetection } from '../factories/WithFaceDetection';
import { isWithFaceLandmarks, WithFaceLandmarks } from '../factories/WithFaceLandmarks';
import { drawContour } from './drawContour';
export interface IDrawFaceLandmarksOptions {
drawLines?: boolean
drawPoints?: boolean
lineWidth?: number
pointSize?: number
lineColor?: string
pointColor?: string
}
export class DrawFaceLandmarksOptions {
public drawLines: boolean
2020-12-23 17:26:55 +01:00
2020-08-18 13:54:53 +02:00
public drawPoints: boolean
2020-12-23 17:26:55 +01:00
2020-08-18 13:54:53 +02:00
public lineWidth: number
2020-12-23 17:26:55 +01:00
2020-08-18 13:54:53 +02:00
public pointSize: number
2020-12-23 17:26:55 +01:00
2020-08-18 13:54:53 +02:00
public lineColor: string
2020-12-23 17:26:55 +01:00
2020-08-18 13:54:53 +02:00
public pointColor: string
constructor(options: IDrawFaceLandmarksOptions = {}) {
2020-12-23 17:26:55 +01:00
const {
drawLines = true, drawPoints = true, lineWidth, lineColor, pointSize, pointColor,
} = options;
this.drawLines = drawLines;
this.drawPoints = drawPoints;
this.lineWidth = lineWidth || 1;
this.pointSize = pointSize || 2;
this.lineColor = lineColor || 'rgba(0, 255, 255, 1)';
this.pointColor = pointColor || 'rgba(255, 0, 255, 1)';
2020-08-18 13:54:53 +02:00
}
}
export class DrawFaceLandmarks {
public faceLandmarks: FaceLandmarks
2020-12-23 17:26:55 +01:00
2020-08-18 13:54:53 +02:00
public options: DrawFaceLandmarksOptions
constructor(
faceLandmarks: FaceLandmarks,
2020-12-23 17:26:55 +01:00
options: IDrawFaceLandmarksOptions = {},
2020-08-18 13:54:53 +02:00
) {
2020-12-23 17:26:55 +01:00
this.faceLandmarks = faceLandmarks;
this.options = new DrawFaceLandmarksOptions(options);
2020-08-18 13:54:53 +02:00
}
draw(canvasArg: string | HTMLCanvasElement | CanvasRenderingContext2D) {
2020-12-23 17:26:55 +01:00
const ctx = getContext2dOrThrow(canvasArg);
2020-08-18 13:54:53 +02:00
2020-12-23 17:26:55 +01:00
const {
drawLines, drawPoints, lineWidth, lineColor, pointSize, pointColor,
} = this.options;
2020-08-18 13:54:53 +02:00
if (drawLines && this.faceLandmarks instanceof FaceLandmarks68) {
2020-12-23 17:26:55 +01:00
ctx.strokeStyle = lineColor;
ctx.lineWidth = lineWidth;
drawContour(ctx, this.faceLandmarks.getJawOutline());
drawContour(ctx, this.faceLandmarks.getLeftEyeBrow());
drawContour(ctx, this.faceLandmarks.getRightEyeBrow());
drawContour(ctx, this.faceLandmarks.getNose());
drawContour(ctx, this.faceLandmarks.getLeftEye(), true);
drawContour(ctx, this.faceLandmarks.getRightEye(), true);
drawContour(ctx, this.faceLandmarks.getMouth(), true);
2020-08-18 13:54:53 +02:00
}
if (drawPoints) {
2020-12-23 17:26:55 +01:00
ctx.strokeStyle = pointColor;
ctx.fillStyle = pointColor;
2020-08-18 13:54:53 +02:00
const drawPoint = (pt: IPoint) => {
2020-12-23 17:26:55 +01:00
ctx.beginPath();
ctx.arc(pt.x, pt.y, pointSize, 0, 2 * Math.PI);
ctx.fill();
};
this.faceLandmarks.positions.forEach(drawPoint);
2020-08-18 13:54:53 +02:00
}
}
}
export type DrawFaceLandmarksInput = FaceLandmarks | WithFaceLandmarks<WithFaceDetection<{}>>
export function drawFaceLandmarks(
canvasArg: string | HTMLCanvasElement,
2020-12-23 17:26:55 +01:00
faceLandmarks: DrawFaceLandmarksInput | Array<DrawFaceLandmarksInput>,
2020-08-18 13:54:53 +02:00
) {
2020-12-23 17:26:55 +01:00
const faceLandmarksArray = Array.isArray(faceLandmarks) ? faceLandmarks : [faceLandmarks];
faceLandmarksArray.forEach((f) => {
// eslint-disable-next-line no-nested-ternary
2020-08-18 13:54:53 +02:00
const landmarks = f instanceof FaceLandmarks
? f
2020-12-23 17:26:55 +01:00
: (isWithFaceLandmarks(f) ? f.landmarks : undefined);
2020-08-18 13:54:53 +02:00
if (!landmarks) {
2020-12-23 17:26:55 +01:00
throw new Error('drawFaceLandmarks - expected faceExpressions to be FaceLandmarks | WithFaceLandmarks<WithFaceDetection<{}>> or array thereof');
2020-08-18 13:54:53 +02:00
}
2020-12-23 17:26:55 +01:00
new DrawFaceLandmarks(landmarks).draw(canvasArg);
});
}