Skip to content

Commit 5442a71

Browse files
rearranged tests
1 parent 7396324 commit 5442a71

23 files changed

+312
-504
lines changed

src/classes/FaceDetectionWithLandmarks.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@ import { FaceDetection } from './FaceDetection';
22
import { FaceLandmarks } from './FaceLandmarks';
33
import { FaceLandmarks68 } from './FaceLandmarks68';
44

5-
export class FaceDetectionWithLandmarks<TFaceLandmarks extends FaceLandmarks = FaceLandmarks68> {
5+
export interface IFaceDetectionWithLandmarks<TFaceLandmarks extends FaceLandmarks = FaceLandmarks68> {
6+
detection: FaceDetection,
7+
landmarks: TFaceLandmarks
8+
}
9+
10+
export class FaceDetectionWithLandmarks<TFaceLandmarks extends FaceLandmarks = FaceLandmarks68>
11+
implements IFaceDetectionWithLandmarks<TFaceLandmarks> {
12+
613
private _detection: FaceDetection
714
private _unshiftedLandmarks: TFaceLandmarks
815

src/classes/FullFaceDescription.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
import { FaceDetection } from './FaceDetection';
2-
import { FaceDetectionWithLandmarks } from './FaceDetectionWithLandmarks';
2+
import { FaceDetectionWithLandmarks, IFaceDetectionWithLandmarks } from './FaceDetectionWithLandmarks';
33
import { FaceLandmarks } from './FaceLandmarks';
44
import { FaceLandmarks68 } from './FaceLandmarks68';
55

6-
export class FullFaceDescription<TFaceLandmarks extends FaceLandmarks = FaceLandmarks68> extends FaceDetectionWithLandmarks<TFaceLandmarks> {
6+
export interface IFullFaceDescription<TFaceLandmarks extends FaceLandmarks = FaceLandmarks68>
7+
extends IFaceDetectionWithLandmarks<TFaceLandmarks>{
8+
9+
detection: FaceDetection,
10+
landmarks: TFaceLandmarks,
11+
descriptor: Float32Array
12+
}
13+
14+
export class FullFaceDescription<TFaceLandmarks extends FaceLandmarks = FaceLandmarks68>
15+
extends FaceDetectionWithLandmarks<TFaceLandmarks>
16+
implements IFullFaceDescription<TFaceLandmarks> {
17+
718
private _descriptor: Float32Array
819

920
constructor(

src/globalApi/nets.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ITinyYolov2Options } from 'tfjs-tiny-yolov2';
33

44
import { FaceDetection } from '../classes/FaceDetection';
55
import { FaceDetectionWithLandmarks } from '../classes/FaceDetectionWithLandmarks';
6+
import { FaceLandmarks5 } from '../classes/FaceLandmarks5';
67
import { FaceLandmarks68 } from '../classes/FaceLandmarks68';
78
import { FaceLandmark68Net } from '../faceLandmarkNet/FaceLandmark68Net';
89
import { FaceLandmark68TinyNet } from '../faceLandmarkNet/FaceLandmark68TinyNet';
@@ -63,7 +64,7 @@ export const tinyYolov2 = (input: TNetInput, options: ITinyYolov2Options): Promi
6364
* @param options (optional, default: see MtcnnOptions constructor for default parameters).
6465
* @returns Bounding box of each face with score and 5 point face landmarks.
6566
*/
66-
export const mtcnn = (input: TNetInput, options: MtcnnOptions): Promise<FaceDetectionWithLandmarks[]> =>
67+
export const mtcnn = (input: TNetInput, options: MtcnnOptions): Promise<FaceDetectionWithLandmarks<FaceLandmarks5>[]> =>
6768
nets.mtcnn.forward(input, options)
6869

6970
/**

src/mtcnn/Mtcnn.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as tf from '@tensorflow/tfjs-core';
22
import { NetInput, NeuralNetwork, Point, Rect, TNetInput, toNetInput } from 'tfjs-image-recognition-base';
33

44
import { FaceDetection } from '../classes/FaceDetection';
5+
import { FaceDetectionWithLandmarks } from '../classes/FaceDetectionWithLandmarks';
56
import { FaceLandmarks5 } from '../classes/FaceLandmarks5';
67
import { bgrToRgbTensor } from './bgrToRgbTensor';
78
import { CELL_SIZE } from './config';
@@ -14,7 +15,6 @@ import { stage1 } from './stage1';
1415
import { stage2 } from './stage2';
1516
import { stage3 } from './stage3';
1617
import { NetParams } from './types';
17-
import { FaceDetectionWithLandmarks } from '../classes/FaceDetectionWithLandmarks';
1818

1919
export class Mtcnn extends NeuralNetwork<NetParams> {
2020

@@ -25,7 +25,7 @@ export class Mtcnn extends NeuralNetwork<NetParams> {
2525
public async forwardInput(
2626
input: NetInput,
2727
forwardParams: IMtcnnOptions = {}
28-
): Promise<{ results: FaceDetectionWithLandmarks[], stats: any }> {
28+
): Promise<{ results: FaceDetectionWithLandmarks<FaceLandmarks5>[], stats: any }> {
2929

3030
const { params } = this
3131

@@ -101,7 +101,7 @@ export class Mtcnn extends NeuralNetwork<NetParams> {
101101
const out3 = await stage3(inputCanvas, out2.boxes, scoreThresholds[2], params.onet, stats)
102102
stats.total_stage3 = Date.now() - ts
103103

104-
const results = out3.boxes.map((box, idx) => new FaceDetectionWithLandmarks(
104+
const results = out3.boxes.map((box, idx) => new FaceDetectionWithLandmarks<FaceLandmarks5>(
105105
new FaceDetection(
106106
out3.scores[idx],
107107
new Rect(
@@ -127,7 +127,7 @@ export class Mtcnn extends NeuralNetwork<NetParams> {
127127
public async forward(
128128
input: TNetInput,
129129
forwardParams: IMtcnnOptions = {}
130-
): Promise<FaceDetectionWithLandmarks[]> {
130+
): Promise<FaceDetectionWithLandmarks<FaceLandmarks5>[]> {
131131
return (
132132
await this.forwardInput(
133133
await toNetInput(input),
@@ -139,7 +139,7 @@ export class Mtcnn extends NeuralNetwork<NetParams> {
139139
public async forwardWithStats(
140140
input: TNetInput,
141141
forwardParams: IMtcnnOptions = {}
142-
): Promise<{ results: FaceDetectionWithLandmarks[], stats: any }> {
142+
): Promise<{ results: FaceDetectionWithLandmarks<FaceLandmarks5>[], stats: any }> {
143143
return this.forwardInput(
144144
await toNetInput(input),
145145
forwardParams
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
[[{"x":117.85171800851822,"y":58.91067498922348},{"x":157.70139408111572,"y":64.48519098758698},{"x":142.3133249282837,"y":88.54253697395325},{"x":110.16610914468765,"y":99.86233913898468},{"x":149.25052666664124,"y":106.37608766555786}], [{"x":260.46802616119385,"y":82.86598587036133},{"x":305.55760955810547,"y":83.54110813140869},{"x":281.4357223510742,"y":113.98349380493164},{"x":257.06039476394653,"y":125.50608730316164},{"x":306.0191822052002,"y":127.20984458923341}], [{"x":82.91613873839378,"y":292.6100924015045},{"x":133.91112035512924,"y":304.814593821764},{"x":104.43486452102661,"y":330.3951778411865},{"x":72.6984107196331,"y":342.633121073246},{"x":120.51901644468307,"y":354.2677878141403}], [{"x":278.20400857925415,"y":273.83238887786865},{"x":318.7582621574402,"y":273.39686036109924},{"x":295.54277753829956,"y":300.43398427963257},{"x":279.5109224319458,"y":311.497838973999},{"x":317.0187101364136,"y":313.05305886268616}], [{"x":489.58824399113655,"y":224.56882098317146},{"x":534.514480471611,"y":223.28146517276764},{"x":507.2082565128803,"y":250.17186474800113},{"x":493.0139665305615,"y":271.0716395378113},{"x":530.7517347931862,"y":270.4143014550209}], [{"x":606.397784024477,"y":105.43332603573799},{"x":645.2468676567078,"y":111.50095802545547},{"x":625.1735819578171,"y":133.40740483999252},{"x":598.8033188581467,"y":141.26283955574036},{"x":637.2144679427147,"y":147.32198816537857}]]
1+
[[{"x":117.85171800851822,"y":58.91067159175873},{"x":157.70139408111572,"y":64.48519098758698},{"x":142.3133249282837,"y":88.54254376888275},{"x":110.1661057472229,"y":99.86233913898468},{"x":149.25052666664124,"y":106.37608766555786}],[{"x":82.91613873839378,"y":292.6100924015045},{"x":133.91112035512924,"y":304.814593821764},{"x":104.43486452102661,"y":330.3951778411865},{"x":72.6984107196331,"y":342.63312900066376},{"x":120.51901644468307,"y":354.2677878141403}],[{"x":278.20400857925415,"y":273.8323953151703},{"x":318.7582621574402,"y":273.39686357975006},{"x":295.5427807569504,"y":300.43398427963257},{"x":279.5109224319458,"y":311.497838973999},{"x":317.0187101364136,"y":313.05305886268616}],[{"x":260.46802616119385,"y":82.86598253250122},{"x":305.55760955810547,"y":83.54110813140869},{"x":281.43571567535395,"y":113.98349380493164},{"x":257.0603914260864,"y":125.50608730316162},{"x":306.01917552948,"y":127.2098445892334}],[{"x":489.5882513225079,"y":224.56882098317146},{"x":534.514480471611,"y":223.28146517276764},{"x":507.20826017856604,"y":250.1718647480011},{"x":493.0139665305615,"y":271.0716395378113},{"x":530.7517347931862,"y":270.4143014550209}],[{"x":606.397784024477,"y":105.43332290649414},{"x":645.2468676567078,"y":111.50095802545547},{"x":625.1735819578171,"y":133.40740483999252},{"x":598.8033188581467,"y":141.26284581422806},{"x":637.2144679427147,"y":147.32198816537857}]]

test/expectDetectionResults.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { IRect } from '../src';
2+
import { FaceDetection } from '../src/classes/FaceDetection';
3+
import { expectRectClose, sortBoxes, sortFaceDetections } from './utils';
4+
5+
export function expectDetectionResults(
6+
results: FaceDetection[],
7+
allExpectedFaceDetections: IRect[],
8+
expectedScores: number[],
9+
maxBoxDelta: number
10+
) {
11+
12+
const expectedDetections = expectedScores
13+
.map((score, i) => ({
14+
score,
15+
...allExpectedFaceDetections[i]
16+
}))
17+
.filter(expected => expected.score !== -1)
18+
19+
const sortedResults = sortFaceDetections(results)
20+
21+
expectedDetections.forEach((expectedDetection, i) => {
22+
const det = sortedResults[i]
23+
expect(det.score).toBeCloseTo(expectedDetection.score, 2)
24+
expectRectClose(det.box, expectedDetection, maxBoxDelta)
25+
})
26+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { FaceDetectionWithLandmarks } from '../src/classes/FaceDetectionWithLandmarks';
2+
import { FaceLandmarks } from '../src/classes/FaceLandmarks';
3+
import { FaceLandmarks68 } from '../src/classes/FaceLandmarks68';
4+
import { ExpectedFaceDetectionWithLandmarks, expectPointClose, expectRectClose, sortByFaceDetection } from './utils';
5+
6+
export type BoxAndLandmarksDeltas = {
7+
maxBoxDelta: number
8+
maxLandmarksDelta: number
9+
}
10+
11+
export function expectFaceDetectionsWithLandmarks<TFaceLandmarks extends FaceLandmarks = FaceLandmarks68>(
12+
results: FaceDetectionWithLandmarks<TFaceLandmarks>[],
13+
allExpectedFullFaceDescriptions: ExpectedFaceDetectionWithLandmarks[],
14+
expectedScores: number[],
15+
deltas: BoxAndLandmarksDeltas
16+
) {
17+
18+
const expectedFullFaceDescriptions = expectedScores
19+
.map((score, i) => ({
20+
score,
21+
...allExpectedFullFaceDescriptions[i]
22+
}))
23+
.filter(expected => expected.score !== -1)
24+
25+
const sortedResults = sortByFaceDetection(results)
26+
27+
expectedFullFaceDescriptions.forEach((expected, i) => {
28+
const { detection, landmarks } = sortedResults[i]
29+
expect(detection.score).toBeCloseTo(expected.score, 2)
30+
expectRectClose(detection.box, expected.detection, deltas.maxBoxDelta)
31+
landmarks.positions.forEach((pt, j) => expectPointClose(pt, expected.landmarks[j], deltas.maxLandmarksDelta))
32+
})
33+
}

test/expectFullFaceDescriptions.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { FullFaceDescription } from '../src/classes/FullFaceDescription';
2+
import { euclideanDistance } from '../src/euclideanDistance';
3+
import { BoxAndLandmarksDeltas } from './expectFaceDetectionsWithLandmarks';
4+
import { ExpectedFullFaceDescription, expectPointClose, expectRectClose, sortByFaceDetection } from './utils';
5+
6+
export type FullFaceDescriptionDeltas = BoxAndLandmarksDeltas & {
7+
maxDescriptorDelta: number
8+
}
9+
10+
export function expectFullFaceDescriptions(
11+
results: FullFaceDescription[],
12+
allExpectedFullFaceDescriptions: ExpectedFullFaceDescription[],
13+
expectedScores: number[],
14+
deltas: FullFaceDescriptionDeltas
15+
) {
16+
17+
const expectedFullFaceDescriptions = expectedScores
18+
.map((score, i) => ({
19+
score,
20+
...allExpectedFullFaceDescriptions[i]
21+
}))
22+
.filter(expected => expected.score !== -1)
23+
24+
const sortedResults = sortByFaceDetection(results)
25+
26+
expectedFullFaceDescriptions.forEach((expected, i) => {
27+
const { detection, landmarks, descriptor } = sortedResults[i]
28+
expect(detection.score).toBeCloseTo(expected.score, 2)
29+
expectRectClose(detection.box, expected.detection, deltas.maxBoxDelta)
30+
landmarks.positions.forEach((pt, j) => expectPointClose(pt, expected.landmarks[j], deltas.maxLandmarksDelta))
31+
expect(euclideanDistance(descriptor, expected.descriptor)).toBeLessThan(deltas.maxDescriptorDelta)
32+
})
33+
}

test/tests/e2e/allFacesMtcnn.test.ts

Lines changed: 0 additions & 54 deletions
This file was deleted.

test/tests/e2e/allFacesSsdMobilenetv1.test.ts

Lines changed: 0 additions & 87 deletions
This file was deleted.

0 commit comments

Comments
 (0)