Commit 84909181 by vincent

weight loading of quantized tiny-yolov2-seperable-conv2d + use separable conv…

weight loading of quantized tiny-yolov2-seperable-conv2d + use separable conv model by default + testcases
parent 4f45297b
...@@ -20,17 +20,17 @@ import { NetParams, PostProcessingParams, TinyYolov2ForwardParams } from './type ...@@ -20,17 +20,17 @@ import { NetParams, PostProcessingParams, TinyYolov2ForwardParams } from './type
export class TinyYolov2 extends NeuralNetwork<NetParams> { export class TinyYolov2 extends NeuralNetwork<NetParams> {
private _hasSeparableConvs: boolean private _withSeparableConvs: boolean
private _anchors: Point[] private _anchors: Point[]
constructor(hasSeparableConvs: boolean = false) { constructor(withSeparableConvs: boolean = true) {
super('TinyYolov2') super('TinyYolov2')
this._hasSeparableConvs = hasSeparableConvs this._withSeparableConvs = withSeparableConvs
this._anchors = hasSeparableConvs ? BOX_ANCHORS_SEPARABLE : BOX_ANCHORS this._anchors = withSeparableConvs ? BOX_ANCHORS_SEPARABLE : BOX_ANCHORS
} }
public get hasSeparableConvs(): boolean { public get withSeparableConvs(): boolean {
return this._hasSeparableConvs return this._withSeparableConvs
} }
public get anchors(): Point[] { public get anchors(): Point[] {
...@@ -48,7 +48,7 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> { ...@@ -48,7 +48,7 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> {
const out = tf.tidy(() => { const out = tf.tidy(() => {
let batchTensor = input.toBatchTensor(inputSize, false) let batchTensor = input.toBatchTensor(inputSize, false)
batchTensor = this.hasSeparableConvs batchTensor = this.withSeparableConvs
? normalize(batchTensor, MEAN_RGB) ? normalize(batchTensor, MEAN_RGB)
: batchTensor : batchTensor
batchTensor = batchTensor.div(tf.scalar(256)) as tf.Tensor4D batchTensor = batchTensor.div(tf.scalar(256)) as tf.Tensor4D
...@@ -132,7 +132,7 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> { ...@@ -132,7 +132,7 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> {
const numCells = outputTensor.shape[1] const numCells = outputTensor.shape[1]
const [boxesTensor, scoresTensor] = tf.tidy(() => { const [boxesTensor, scoresTensor] = tf.tidy(() => {
const reshaped = outputTensor.reshape([numCells, numCells, NUM_BOXES, this.hasSeparableConvs ? 5 : 6]) const reshaped = outputTensor.reshape([numCells, numCells, NUM_BOXES, this.withSeparableConvs ? 5 : 6])
const boxes = reshaped.slice([0, 0, 0, 0], [numCells, numCells, NUM_BOXES, 4]) const boxes = reshaped.slice([0, 0, 0, 0], [numCells, numCells, NUM_BOXES, 4])
const scores = reshaped.slice([0, 0, 0, 4], [numCells, numCells, NUM_BOXES, 1]) const scores = reshaped.slice([0, 0, 0, 4], [numCells, numCells, NUM_BOXES, 1])
...@@ -172,10 +172,10 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> { ...@@ -172,10 +172,10 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> {
} }
protected loadQuantizedParams(uri: string | undefined) { protected loadQuantizedParams(uri: string | undefined) {
return loadQuantizedParams(uri) return loadQuantizedParams(uri, this.withSeparableConvs)
} }
protected extractParams(weights: Float32Array) { protected extractParams(weights: Float32Array) {
return extractParams(weights, this.hasSeparableConvs) return extractParams(weights, this.withSeparableConvs)
} }
} }
\ No newline at end of file
...@@ -56,7 +56,7 @@ function extractorsFactory(extractWeights: ExtractWeightsFunction, paramMappings ...@@ -56,7 +56,7 @@ function extractorsFactory(extractWeights: ExtractWeightsFunction, paramMappings
} }
export function extractParams(weights: Float32Array, hasSeparableConvs: boolean): { params: NetParams, paramMappings: ParamMapping[] } { export function extractParams(weights: Float32Array, withSeparableConvs: boolean): { params: NetParams, paramMappings: ParamMapping[] } {
const { const {
extractWeights, extractWeights,
...@@ -71,8 +71,8 @@ export function extractParams(weights: Float32Array, hasSeparableConvs: boolean) ...@@ -71,8 +71,8 @@ export function extractParams(weights: Float32Array, hasSeparableConvs: boolean)
extractSeparableConvParams extractSeparableConvParams
} = extractorsFactory(extractWeights, paramMappings) } = extractorsFactory(extractWeights, paramMappings)
const extractConvFn = hasSeparableConvs ? extractSeparableConvParams : extractConvWithBatchNormParams const extractConvFn = withSeparableConvs ? extractSeparableConvParams : extractConvWithBatchNormParams
const numAnchorEncodings = hasSeparableConvs ? 5 : 6 const numAnchorEncodings = withSeparableConvs ? 5 : 6
const conv0 = extractConvFn(3, 16, 'conv0',) const conv0 = extractConvFn(3, 16, 'conv0',)
const conv1 = extractConvFn(16, 32, 'conv1') const conv1 = extractConvFn(16, 32, 'conv1')
......
...@@ -2,8 +2,8 @@ import { TinyYolov2 } from './TinyYolov2'; ...@@ -2,8 +2,8 @@ import { TinyYolov2 } from './TinyYolov2';
export * from './TinyYolov2'; export * from './TinyYolov2';
export function createTinyYolov2(weights: Float32Array) { export function createTinyYolov2(weights: Float32Array, withSeparableConvs: boolean = true) {
const net = new TinyYolov2() const net = new TinyYolov2(withSeparableConvs)
net.extractWeights(weights) net.extractWeights(weights)
return net return net
} }
\ No newline at end of file
...@@ -4,9 +4,10 @@ import { disposeUnusedWeightTensors } from '../commons/disposeUnusedWeightTensor ...@@ -4,9 +4,10 @@ import { disposeUnusedWeightTensors } from '../commons/disposeUnusedWeightTensor
import { extractWeightEntryFactory } from '../commons/extractWeightEntryFactory'; import { extractWeightEntryFactory } from '../commons/extractWeightEntryFactory';
import { loadWeightMap } from '../commons/loadWeightMap'; import { loadWeightMap } from '../commons/loadWeightMap';
import { ConvParams, ParamMapping } from '../commons/types'; import { ConvParams, ParamMapping } from '../commons/types';
import { BatchNorm, ConvWithBatchNorm, NetParams } from './types'; import { BatchNorm, ConvWithBatchNorm, NetParams, SeparableConvParams } from './types';
const DEFAULT_MODEL_NAME = 'tiny_yolov2_model' const DEFAULT_MODEL_NAME = 'tiny_yolov2_model'
const DEFAULT_MODEL_NAME_SEPARABLE_CONV = 'tiny_yolov2_separable_conv_model'
function extractorsFactory(weightMap: any, paramMappings: ParamMapping[]) { function extractorsFactory(weightMap: any, paramMappings: ParamMapping[]) {
...@@ -30,35 +31,51 @@ function extractorsFactory(weightMap: any, paramMappings: ParamMapping[]) { ...@@ -30,35 +31,51 @@ function extractorsFactory(weightMap: any, paramMappings: ParamMapping[]) {
return { conv, bn } return { conv, bn }
} }
function extractSeparableConvParams(prefix: string): SeparableConvParams {
const depthwise_filter = extractWeightEntry<tf.Tensor4D>(`${prefix}/depthwise_filter`, 4)
const pointwise_filter = extractWeightEntry<tf.Tensor4D>(`${prefix}/pointwise_filter`, 4)
const bias = extractWeightEntry<tf.Tensor1D>(`${prefix}/bias`, 1)
return new SeparableConvParams(
depthwise_filter,
pointwise_filter,
bias
)
}
return { return {
extractConvParams, extractConvParams,
extractConvWithBatchNormParams extractConvWithBatchNormParams,
extractSeparableConvParams
} }
} }
export async function loadQuantizedParams( export async function loadQuantizedParams(
uri: string | undefined uri: string | undefined,
withSeparableConvs: boolean
): Promise<{ params: NetParams, paramMappings: ParamMapping[] }> { ): Promise<{ params: NetParams, paramMappings: ParamMapping[] }> {
const weightMap = await loadWeightMap(uri, DEFAULT_MODEL_NAME) const weightMap = await loadWeightMap(uri, withSeparableConvs ? DEFAULT_MODEL_NAME_SEPARABLE_CONV : DEFAULT_MODEL_NAME)
const paramMappings: ParamMapping[] = [] const paramMappings: ParamMapping[] = []
const { const {
extractConvParams, extractConvParams,
extractConvWithBatchNormParams extractConvWithBatchNormParams,
extractSeparableConvParams
} = extractorsFactory(weightMap, paramMappings) } = extractorsFactory(weightMap, paramMappings)
const extractConvFn = withSeparableConvs ? extractSeparableConvParams : extractConvWithBatchNormParams
const params = { const params = {
conv0: extractConvWithBatchNormParams('conv0'), conv0: extractConvFn('conv0'),
conv1: extractConvWithBatchNormParams('conv1'), conv1: extractConvFn('conv1'),
conv2: extractConvWithBatchNormParams('conv2'), conv2: extractConvFn('conv2'),
conv3: extractConvWithBatchNormParams('conv3'), conv3: extractConvFn('conv3'),
conv4: extractConvWithBatchNormParams('conv4'), conv4: extractConvFn('conv4'),
conv5: extractConvWithBatchNormParams('conv5'), conv5: extractConvFn('conv5'),
conv6: extractConvWithBatchNormParams('conv6'), conv6: extractConvFn('conv6'),
conv7: extractConvWithBatchNormParams('conv7'), conv7: extractConvFn('conv7'),
conv8: extractConvParams('conv8') conv8: extractConvParams('conv8')
} }
......
...@@ -29,6 +29,15 @@ export const expectedTinyYolov2Boxes = [ ...@@ -29,6 +29,15 @@ export const expectedTinyYolov2Boxes = [
{ x: 87, y: 30, width: 92, height: 93 } { x: 87, y: 30, width: 92, height: 93 }
] ]
export const expectedTinyYolov2SeparableConvBoxes = [
{ x: 42, y: 257, width: 111, height: 121 },
{ x: 454, y: 175, width: 104, height: 121 },
{ x: 230, y: 45, width: 94, height: 104 },
{ x: 574, y: 62, width: 88, height: 113 },
{ x: 260, y: 233, width: 82, height: 104 },
{ x: 83, y: 24, width: 85, height: 111 }
]
export const expectedMtcnnFaceLandmarks = [ export const expectedMtcnnFaceLandmarks = [
[new Point(117, 58), new Point(156, 63), new Point(141, 86), new Point(109, 98), new Point(147, 104)], [new Point(117, 58), new Point(156, 63), new Point(141, 86), new Point(109, 98), new Point(147, 104)],
[new Point(82, 292), new Point(134, 304), new Point(104, 330), new Point(72, 342), new Point(120, 353)], [new Point(82, 292), new Point(134, 304), new Point(104, 330), new Point(72, 342), new Point(120, 353)],
...@@ -38,7 +47,6 @@ export const expectedMtcnnFaceLandmarks = [ ...@@ -38,7 +47,6 @@ export const expectedMtcnnFaceLandmarks = [
[new Point(489, 224), new Point(534, 223), new Point(507, 250), new Point(493, 271), new Point(530, 270)] [new Point(489, 224), new Point(534, 223), new Point(507, 250), new Point(493, 271), new Point(530, 270)]
] ]
export function expectMtcnnResults( export function expectMtcnnResults(
results: { faceDetection: faceapi.FaceDetection, faceLandmarks: faceapi.FaceLandmarks5 }[], results: { faceDetection: faceapi.FaceDetection, faceLandmarks: faceapi.FaceLandmarks5 }[],
boxOrder: number[], boxOrder: number[],
......
import * as faceapi from '../../../src'; import * as faceapi from '../../../src';
import { SizeType } from '../../../src/tinyYolov2/types'; import { SizeType } from '../../../src/tinyYolov2/types';
import { describeWithNets, expectAllTensorsReleased, expectRectClose } from '../../utils'; import { describeWithNets, expectAllTensorsReleased, expectRectClose } from '../../utils';
import { expectedTinyYolov2Boxes } from './expectedResults'; import { expectedTinyYolov2Boxes, expectedTinyYolov2SeparableConvBoxes } from './expectedResults';
describe('tinyYolov2', () => { describe('tinyYolov2', () => {
...@@ -13,121 +12,208 @@ describe('tinyYolov2', () => { ...@@ -13,121 +12,208 @@ describe('tinyYolov2', () => {
imgEl = await faceapi.bufferToImage(img) imgEl = await faceapi.bufferToImage(img)
}) })
describeWithNets('quantized weights', { withTinyYolov2: { quantized: true } }, ({ tinyYolov2 }) => { describe('with separable convolutions', () => {
describeWithNets('quantized weights', { withTinyYolov2: { quantized: true } }, ({ tinyYolov2 }) => {
it('inputSize lg, finds all faces', async () => { it('inputSize lg, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: SizeType.LG }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: SizeType.LG })
const expectedScores = [0.86, 0.86, 0.85, 0.83, 0.81, 0.81] const expectedScores = [0.9, 0.9, 0.89, 0.85, 0.85, 0.85]
const maxBoxDelta = 3 const maxBoxDelta = 1
const boxOrder = [0, 1, 2, 3, 4, 5] const boxOrder = [0, 1, 2, 3, 4, 5]
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
detections.forEach((det, i) => { detections.forEach((det, i) => {
expect(det.getScore()).toBeCloseTo(expectedScores[i], 2) expect(det.getScore()).toBeCloseTo(expectedScores[i], 2)
expectRectClose(det.getBox(), expectedTinyYolov2Boxes[boxOrder[i]], maxBoxDelta) expectRectClose(det.getBox(), expectedTinyYolov2SeparableConvBoxes[boxOrder[i]], maxBoxDelta)
})
}) })
})
it('inputSize md, finds all faces', async () => { it('inputSize md, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: SizeType.MD }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: SizeType.MD })
const expectedScores = [0.89, 0.87, 0.83, 0.82, 0.81, 0.72] const expectedScores = [0.85, 0.85, 0.84, 0.83, 0.8, 0.8]
const maxBoxDelta = 16 const maxBoxDelta = 17
const boxOrder = [5, 4, 0, 2, 1, 3] const boxOrder = [5, 1, 4, 3, 2, 0]
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
detections.forEach((det, i) => { detections.forEach((det, i) => {
expect(det.getScore()).toBeCloseTo(expectedScores[i], 2) expect(det.getScore()).toBeCloseTo(expectedScores[i], 2)
expectRectClose(det.getBox(), expectedTinyYolov2Boxes[boxOrder[i]], maxBoxDelta) expectRectClose(det.getBox(), expectedTinyYolov2SeparableConvBoxes[boxOrder[i]], 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.87, 0.83, 0.82, 0.81, 0.72] const expectedScores = [0.85, 0.85, 0.84, 0.83, 0.8, 0.8]
const maxBoxDelta = 16 const maxBoxDelta = 17
const boxOrder = [5, 4, 0, 2, 1, 3] const boxOrder = [5, 1, 4, 3, 2, 0]
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
detections.forEach((det, i) => { detections.forEach((det, i) => {
expect(det.getScore()).toBeCloseTo(expectedScores[i], 2) expect(det.getScore()).toBeCloseTo(expectedScores[i], 2)
expectRectClose(det.getBox(), expectedTinyYolov2Boxes[boxOrder[i]], maxBoxDelta) expectRectClose(det.getBox(), expectedTinyYolov2SeparableConvBoxes[boxOrder[i]], maxBoxDelta)
})
}) })
}) })
}) })
describeWithNets('uncompressed weights', { withTinyYolov2: { quantized: false } }, ({ tinyYolov2 }) => { describe('without separable convolutions', () => {
describeWithNets('quantized weights', { withTinyYolov2: { quantized: true, withSeparableConv: false } }, ({ tinyYolov2 }) => {
it('inputSize lg, finds all faces', async () => { it('inputSize lg, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: SizeType.LG }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: SizeType.LG })
const expectedScores = [0.86, 0.86, 0.85, 0.83, 0.81, 0.81] const expectedScores = [0.86, 0.86, 0.85, 0.83, 0.81, 0.81]
const maxBoxDelta = 1 const maxBoxDelta = 3
const boxOrder = [0, 1, 2, 3, 4, 5] const boxOrder = [0, 1, 2, 3, 4, 5]
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
detections.forEach((det, i) => { detections.forEach((det, i) => {
expect(det.getScore()).toBeCloseTo(expectedScores[i], 2) expect(det.getScore()).toBeCloseTo(expectedScores[i], 2)
expectRectClose(det.getBox(), expectedTinyYolov2Boxes[boxOrder[i]], maxBoxDelta) expectRectClose(det.getBox(), expectedTinyYolov2Boxes[boxOrder[i]], maxBoxDelta)
})
}) })
})
it('inputSize md, finds all faces', async () => { it('inputSize md, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: SizeType.MD }) const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: SizeType.MD })
const expectedScores = [0.89, 0.87, 0.83, 0.83, 0.81, 0.73] const expectedScores = [0.89, 0.87, 0.83, 0.82, 0.81, 0.72]
const maxBoxDelta = 14 const maxBoxDelta = 16
const boxOrder = [5, 4, 2, 0, 1, 3] const boxOrder = [5, 4, 0, 2, 1, 3]
expect(detections.length).toEqual(6) expect(detections.length).toEqual(6)
detections.forEach((det, i) => { detections.forEach((det, i) => {
expect(det.getScore()).toBeCloseTo(expectedScores[i], 2) expect(det.getScore()).toBeCloseTo(expectedScores[i], 2)
expectRectClose(det.getBox(), expectedTinyYolov2Boxes[boxOrder[i]], maxBoxDelta) expectRectClose(det.getBox(), expectedTinyYolov2Boxes[boxOrder[i]], maxBoxDelta)
})
}) })
it('inputSize custom, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: 416 })
const expectedScores = [0.89, 0.87, 0.83, 0.82, 0.81, 0.72]
const maxBoxDelta = 16
const boxOrder = [5, 4, 0, 2, 1, 3]
expect(detections.length).toEqual(6)
detections.forEach((det, i) => {
expect(det.getScore()).toBeCloseTo(expectedScores[i], 2)
expectRectClose(det.getBox(), expectedTinyYolov2Boxes[boxOrder[i]], maxBoxDelta)
})
})
}) })
it('inputSize custom, finds all faces', async () => { describeWithNets('uncompressed weights', { withTinyYolov2: { quantized: false, withSeparableConv: false } }, ({ tinyYolov2 }) => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: 416 })
const expectedScores = [0.89, 0.87, 0.83, 0.83, 0.81, 0.73] it('inputSize lg, finds all faces', async () => {
const maxBoxDelta = 14 const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: SizeType.LG })
const boxOrder = [5, 4, 2, 0, 1, 3]
expect(detections.length).toEqual(6) const expectedScores = [0.86, 0.86, 0.85, 0.83, 0.81, 0.81]
detections.forEach((det, i) => { const maxBoxDelta = 1
expect(det.getScore()).toBeCloseTo(expectedScores[i], 2) const boxOrder = [0, 1, 2, 3, 4, 5]
expectRectClose(det.getBox(), expectedTinyYolov2Boxes[boxOrder[i]], maxBoxDelta)
expect(detections.length).toEqual(6)
detections.forEach((det, i) => {
expect(det.getScore()).toBeCloseTo(expectedScores[i], 2)
expectRectClose(det.getBox(), expectedTinyYolov2Boxes[boxOrder[i]], maxBoxDelta)
})
}) })
it('inputSize md, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: SizeType.MD })
const expectedScores = [0.89, 0.87, 0.83, 0.83, 0.81, 0.73]
const maxBoxDelta = 14
const boxOrder = [5, 4, 2, 0, 1, 3]
expect(detections.length).toEqual(6)
detections.forEach((det, i) => {
expect(det.getScore()).toBeCloseTo(expectedScores[i], 2)
expectRectClose(det.getBox(), expectedTinyYolov2Boxes[boxOrder[i]], maxBoxDelta)
})
})
it('inputSize custom, finds all faces', async () => {
const detections = await tinyYolov2.locateFaces(imgEl, { inputSize: 416 })
const expectedScores = [0.89, 0.87, 0.83, 0.83, 0.81, 0.73]
const maxBoxDelta = 14
const boxOrder = [5, 4, 2, 0, 1, 3]
expect(detections.length).toEqual(6)
detections.forEach((det, i) => {
expect(det.getScore()).toBeCloseTo(expectedScores[i], 2)
expectRectClose(det.getBox(), expectedTinyYolov2Boxes[boxOrder[i]], maxBoxDelta)
})
})
}) })
}) })
describe('no memory leaks', () => { describe('no memory leaks', () => {
describe('NeuralNetwork, uncompressed model', () => { describe('with separable convolutions', () => {
describe('NeuralNetwork, uncompressed model', () => {
it('disposes all param tensors', async () => {
await expectAllTensorsReleased(async () => {
const res = await fetch('base/weights_uncompressed/tiny_yolov2_separable_conv_model.weights')
const weights = new Float32Array(await res.arrayBuffer())
const net = faceapi.createTinyYolov2(weights)
net.dispose()
})
})
})
describe('NeuralNetwork, quantized model', () => {
it('disposes all param tensors', async () => { it('disposes all param tensors', async () => {
await expectAllTensorsReleased(async () => { await expectAllTensorsReleased(async () => {
const res = await fetch('base/weights_uncompressed/tiny_yolov2_model.weights') const net = new faceapi.TinyYolov2()
const weights = new Float32Array(await res.arrayBuffer()) await net.load('base/weights')
const net = faceapi.createTinyYolov2(weights) net.dispose()
net.dispose() })
}) })
}) })
}) })
describe('NeuralNetwork, quantized model', () => { describe('without separable convolutions', () => {
describe('NeuralNetwork, uncompressed model', () => {
it('disposes all param tensors', async () => { it('disposes all param tensors', async () => {
await expectAllTensorsReleased(async () => { await expectAllTensorsReleased(async () => {
const net = new faceapi.TinyYolov2() const res = await fetch('base/weights_uncompressed/tiny_yolov2_model.weights')
await net.load('base/weights') const weights = new Float32Array(await res.arrayBuffer())
net.dispose() const net = faceapi.createTinyYolov2(weights, false)
net.dispose()
})
}) })
})
describe('NeuralNetwork, quantized model', () => {
it('disposes all param tensors', async () => {
await expectAllTensorsReleased(async () => {
const net = new faceapi.TinyYolov2(false)
await net.load('base/weights')
net.dispose()
})
})
}) })
}) })
......
...@@ -5,8 +5,7 @@ import * as faceapi from '../src/'; ...@@ -5,8 +5,7 @@ import * as faceapi from '../src/';
import { NeuralNetwork } from '../src/commons/NeuralNetwork'; import { NeuralNetwork } from '../src/commons/NeuralNetwork';
import { IPoint } from '../src/'; import { IPoint } from '../src/';
import { allFacesFactory, allFacesMtcnnFactory } from '../src/allFacesFactory'; import { allFacesFactory, allFacesMtcnnFactory } from '../src/allFacesFactory';
import { allFacesMtcnnFunction, allFacesFunction, tinyYolov2 } from '../src/globalApi'; import { allFacesMtcnnFunction, allFacesFunction } from '../src/globalApi';
import { TinyYolov2 } from '../src/tinyYolov2/TinyYolov2';
export function zeros(length: number): Float32Array { export function zeros(length: number): Float32Array {
return new Float32Array(length) return new Float32Array(length)
...@@ -55,6 +54,10 @@ export type WithNetOptions = { ...@@ -55,6 +54,10 @@ export type WithNetOptions = {
quantized?: boolean quantized?: boolean
} }
export type WithTinyYolov2Options = WithNetOptions & {
withSeparableConv?: boolean
}
export type InjectNetArgs = { export type InjectNetArgs = {
allFaces: allFacesFunction allFaces: allFacesFunction
allFacesMtcnn: allFacesMtcnnFunction allFacesMtcnn: allFacesMtcnnFunction
...@@ -73,7 +76,7 @@ export type DescribeWithNetsOptions = { ...@@ -73,7 +76,7 @@ export type DescribeWithNetsOptions = {
withFaceLandmarkNet?: WithNetOptions withFaceLandmarkNet?: WithNetOptions
withFaceRecognitionNet?: WithNetOptions withFaceRecognitionNet?: WithNetOptions
withMtcnn?: WithNetOptions withMtcnn?: WithNetOptions
withTinyYolov2?: WithNetOptions withTinyYolov2?: WithTinyYolov2Options
} }
async function loadNetWeights(uri: string): Promise<Float32Array> { async function loadNetWeights(uri: string): Promise<Float32Array> {
...@@ -102,7 +105,7 @@ export function describeWithNets( ...@@ -102,7 +105,7 @@ export function describeWithNets(
let faceLandmarkNet: faceapi.FaceLandmarkNet = new faceapi.FaceLandmarkNet() let faceLandmarkNet: faceapi.FaceLandmarkNet = new faceapi.FaceLandmarkNet()
let faceRecognitionNet: faceapi.FaceRecognitionNet = new faceapi.FaceRecognitionNet() let faceRecognitionNet: faceapi.FaceRecognitionNet = new faceapi.FaceRecognitionNet()
let mtcnn: faceapi.Mtcnn = new faceapi.Mtcnn() let mtcnn: faceapi.Mtcnn = new faceapi.Mtcnn()
let tinyYolov2: faceapi.TinyYolov2 = new faceapi.TinyYolov2() let tinyYolov2: faceapi.TinyYolov2 = new faceapi.TinyYolov2(options.withTinyYolov2 && options.withTinyYolov2.withSeparableConv)
let allFaces = allFacesFactory(faceDetectionNet, faceLandmarkNet, faceRecognitionNet) let allFaces = allFacesFactory(faceDetectionNet, faceLandmarkNet, faceRecognitionNet)
let allFacesMtcnn = allFacesMtcnnFactory(mtcnn, faceRecognitionNet) let allFacesMtcnn = allFacesMtcnnFactory(mtcnn, faceRecognitionNet)
......
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