Unverified Commit 4695c1bf by justadudewhohacks Committed by GitHub

Travis ci (#114)

parent 5b8bb8c4
sudo: required
language: node_js
node_js:
- "10"
env:
- BACKEND_CPU=true EXCLUDE_UNCOMPRESSED=true
before_script:
- wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
- sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
- sudo apt-get update
- sudo apt-get install google-chrome-stable
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
script:
- npm run test-travis
- npm install
- npm run build
\ No newline at end of file
...@@ -14,7 +14,8 @@ const dataFiles = [ ...@@ -14,7 +14,8 @@ const dataFiles = [
nocache: false nocache: false
})) }))
const exclude = process.env.UUT let exclude = (
process.env.UUT
? [ ? [
'dom', 'dom',
'faceLandmarkNet', 'faceLandmarkNet',
...@@ -24,11 +25,24 @@ const exclude = process.env.UUT ...@@ -24,11 +25,24 @@ const exclude = process.env.UUT
'mtcnn', 'mtcnn',
'tinyYolov2' 'tinyYolov2'
] ]
: ['tinyYolov2']
)
.filter(ex => ex !== process.env.UUT) .filter(ex => ex !== process.env.UUT)
.map(ex => `test/tests/${ex}/*.ts`) .map(ex => `test/tests/${ex}/*.ts`)
exclude = exclude.concat(
process.env.EXCLUDE_UNCOMPRESSED
? ['**/*.uncompressed.test.ts']
: [] : []
)
module.exports = function(config) { module.exports = function(config) {
const args = []
if (process.env.BACKEND_CPU) {
args.push('backend_cpu')
}
config.set({ config.set({
frameworks: ['jasmine', 'karma-typescript'], frameworks: ['jasmine', 'karma-typescript'],
files: [ files: [
...@@ -44,10 +58,13 @@ module.exports = function(config) { ...@@ -44,10 +58,13 @@ module.exports = function(config) {
}, },
browsers: ['Chrome'], browsers: ['Chrome'],
browserNoActivityTimeout: 120000, browserNoActivityTimeout: 120000,
browserDisconnectTolerance: 3,
browserDisconnectTimeout : 120000,
captureTimeout: 60000, captureTimeout: 60000,
client: { client: {
jasmine: { jasmine: {
timeoutInterval: 60000 timeoutInterval: 60000,
args
} }
} }
}) })
......
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
"test-tinyfacedetector": "set UUT=tinyFaceDetector&& karma start", "test-tinyfacedetector": "set UUT=tinyFaceDetector&& karma start",
"test-mtcnn": "set UUT=mtcnn&& karma start", "test-mtcnn": "set UUT=mtcnn&& karma start",
"test-tinyyolov2": "set UUT=tinyYolov2&& karma start", "test-tinyyolov2": "set UUT=tinyYolov2&& karma start",
"test-cpu": "set BACKEND_CPU=true&& karma start",
"test-exclude-uncompressed": "set EXCLUDE_UNCOMPRESSED=true&& karma start",
"test-travis": "karma start --single-run",
"docs": "typedoc --options ./typedoc.config.js ./src" "docs": "typedoc --options ./typedoc.config.js ./src"
}, },
"keywords": [ "keywords": [
......
...@@ -6,6 +6,7 @@ export function expectFaceDetections( ...@@ -6,6 +6,7 @@ export function expectFaceDetections(
results: FaceDetection[], results: FaceDetection[],
allExpectedFaceDetections: IRect[], allExpectedFaceDetections: IRect[],
expectedScores: number[], expectedScores: number[],
maxScoreDelta: number,
maxBoxDelta: number maxBoxDelta: number
) { ) {
...@@ -20,7 +21,7 @@ export function expectFaceDetections( ...@@ -20,7 +21,7 @@ export function expectFaceDetections(
expectedDetections.forEach((expectedDetection, i) => { expectedDetections.forEach((expectedDetection, i) => {
const det = sortedResults[i] const det = sortedResults[i]
expect(det.score).toBeCloseTo(expectedDetection.score, 2) expect(Math.abs(det.score - expectedDetection.score)).toBeLessThan(maxScoreDelta)
expectRectClose(det.box, expectedDetection, maxBoxDelta) expectRectClose(det.box, expectedDetection, maxBoxDelta)
}) })
} }
\ No newline at end of file
...@@ -4,6 +4,7 @@ import { FaceLandmarks68 } from '../src/classes/FaceLandmarks68'; ...@@ -4,6 +4,7 @@ import { FaceLandmarks68 } from '../src/classes/FaceLandmarks68';
import { ExpectedFaceDetectionWithLandmarks, expectPointClose, expectRectClose, sortByFaceDetection } from './utils'; import { ExpectedFaceDetectionWithLandmarks, expectPointClose, expectRectClose, sortByFaceDetection } from './utils';
export type BoxAndLandmarksDeltas = { export type BoxAndLandmarksDeltas = {
maxScoreDelta: number
maxBoxDelta: number maxBoxDelta: number
maxLandmarksDelta: number maxLandmarksDelta: number
} }
...@@ -26,7 +27,7 @@ export function expectFaceDetectionsWithLandmarks<TFaceLandmarks extends FaceLan ...@@ -26,7 +27,7 @@ export function expectFaceDetectionsWithLandmarks<TFaceLandmarks extends FaceLan
expectedFullFaceDescriptions.forEach((expected, i) => { expectedFullFaceDescriptions.forEach((expected, i) => {
const { detection, landmarks } = sortedResults[i] const { detection, landmarks } = sortedResults[i]
expect(detection.score).toBeCloseTo(expected.score, 2) expect(Math.abs(detection.score - expected.score)).toBeLessThan(deltas.maxScoreDelta)
expectRectClose(detection.box, expected.detection, deltas.maxBoxDelta) expectRectClose(detection.box, expected.detection, deltas.maxBoxDelta)
landmarks.positions.forEach((pt, j) => expectPointClose(pt, expected.landmarks[j], deltas.maxLandmarksDelta)) landmarks.positions.forEach((pt, j) => expectPointClose(pt, expected.landmarks[j], deltas.maxLandmarksDelta))
}) })
......
...@@ -25,7 +25,7 @@ export function expectFullFaceDescriptions( ...@@ -25,7 +25,7 @@ export function expectFullFaceDescriptions(
expectedFullFaceDescriptions.forEach((expected, i) => { expectedFullFaceDescriptions.forEach((expected, i) => {
const { detection, landmarks, descriptor } = sortedResults[i] const { detection, landmarks, descriptor } = sortedResults[i]
expect(detection.score).toBeCloseTo(expected.score, 2) expect(detection.score - expected.score).toBeLessThan(deltas.maxScoreDelta)
expectRectClose(detection.box, expected.detection, deltas.maxBoxDelta) expectRectClose(detection.box, expected.detection, deltas.maxBoxDelta)
landmarks.positions.forEach((pt, j) => expectPointClose(pt, expected.landmarks[j], deltas.maxLandmarksDelta)) landmarks.positions.forEach((pt, j) => expectPointClose(pt, expected.landmarks[j], deltas.maxLandmarksDelta))
expect(euclideanDistance(descriptor, expected.descriptor)).toBeLessThan(deltas.maxDescriptorDelta) expect(euclideanDistance(descriptor, expected.descriptor)).toBeLessThan(deltas.maxDescriptorDelta)
......
...@@ -64,7 +64,7 @@ describe('faceLandmark68Net', () => { ...@@ -64,7 +64,7 @@ describe('faceLandmark68Net', () => {
}) })
describeWithNets('batch inputs', { withFaceLandmark68Net: { quantized: false } }, ({ faceLandmark68Net }) => { describeWithNets('batch inputs', { withFaceLandmark68Net: { quantized: true } }, ({ faceLandmark68Net }) => {
it('computes face landmarks for batch of image elements', async () => { it('computes face landmarks for batch of image elements', async () => {
const inputs = [imgEl1, imgEl2, imgElRect] const inputs = [imgEl1, imgEl2, imgElRect]
...@@ -145,19 +145,6 @@ describe('faceLandmark68Net', () => { ...@@ -145,19 +145,6 @@ describe('faceLandmark68Net', () => {
describeWithNets('no memory leaks', { withFaceLandmark68Net: { quantized: true } }, ({ faceLandmark68Net }) => { describeWithNets('no memory leaks', { withFaceLandmark68Net: { quantized: true } }, ({ faceLandmark68Net }) => {
describe('NeuralNetwork, uncompressed model', () => {
it('disposes all param tensors', async () => {
await expectAllTensorsReleased(async () => {
const res = await fetch('base/weights_uncompressed/face_landmark_68_model.weights')
const weights = new Float32Array(await res.arrayBuffer())
const net = createFaceLandmarkNet(weights)
net.dispose()
})
})
})
describe('NeuralNetwork, quantized model', () => { describe('NeuralNetwork, quantized model', () => {
it('disposes all param tensors', async () => { it('disposes all param tensors', async () => {
......
import { fetchImage, fetchJson, Point } from '../../../src'; import { fetchImage, fetchJson, Point } from '../../../src';
import { FaceLandmarks68 } from '../../../src/classes/FaceLandmarks68'; import { FaceLandmarks68 } from '../../../src/classes/FaceLandmarks68';
import { describeWithNets, expectPointClose } from '../../utils'; import { createFaceLandmarkNet } from '../../../src/faceLandmarkNet';
import { describeWithNets, expectAllTensorsReleased, expectPointClose } from '../../utils';
describe('faceLandmark68Net, uncompressed', () => { describe('faceLandmark68Net, uncompressed', () => {
...@@ -46,6 +47,15 @@ describe('faceLandmark68Net, uncompressed', () => { ...@@ -46,6 +47,15 @@ describe('faceLandmark68Net, uncompressed', () => {
}) })
}) })
it('no memory leaks', async () => {
await expectAllTensorsReleased(async () => {
const res = await fetch('base/weights_uncompressed/face_landmark_68_model.weights')
const weights = new Float32Array(await res.arrayBuffer())
const net = createFaceLandmarkNet(weights)
net.dispose()
})
})
}) })
}) })
......
...@@ -145,19 +145,6 @@ describe('faceLandmark68TinyNet', () => { ...@@ -145,19 +145,6 @@ describe('faceLandmark68TinyNet', () => {
describeWithNets('no memory leaks', { withFaceLandmark68TinyNet: { quantized: true } }, ({ faceLandmark68TinyNet }) => { describeWithNets('no memory leaks', { withFaceLandmark68TinyNet: { quantized: true } }, ({ faceLandmark68TinyNet }) => {
describe('NeuralNetwork, uncompressed model', () => {
it('disposes all param tensors', async () => {
await expectAllTensorsReleased(async () => {
const res = await fetch('base/weights_uncompressed/face_landmark_68_model.weights')
const weights = new Float32Array(await res.arrayBuffer())
const net = createFaceLandmarkNet(weights)
net.dispose()
})
})
})
describe('NeuralNetwork, quantized model', () => { describe('NeuralNetwork, quantized model', () => {
it('disposes all param tensors', async () => { it('disposes all param tensors', async () => {
......
import { fetchImage, fetchJson, Point } from '../../../src'; import { fetchImage, fetchJson, Point } from '../../../src';
import { FaceLandmarks68 } from '../../../src/classes/FaceLandmarks68'; import { FaceLandmarks68 } from '../../../src/classes/FaceLandmarks68';
import { describeWithNets, expectPointClose } from '../../utils'; import { createFaceLandmarkNet } from '../../../src/faceLandmarkNet';
import { describeWithNets, expectAllTensorsReleased, expectPointClose } from '../../utils';
describe('faceLandmark68TinyNet, uncompressed', () => { describe('faceLandmark68TinyNet, uncompressed', () => {
...@@ -46,6 +47,15 @@ describe('faceLandmark68TinyNet, uncompressed', () => { ...@@ -46,6 +47,15 @@ describe('faceLandmark68TinyNet, uncompressed', () => {
}) })
}) })
it('no memory leaks', async () => {
await expectAllTensorsReleased(async () => {
const res = await fetch('base/weights_uncompressed/face_landmark_68_model.weights')
const weights = new Float32Array(await res.arrayBuffer())
const net = createFaceLandmarkNet(weights)
net.dispose()
})
})
}) })
}) })
......
...@@ -2,7 +2,6 @@ import * as tf from '@tensorflow/tfjs-core'; ...@@ -2,7 +2,6 @@ import * as tf from '@tensorflow/tfjs-core';
import { FaceRecognitionNet, fetchImage, fetchJson, NetInput, toNetInput } from '../../../src'; import { FaceRecognitionNet, fetchImage, fetchJson, NetInput, toNetInput } from '../../../src';
import { euclideanDistance } from '../../../src/euclideanDistance'; import { euclideanDistance } from '../../../src/euclideanDistance';
import { createFaceRecognitionNet } from '../../../src/faceRecognitionNet';
import { describeWithNets, expectAllTensorsReleased } from '../../utils'; import { describeWithNets, expectAllTensorsReleased } from '../../utils';
describe('faceRecognitionNet', () => { describe('faceRecognitionNet', () => {
...@@ -97,19 +96,6 @@ describe('faceRecognitionNet', () => { ...@@ -97,19 +96,6 @@ describe('faceRecognitionNet', () => {
describeWithNets('no memory leaks', { withFaceRecognitionNet: { quantized: true } }, ({ faceRecognitionNet }) => { describeWithNets('no memory leaks', { withFaceRecognitionNet: { quantized: true } }, ({ faceRecognitionNet }) => {
describe('NeuralNetwork, uncompressed model', () => {
it('disposes all param tensors', async () => {
await expectAllTensorsReleased(async () => {
const res = await fetch('base/weights_uncompressed/face_recognition_model.weights')
const weights = new Float32Array(await res.arrayBuffer())
const net = createFaceRecognitionNet(weights)
net.dispose()
})
})
})
describe('NeuralNetwork, quantized model', () => { describe('NeuralNetwork, quantized model', () => {
it('disposes all param tensors', async () => { it('disposes all param tensors', async () => {
......
import { fetchImage, fetchJson } from '../../../src'; import { fetchImage, fetchJson } from '../../../src';
import { euclideanDistance } from '../../../src/euclideanDistance'; import { euclideanDistance } from '../../../src/euclideanDistance';
import { describeWithNets } from '../../utils'; import { createFaceRecognitionNet } from '../../../src/faceRecognitionNet';
import { describeWithNets, expectAllTensorsReleased } from '../../utils';
describe('faceRecognitionNet, uncompressed', () => { describe('faceRecognitionNet, uncompressed', () => {
...@@ -30,5 +31,14 @@ describe('faceRecognitionNet, uncompressed', () => { ...@@ -30,5 +31,14 @@ describe('faceRecognitionNet, uncompressed', () => {
expect(euclideanDistance(result, faceDescriptorRect)).toBeLessThan(0.1) expect(euclideanDistance(result, faceDescriptorRect)).toBeLessThan(0.1)
}) })
it('no memory leaks', async () => {
await expectAllTensorsReleased(async () => {
const res = await fetch('base/weights_uncompressed/face_recognition_model.weights')
const weights = new Float32Array(await res.arrayBuffer())
const net = createFaceRecognitionNet(weights)
net.dispose()
})
})
}) })
}) })
\ No newline at end of file
...@@ -13,8 +13,8 @@ describe('mtcnn.forward', () => { ...@@ -13,8 +13,8 @@ describe('mtcnn.forward', () => {
expectedMtcnnLandmarks = await fetchJson<IPoint[][]>('base/test/data/mtcnnFaceLandmarkPositions.json') expectedMtcnnLandmarks = await fetchJson<IPoint[][]>('base/test/data/mtcnnFaceLandmarkPositions.json')
}) })
describeWithNets('uncompressed weights', { withMtcnn: { quantized: false } }, ({ mtcnn }) => { // "quantized" actually means loaded from manifest.json, since there is no quantization applied to the mtcnn model
describeWithNets('quantized weights', { withMtcnn: { quantized: true } }, ({ mtcnn }) => {
it('minFaceSize = 20, finds all faces', async () => { it('minFaceSize = 20, finds all faces', async () => {
const forwardParams = { const forwardParams = {
...@@ -25,6 +25,7 @@ describe('mtcnn.forward', () => { ...@@ -25,6 +25,7 @@ describe('mtcnn.forward', () => {
expect(results.length).toEqual(6) expect(results.length).toEqual(6)
const deltas = { const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 2, maxBoxDelta: 2,
maxLandmarksDelta: 5 maxLandmarksDelta: 5
} }
...@@ -40,6 +41,7 @@ describe('mtcnn.forward', () => { ...@@ -40,6 +41,7 @@ describe('mtcnn.forward', () => {
expect(results.length).toEqual(6) expect(results.length).toEqual(6)
const deltas = { const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 15, maxBoxDelta: 15,
maxLandmarksDelta: 13 maxLandmarksDelta: 13
} }
...@@ -58,6 +60,7 @@ describe('mtcnn.forward', () => { ...@@ -58,6 +60,7 @@ describe('mtcnn.forward', () => {
expect(results.length).toEqual(6) expect(results.length).toEqual(6)
const deltas = { const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 8, maxBoxDelta: 8,
maxLandmarksDelta: 7 maxLandmarksDelta: 7
} }
...@@ -73,32 +76,14 @@ describe('mtcnn.forward', () => { ...@@ -73,32 +76,14 @@ describe('mtcnn.forward', () => {
expect(results.length).toEqual(6) expect(results.length).toEqual(6)
const deltas = { const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 8, maxBoxDelta: 8,
maxLandmarksDelta: 10 maxLandmarksDelta: 10
} }
expectMtcnnResults(results, expectedMtcnnLandmarks, [1.0, 1.0, 1.0, 1.0, 1.0, 1.0], deltas) expectMtcnnResults(results, expectedMtcnnLandmarks, [1.0, 1.0, 1.0, 1.0, 1.0, 1.0], deltas)
}) })
}) it('no memory leaks', async () => {
describe('no memory leaks', () => {
describe('NeuralNetwork, uncompressed model', () => {
it('disposes all param tensors', async () => {
await expectAllTensorsReleased(async () => {
const res = await fetch('base/weights_uncompressed/mtcnn_model.weights')
const weights = new Float32Array(await res.arrayBuffer())
const net = faceapi.createMtcnn(weights)
net.dispose()
})
})
})
describe('NeuralNetwork, quantized model', () => {
it('disposes all param tensors', async () => {
await expectAllTensorsReleased(async () => { await expectAllTensorsReleased(async () => {
const net = new faceapi.Mtcnn() const net = new faceapi.Mtcnn()
await net.load('base/weights') await net.load('base/weights')
...@@ -108,6 +93,4 @@ describe('mtcnn.forward', () => { ...@@ -108,6 +93,4 @@ describe('mtcnn.forward', () => {
}) })
})
}) })
\ No newline at end of file
import * as faceapi from '../../../src';
import { describeWithNets, expectAllTensorsReleased } from '../../utils';
import { expectMtcnnResults } from './expectMtcnnResults';
import { IPoint, fetchImage, fetchJson } from '../../../src';
describe('mtcnn.forward', () => {
let imgEl: HTMLImageElement
let expectedMtcnnLandmarks: IPoint[][]
beforeAll(async () => {
imgEl = await fetchImage('base/test/images/faces.jpg')
expectedMtcnnLandmarks = await fetchJson<IPoint[][]>('base/test/data/mtcnnFaceLandmarkPositions.json')
})
describeWithNets('uncompressed weights', { withMtcnn: { quantized: false } }, ({ mtcnn }) => {
it('minFaceSize = 20, finds all faces', async () => {
const forwardParams = {
minFaceSize: 20
}
const results = await mtcnn.forward(imgEl, forwardParams)
expect(results.length).toEqual(6)
const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 2,
maxLandmarksDelta: 5
}
expectMtcnnResults(results, expectedMtcnnLandmarks, [1.0, 1.0, 1.0, 1.0, 0.99, 0.99], deltas)
})
it('minFaceSize = 80, finds all faces', async () => {
const forwardParams = {
minFaceSize: 80
}
const results = await mtcnn.forward(imgEl, forwardParams)
expect(results.length).toEqual(6)
const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 15,
maxLandmarksDelta: 13
}
expectMtcnnResults(results, expectedMtcnnLandmarks, [1.0, 1.0, 1.0, 1.0, 1.0, 0.99], deltas)
})
it('all optional params passed, finds all faces', async () => {
const forwardParams = {
maxNumScales: 10,
scaleFactor: 0.8,
scoreThresholds: [0.8, 0.8, 0.9],
minFaceSize: 20
}
const results = await mtcnn.forward(imgEl, forwardParams)
expect(results.length).toEqual(6)
const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 8,
maxLandmarksDelta: 7
}
expectMtcnnResults(results, expectedMtcnnLandmarks, [1.0, 1.0, 1.0, 0.99, 1.0, 1.0], deltas)
})
it('scale steps passed, finds all faces', async () => {
const forwardParams = {
scaleSteps: [0.6, 0.4, 0.2, 0.15, 0.1, 0.08, 0.02]
}
const results = await mtcnn.forward(imgEl, forwardParams)
expect(results.length).toEqual(6)
const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 8,
maxLandmarksDelta: 10
}
expectMtcnnResults(results, expectedMtcnnLandmarks, [1.0, 1.0, 1.0, 1.0, 1.0, 1.0], deltas)
})
it('no memory leaks', async () => {
await expectAllTensorsReleased(async () => {
const res = await fetch('base/weights_uncompressed/mtcnn_model.weights')
const weights = new Float32Array(await res.arrayBuffer())
const net = faceapi.createMtcnn(weights)
net.dispose()
})
})
})
})
\ No newline at end of file
...@@ -26,10 +26,10 @@ describe('mtcnn', () => { ...@@ -26,10 +26,10 @@ describe('mtcnn', () => {
}) })
const results = await faceapi.detectAllFaces(imgEl, options) const results = await faceapi.detectAllFaces(imgEl, options)
const maxScoreDelta = 0.01
const maxBoxDelta = 2 const maxBoxDelta = 2
expect(results.length).toEqual(6) expect(results.length).toEqual(6)
expectFaceDetections(results, expectedMtcnnBoxes, expectedScores, maxBoxDelta) expectFaceDetections(results, expectedMtcnnBoxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('detectAllFaces.withFaceLandmarks().withFaceDescriptors()', async () => { it('detectAllFaces.withFaceLandmarks().withFaceDescriptors()', async () => {
...@@ -42,6 +42,7 @@ describe('mtcnn', () => { ...@@ -42,6 +42,7 @@ describe('mtcnn', () => {
.withFaceLandmarks() .withFaceLandmarks()
const deltas = { const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 2, maxBoxDelta: 2,
maxLandmarksDelta: 6 maxLandmarksDelta: 6
} }
...@@ -60,6 +61,7 @@ describe('mtcnn', () => { ...@@ -60,6 +61,7 @@ describe('mtcnn', () => {
.withFaceDescriptors() .withFaceDescriptors()
const deltas = { const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 2, maxBoxDelta: 2,
maxLandmarksDelta: 6, maxLandmarksDelta: 6,
maxDescriptorDelta: 0.2 maxDescriptorDelta: 0.2
......
...@@ -20,9 +20,10 @@ describe('ssdMobilenetv1.locateFaces', () => { ...@@ -20,9 +20,10 @@ describe('ssdMobilenetv1.locateFaces', () => {
expect(detections.length).toEqual(4) expect(detections.length).toEqual(4)
const expectedScores = [-1, 0.81, 0.97, 0.88, 0.84, -1] const expectedScores = [-1, 0.81, 0.97, 0.88, 0.84, -1]
const maxScoreDelta = 0.01
const maxBoxDelta = 4 const maxBoxDelta = 4
expectFaceDetections(detections, expectedSsdBoxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedSsdBoxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('scores > 0.5', async () => { it('scores > 0.5', async () => {
...@@ -31,9 +32,10 @@ describe('ssdMobilenetv1.locateFaces', () => { ...@@ -31,9 +32,10 @@ describe('ssdMobilenetv1.locateFaces', () => {
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
const expectedScores = [0.54, 0.81, 0.97, 0.88, 0.84, 0.61] const expectedScores = [0.54, 0.81, 0.97, 0.88, 0.84, 0.61]
const maxScoreDelta = 0.01
const maxBoxDelta = 5 const maxBoxDelta = 5
expectFaceDetections(detections, expectedSsdBoxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedSsdBoxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('no memory leaks', async () => { it('no memory leaks', async () => {
......
...@@ -20,9 +20,10 @@ describe('ssdMobilenetv1.locateFaces, uncompressed', () => { ...@@ -20,9 +20,10 @@ describe('ssdMobilenetv1.locateFaces, uncompressed', () => {
expect(detections.length).toEqual(3) expect(detections.length).toEqual(3)
const expectedScores = [-1, -1, 0.98, 0.88, 0.81, -1] const expectedScores = [-1, -1, 0.98, 0.88, 0.81, -1]
const maxScoreDelta = 0.01
const maxBoxDelta = 3 const maxBoxDelta = 3
expectFaceDetections(detections, expectedSsdBoxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedSsdBoxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('scores > 0.5', async () => { it('scores > 0.5', async () => {
...@@ -31,9 +32,10 @@ describe('ssdMobilenetv1.locateFaces, uncompressed', () => { ...@@ -31,9 +32,10 @@ describe('ssdMobilenetv1.locateFaces, uncompressed', () => {
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
const expectedScores = [0.57, 0.74, 0.98, 0.88, 0.81, 0.58] const expectedScores = [0.57, 0.74, 0.98, 0.88, 0.81, 0.58]
const maxScoreDelta = 0.01
const maxBoxDelta = 3 const maxBoxDelta = 3
expectFaceDetections(detections, expectedSsdBoxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedSsdBoxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('no memory leaks', async () => { it('no memory leaks', async () => {
......
...@@ -26,9 +26,10 @@ describe('ssdMobilenetv1', () => { ...@@ -26,9 +26,10 @@ describe('ssdMobilenetv1', () => {
const results = await faceapi.detectAllFaces(imgEl, options) const results = await faceapi.detectAllFaces(imgEl, options)
const maxScoreDelta = 0.01
const maxBoxDelta = 5 const maxBoxDelta = 5
expect(results.length).toEqual(6) expect(results.length).toEqual(6)
expectFaceDetections(results, expectedSsdBoxes, expectedScores, maxBoxDelta) expectFaceDetections(results, expectedSsdBoxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('detectAllFaces.withFaceLandmarks()', async () => { it('detectAllFaces.withFaceLandmarks()', async () => {
...@@ -41,8 +42,9 @@ describe('ssdMobilenetv1', () => { ...@@ -41,8 +42,9 @@ describe('ssdMobilenetv1', () => {
.withFaceLandmarks() .withFaceLandmarks()
const deltas = { const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 5, maxBoxDelta: 5,
maxLandmarksDelta: 1 maxLandmarksDelta: 2
} }
expect(results.length).toEqual(6) expect(results.length).toEqual(6)
expectFaceDetectionsWithLandmarks(results, expectedFullFaceDescriptions, expectedScores, deltas) expectFaceDetectionsWithLandmarks(results, expectedFullFaceDescriptions, expectedScores, deltas)
...@@ -59,8 +61,9 @@ describe('ssdMobilenetv1', () => { ...@@ -59,8 +61,9 @@ describe('ssdMobilenetv1', () => {
.withFaceDescriptors() .withFaceDescriptors()
const deltas = { const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 5, maxBoxDelta: 5,
maxLandmarksDelta: 1, maxLandmarksDelta: 2,
maxDescriptorDelta: 0.1 maxDescriptorDelta: 0.1
} }
expect(results.length).toEqual(6) expect(results.length).toEqual(6)
......
...@@ -20,9 +20,10 @@ describe('tinyFaceDetector.locateFaces', () => { ...@@ -20,9 +20,10 @@ describe('tinyFaceDetector.locateFaces', () => {
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
const expectedScores = [0.77, 0.75, 0.88, 0.77, 0.83, 0.85] const expectedScores = [0.77, 0.75, 0.88, 0.77, 0.83, 0.85]
const maxBoxDelta = 36 const maxScoreDelta = 0.01
const maxBoxDelta = 40
expectFaceDetections(detections, expectedTinyFaceDetectorBoxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedTinyFaceDetectorBoxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('inputSize 416, finds all faces', async () => { it('inputSize 416, finds all faces', async () => {
...@@ -31,9 +32,10 @@ describe('tinyFaceDetector.locateFaces', () => { ...@@ -31,9 +32,10 @@ describe('tinyFaceDetector.locateFaces', () => {
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
const expectedScores = [0.7, 0.82, 0.93, 0.86, 0.79, 0.84] const expectedScores = [0.7, 0.82, 0.93, 0.86, 0.79, 0.84]
const maxScoreDelta = 0.01
const maxBoxDelta = 1 const maxBoxDelta = 1
expectFaceDetections(detections, expectedTinyFaceDetectorBoxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedTinyFaceDetectorBoxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('no memory leaks', async () => { it('no memory leaks', async () => {
......
...@@ -26,9 +26,10 @@ describe('tinyFaceDetector', () => { ...@@ -26,9 +26,10 @@ describe('tinyFaceDetector', () => {
const results = await faceapi.detectAllFaces(imgEl, options) const results = await faceapi.detectAllFaces(imgEl, options)
const maxScoreDelta = 0.01
const maxBoxDelta = 1 const maxBoxDelta = 1
expect(results.length).toEqual(6) expect(results.length).toEqual(6)
expectFaceDetections(results, expectedTinyFaceDetectorBoxes, expectedScores, maxBoxDelta) expectFaceDetections(results, expectedTinyFaceDetectorBoxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('detectAllFaces.withFaceLandmarks()', async () => { it('detectAllFaces.withFaceLandmarks()', async () => {
...@@ -41,6 +42,7 @@ describe('tinyFaceDetector', () => { ...@@ -41,6 +42,7 @@ describe('tinyFaceDetector', () => {
.withFaceLandmarks() .withFaceLandmarks()
const deltas = { const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 1, maxBoxDelta: 1,
maxLandmarksDelta: 10 maxLandmarksDelta: 10
} }
...@@ -59,6 +61,7 @@ describe('tinyFaceDetector', () => { ...@@ -59,6 +61,7 @@ describe('tinyFaceDetector', () => {
.withFaceDescriptors() .withFaceDescriptors()
const deltas = { const deltas = {
maxScoreDelta: 0.01,
maxBoxDelta: 1, maxBoxDelta: 1,
maxLandmarksDelta: 10, maxLandmarksDelta: 10,
maxDescriptorDelta: 0.2 maxDescriptorDelta: 0.2
......
...@@ -5,7 +5,7 @@ import { expectFaceDetections } from '../../expectFaceDetections'; ...@@ -5,7 +5,7 @@ import { expectFaceDetections } from '../../expectFaceDetections';
import { describeWithNets, expectAllTensorsReleased } from '../../utils'; import { describeWithNets, expectAllTensorsReleased } from '../../utils';
import { expectedTinyYolov2Boxes } from './expectedBoxes'; import { expectedTinyYolov2Boxes } from './expectedBoxes';
xdescribe('tinyYolov2.locateFaces', () => { describe('tinyYolov2.locateFaces', () => {
let imgEl: HTMLImageElement let imgEl: HTMLImageElement
...@@ -19,30 +19,33 @@ xdescribe('tinyYolov2.locateFaces', () => { ...@@ -19,30 +19,33 @@ xdescribe('tinyYolov2.locateFaces', () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: TinyYolov2SizeType.LG }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: TinyYolov2SizeType.LG })
const expectedScores = [0.8, 0.85, 0.86, 0.83, 0.86, 0.81] const expectedScores = [0.8, 0.85, 0.86, 0.83, 0.86, 0.81]
const maxScoreDelta = 0.01
const maxBoxDelta = 4 const maxBoxDelta = 4
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('inputSize md, finds all faces', async () => { it('inputSize md, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: TinyYolov2SizeType.MD }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: TinyYolov2SizeType.MD })
const expectedScores = [0.89, 0.81, 0.82, 0.72, 0.81, 0.86] const expectedScores = [0.89, 0.81, 0.82, 0.72, 0.81, 0.86]
const maxScoreDelta = 0.01
const maxBoxDelta = 27 const maxBoxDelta = 27
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('inputSize custom, finds all faces', async () => { it('inputSize custom, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: 416 }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: 416 })
const expectedScores = [0.89, 0.81, 0.82, 0.72, 0.81, 0.86] const expectedScores = [0.89, 0.81, 0.82, 0.72, 0.81, 0.86]
const maxScoreDelta = 0.01
const maxBoxDelta = 27 const maxBoxDelta = 27
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('no memory leaks', async () => { it('no memory leaks', async () => {
......
...@@ -5,7 +5,7 @@ import { expectFaceDetections } from '../../expectFaceDetections'; ...@@ -5,7 +5,7 @@ import { expectFaceDetections } from '../../expectFaceDetections';
import { describeWithNets, expectAllTensorsReleased } from '../../utils'; import { describeWithNets, expectAllTensorsReleased } from '../../utils';
import { expectedTinyYolov2Boxes } from './expectedBoxes'; import { expectedTinyYolov2Boxes } from './expectedBoxes';
xdescribe('tinyYolov2.locateFaces, uncompressed', () => { describe('tinyYolov2.locateFaces, uncompressed', () => {
let imgEl: HTMLImageElement let imgEl: HTMLImageElement
...@@ -19,30 +19,33 @@ xdescribe('tinyYolov2.locateFaces, uncompressed', () => { ...@@ -19,30 +19,33 @@ xdescribe('tinyYolov2.locateFaces, uncompressed', () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: TinyYolov2SizeType.LG }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: TinyYolov2SizeType.LG })
const expectedScores = [0.81, 0.85, 0.86, 0.83, 0.86, 0.81] const expectedScores = [0.81, 0.85, 0.86, 0.83, 0.86, 0.81]
const maxScoreDelta = 0.01
const maxBoxDelta = 1 const maxBoxDelta = 1
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('inputSize md, finds all faces', async () => { it('inputSize md, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: TinyYolov2SizeType.MD }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: TinyYolov2SizeType.MD })
const expectedScores = [0.89, 0.82, 0.82, 0.72, 0.81, 0.86] const expectedScores = [0.89, 0.82, 0.82, 0.72, 0.81, 0.86]
const maxScoreDelta = 0.01
const maxBoxDelta = 24 const maxBoxDelta = 24
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('inputSize custom, finds all faces', async () => { it('inputSize custom, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: 416 }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: 416 })
const expectedScores = [0.89, 0.82, 0.82, 0.72, 0.81, 0.86] const expectedScores = [0.89, 0.82, 0.82, 0.72, 0.81, 0.86]
const maxScoreDelta = 0.01
const maxBoxDelta = 24 const maxBoxDelta = 24
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('no memory leaks', async () => { it('no memory leaks', async () => {
......
...@@ -5,7 +5,7 @@ import { expectFaceDetections } from '../../expectFaceDetections'; ...@@ -5,7 +5,7 @@ import { expectFaceDetections } from '../../expectFaceDetections';
import { describeWithNets, expectAllTensorsReleased } from '../../utils'; import { describeWithNets, expectAllTensorsReleased } from '../../utils';
import { expectedTinyYolov2Boxes } from './expectedBoxes'; import { expectedTinyYolov2Boxes } from './expectedBoxes';
xdescribe('tinyYolov2.locateFaces, with separable convolutions', () => { describe('tinyYolov2.locateFaces, with separable convolutions', () => {
let imgEl: HTMLImageElement let imgEl: HTMLImageElement
...@@ -19,30 +19,33 @@ xdescribe('tinyYolov2.locateFaces, with separable convolutions', () => { ...@@ -19,30 +19,33 @@ xdescribe('tinyYolov2.locateFaces, with separable convolutions', () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: TinyYolov2SizeType.LG }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: TinyYolov2SizeType.LG })
const expectedScores = [0.85, 0.88, 0.9, 0.85, 0.9, 0.85] const expectedScores = [0.85, 0.88, 0.9, 0.85, 0.9, 0.85]
const maxScoreDelta = 0.01
const maxBoxDelta = 25 const maxBoxDelta = 25
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('inputSize md, finds all faces', async () => { it('inputSize md, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: TinyYolov2SizeType.MD }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: TinyYolov2SizeType.MD })
const expectedScores = [0.85, 0.8, 0.8, 0.85, 0.85, 0.83] const expectedScores = [0.85, 0.8, 0.8, 0.85, 0.85, 0.83]
const maxScoreDelta = 0.01
const maxBoxDelta = 34 const maxBoxDelta = 34
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
it('inputSize custom, finds all faces', async () => { it('inputSize custom, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: 416 }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: 416 })
const expectedScores = [0.85, 0.8, 0.8, 0.85, 0.85, 0.83] const expectedScores = [0.85, 0.8, 0.8, 0.85, 0.85, 0.83]
const maxScoreDelta = 0.01
const maxBoxDelta = 34 const maxBoxDelta = 34
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxBoxDelta) expectFaceDetections(detections, expectedTinyYolov2Boxes, expectedScores, maxScoreDelta, maxBoxDelta)
}) })
}) })
......
...@@ -11,6 +11,11 @@ import { TinyFaceDetector } from '../src/tinyFaceDetector/TinyFaceDetector'; ...@@ -11,6 +11,11 @@ import { TinyFaceDetector } from '../src/tinyFaceDetector/TinyFaceDetector';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000 jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000
const args: string[] = window['__karma__'].config.jasmine.args
if (args.some(arg => arg === 'backend_cpu')) {
tf.setBackend('cpu')
}
export function expectMaxDelta(val1: number, val2: number, maxDelta: number) { export function expectMaxDelta(val1: number, val2: number, maxDelta: number) {
expect(Math.abs(val1 - val2)).toBeLessThan(maxDelta) expect(Math.abs(val1 - val2)).toBeLessThan(maxDelta)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment