Skip to content

Commit ad2ebd7

Browse files
restore drawFaceLandmarks + make FaceDetection extend ObjectDetection
1 parent adaed9e commit ad2ebd7

File tree

11 files changed

+96
-77
lines changed

11 files changed

+96
-77
lines changed

src/allFacesFactory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { TinyYolov2 } from '.';
44
import { FaceDetection } from './classes/FaceDetection';
55
import { FaceLandmarks68 } from './classes/FaceLandmarks68';
66
import { FullFaceDescription } from './classes/FullFaceDescription';
7-
import { extractFaceTensors } from './extractFaceTensors';
7+
import { extractFaceTensors } from './dom';
88
import { FaceDetectionNet } from './faceDetectionNet/FaceDetectionNet';
99
import { FaceLandmarkNet } from './faceLandmarkNet/FaceLandmarkNet';
1010
import { FaceRecognitionNet } from './faceRecognitionNet/FaceRecognitionNet';

src/classes/FaceDetection.ts

Lines changed: 3 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,11 @@
1-
import { Dimensions, Rect } from 'tfjs-image-recognition-base';
2-
3-
export class FaceDetection {
4-
private _score: number
5-
private _box: Rect
6-
private _imageWidth: number
7-
private _imageHeight: number
1+
import { Dimensions, ObjectDetection, Rect } from 'tfjs-image-recognition-base';
82

3+
export class FaceDetection extends ObjectDetection {
94
constructor(
105
score: number,
116
relativeBox: Rect,
127
imageDims: Dimensions
138
) {
14-
const { width, height } = imageDims
15-
this._imageWidth = width
16-
this._imageHeight = height
17-
this._score = score
18-
this._box = new Rect(
19-
relativeBox.x * width,
20-
relativeBox.y * height,
21-
relativeBox.width * width,
22-
relativeBox.height * height
23-
)
24-
}
25-
26-
public get score(): number {
27-
return this._score
28-
}
29-
30-
public get box(): Rect {
31-
return this._box
32-
}
33-
34-
public get imageWidth(): number {
35-
return this._imageWidth
36-
}
37-
38-
public get imageHeight(): number {
39-
return this._imageHeight
40-
}
41-
42-
public get relativeBox(): Rect {
43-
return new Rect(
44-
this._box.x / this._imageWidth,
45-
this._box.y / this._imageHeight,
46-
this._box.width / this._imageWidth,
47-
this._box.height / this._imageHeight
48-
)
49-
}
50-
51-
public getScore() {
52-
return this.score
53-
}
54-
55-
public getBox() {
56-
return this.box
57-
}
58-
59-
public getImageWidth() {
60-
return this.imageWidth
61-
}
62-
63-
public getImageHeight() {
64-
return this.imageHeight
65-
}
66-
67-
public getRelativeBox() {
68-
return this.relativeBox
69-
}
70-
71-
public forSize(width: number, height: number): FaceDetection {
72-
return new FaceDetection(
73-
this._score,
74-
this.getRelativeBox(),
75-
{ width, height}
76-
)
9+
super(score, score, '', relativeBox, imageDims)
7710
}
7811
}

src/dom/drawContour.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Point } from 'tfjs-image-recognition-base';
2+
3+
export function drawContour(
4+
ctx: CanvasRenderingContext2D,
5+
points: Point[],
6+
isClosed: boolean = false
7+
) {
8+
ctx.beginPath()
9+
10+
points.slice(1).forEach(({ x, y }, prevIdx) => {
11+
const from = points[prevIdx]
12+
ctx.moveTo(from.x, from.y)
13+
ctx.lineTo(x, y)
14+
})
15+
16+
if (isClosed) {
17+
const from = points[points.length - 1]
18+
const to = points[0]
19+
if (!from || !to) {
20+
return
21+
}
22+
23+
ctx.moveTo(from.x, from.y)
24+
ctx.lineTo(to.x, to.y)
25+
}
26+
27+
ctx.stroke()
28+
}

src/dom/drawLandmarks.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { getContext2dOrThrow, getDefaultDrawOptions, resolveInput } from 'tfjs-image-recognition-base';
2+
3+
import { FaceLandmarks } from '../classes/FaceLandmarks';
4+
import { FaceLandmarks68 } from '../classes/FaceLandmarks68';
5+
import { drawContour } from './drawContour';
6+
import { DrawLandmarksOptions } from './types';
7+
8+
export function drawLandmarks(
9+
canvasArg: string | HTMLCanvasElement,
10+
faceLandmarks: FaceLandmarks | FaceLandmarks[],
11+
options?: DrawLandmarksOptions
12+
) {
13+
const canvas = resolveInput(canvasArg)
14+
if (!(canvas instanceof HTMLCanvasElement)) {
15+
throw new Error('drawLandmarks - expected canvas to be of type: HTMLCanvasElement')
16+
}
17+
18+
const drawOptions = Object.assign(
19+
getDefaultDrawOptions(options),
20+
(options || {})
21+
)
22+
23+
const { drawLines } = Object.assign({ drawLines: false }, (options || {}))
24+
25+
const ctx = getContext2dOrThrow(canvas)
26+
const { lineWidth, color = 'blue' } = drawOptions
27+
28+
const faceLandmarksArray = Array.isArray(faceLandmarks) ? faceLandmarks : [faceLandmarks]
29+
30+
faceLandmarksArray.forEach(landmarks => {
31+
if (drawLines && landmarks instanceof FaceLandmarks68) {
32+
ctx.strokeStyle = color
33+
ctx.lineWidth = lineWidth
34+
drawContour(ctx, landmarks.getJawOutline())
35+
drawContour(ctx, landmarks.getLeftEyeBrow())
36+
drawContour(ctx, landmarks.getRightEyeBrow())
37+
drawContour(ctx, landmarks.getNose())
38+
drawContour(ctx, landmarks.getLeftEye(), true)
39+
drawContour(ctx, landmarks.getRightEye(), true)
40+
drawContour(ctx, landmarks.getMouth(), true)
41+
return
42+
}
43+
44+
// else draw points
45+
const ptOffset = lineWidth / 2
46+
ctx.fillStyle = color
47+
landmarks.getPositions().forEach(pt => ctx.fillRect(pt.x - ptOffset, pt.y - ptOffset, lineWidth, lineWidth))
48+
})
49+
}

src/extractFaceTensors.ts renamed to src/dom/extractFaceTensors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as tf from '@tensorflow/tfjs-core';
22
import { Rect, TNetInput, toNetInput } from 'tfjs-image-recognition-base';
33

4-
import { FaceDetection } from './classes/FaceDetection';
4+
import { FaceDetection } from '../classes/FaceDetection';
55

66
/**
77
* Extracts the tensors of the image regions containing the detected faces.

src/extractFaces.ts renamed to src/dom/extractFaces.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
toNetInput,
88
} from 'tfjs-image-recognition-base';
99

10-
import { FaceDetection } from './classes/FaceDetection';
10+
import { FaceDetection } from '../classes/FaceDetection';
1111

1212
/**
1313
* Extracts the image regions containing the detected faces.

src/dom/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export * from './drawContour'
2+
export * from './drawLandmarks'
3+
export * from './extractFaces'
4+
export * from './extractFaceTensors'
5+
export * from './types'

src/dom/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export type DrawLandmarksOptions = {
2+
lineWidth?: number
3+
color?: string,
4+
drawLines?: boolean
5+
}

src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ export * from 'tfjs-image-recognition-base';
88

99
export * from './classes';
1010

11+
export * from './dom'
1112
export * from './euclideanDistance';
12-
export * from './extractFaces'
13-
export * from './extractFaceTensors'
1413
export * from './faceDetectionNet';
1514
export * from './faceLandmarkNet';
1615
export * from './faceRecognitionNet';

test/tests/extractFaceTensors.test.ts renamed to test/tests/dom/extractFaceTensors.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { bufferToImage, extractFaceTensors, Rect } from '../../src';
1+
import { bufferToImage, extractFaceTensors, Rect } from '../../../src';
22

33
describe('extractFaceTensors', () => {
44

test/tests/extractFaces.test.ts renamed to test/tests/dom/extractFaces.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { bufferToImage, createCanvasFromMedia, extractFaces, Rect } from '../../src';
1+
import { bufferToImage, createCanvasFromMedia, extractFaces, Rect } from '../../../src';
22

33
describe('extractFaces', () => {
44

0 commit comments

Comments
 (0)