Commit 4d3706fd by vincent

retrained landmark 68 and tiny landmark 68 point models

parent 0bfaa037
...@@ -67,6 +67,12 @@ ...@@ -67,6 +67,12 @@
left: 0; left: 0;
} }
.overlay {
position: absolute;
top: 0;
left: 0;
}
#facesContainer canvas { #facesContainer canvas {
margin: 10px; margin: 10px;
} }
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import * as tf from '@tensorflow/tfjs-core';
import { NetInput } from 'tfjs-image-recognition-base'; import { NetInput, normalize } from 'tfjs-image-recognition-base';
import { convLayer, ConvParams } from 'tfjs-tiny-yolov2'; import { ConvParams } from 'tfjs-tiny-yolov2';
import { SeparableConvParams } from 'tfjs-tiny-yolov2/build/tinyYolov2/types';
import { depthwiseSeparableConv } from './depthwiseSeparableConv';
import { extractParams } from './extractParams'; import { extractParams } from './extractParams';
import { FaceLandmark68NetBase } from './FaceLandmark68NetBase'; import { FaceLandmark68NetBase } from './FaceLandmark68NetBase';
import { fullyConnectedLayer } from './fullyConnectedLayer'; import { fullyConnectedLayer } from './fullyConnectedLayer';
import { loadQuantizedParams } from './loadQuantizedParams'; import { loadQuantizedParams } from './loadQuantizedParams';
import { NetParams } from './types'; import { DenseBlock4Params, NetParams } from './types';
function conv(x: tf.Tensor4D, params: ConvParams): tf.Tensor4D { function denseBlock(
return convLayer(x, params, 'valid', true) x: tf.Tensor4D,
} denseBlockParams: DenseBlock4Params,
isFirstLayer: boolean = false
): tf.Tensor4D {
return tf.tidy(() => {
const out1 = tf.relu(
isFirstLayer
? tf.add(
tf.conv2d(x, (denseBlockParams.conv0 as ConvParams).filters, [2, 2], 'same'),
denseBlockParams.conv0.bias
)
: depthwiseSeparableConv(x, denseBlockParams.conv0 as SeparableConvParams, [2, 2])
) as tf.Tensor4D
const out2 = depthwiseSeparableConv(out1, denseBlockParams.conv1, [1, 1])
const in3 = tf.relu(tf.add(out1, out2)) as tf.Tensor4D
const out3 = depthwiseSeparableConv(in3, denseBlockParams.conv2, [1, 1])
const in4 = tf.relu(tf.add(out1, tf.add(out2, out3))) as tf.Tensor4D
const out4 = depthwiseSeparableConv(in4, denseBlockParams.conv3, [1, 1])
function maxPool(x: tf.Tensor4D, strides: [number, number] = [2, 2]): tf.Tensor4D { return tf.relu(tf.add(out1, tf.add(out2, tf.add(out3, out4)))) as tf.Tensor4D
return tf.maxPool(x, [2, 2], strides, 'valid') })
} }
export class FaceLandmark68Net extends FaceLandmark68NetBase<NetParams> { export class FaceLandmark68Net extends FaceLandmark68NetBase<NetParams> {
constructor() { constructor() {
super('FaceLandmark68Net') super('FaceLandmark68LargeNet')
} }
public runNet(input: NetInput): tf.Tensor2D { public runNet(input: NetInput): tf.Tensor2D {
...@@ -27,27 +47,21 @@ export class FaceLandmark68Net extends FaceLandmark68NetBase<NetParams> { ...@@ -27,27 +47,21 @@ export class FaceLandmark68Net extends FaceLandmark68NetBase<NetParams> {
const { params } = this const { params } = this
if (!params) { if (!params) {
throw new Error('FaceLandmark68Net - load model before inference') throw new Error('FaceLandmark68LargeNet - load model before inference')
} }
return tf.tidy(() => { return tf.tidy(() => {
const batchTensor = input.toBatchTensor(128, true).toFloat() as tf.Tensor4D const batchTensor = input.toBatchTensor(112, true)
const meanRgb = [122.782, 117.001, 104.298]
let out = conv(batchTensor, params.conv0) const normalized = normalize(batchTensor, meanRgb).div(tf.scalar(255)) as tf.Tensor4D
out = maxPool(out)
out = conv(out, params.conv1) let out = denseBlock(normalized, params.dense0, true)
out = conv(out, params.conv2) out = denseBlock(out, params.dense1)
out = maxPool(out) out = denseBlock(out, params.dense2)
out = conv(out, params.conv3) out = denseBlock(out, params.dense3)
out = conv(out, params.conv4) out = tf.avgPool(out, [7, 7], [2, 2], 'valid')
out = maxPool(out)
out = conv(out, params.conv5) return fullyConnectedLayer(out.as2D(out.shape[0], -1), params.fc)
out = conv(out, params.conv6)
out = maxPool(out, [1, 1])
out = conv(out, params.conv7)
const fc0 = tf.relu(fullyConnectedLayer(out.as2D(out.shape[0], -1), params.fc0))
return fullyConnectedLayer(fc0, params.fc1)
}) })
} }
...@@ -55,6 +69,7 @@ export class FaceLandmark68Net extends FaceLandmark68NetBase<NetParams> { ...@@ -55,6 +69,7 @@ export class FaceLandmark68Net extends FaceLandmark68NetBase<NetParams> {
return loadQuantizedParams(uri) return loadQuantizedParams(uri)
} }
protected extractParams(weights: Float32Array) { protected extractParams(weights: Float32Array) {
return extractParams(weights) return extractParams(weights)
} }
......
...@@ -8,11 +8,11 @@ import { extractParamsTiny } from './extractParamsTiny'; ...@@ -8,11 +8,11 @@ import { extractParamsTiny } from './extractParamsTiny';
import { FaceLandmark68NetBase } from './FaceLandmark68NetBase'; import { FaceLandmark68NetBase } from './FaceLandmark68NetBase';
import { fullyConnectedLayer } from './fullyConnectedLayer'; import { fullyConnectedLayer } from './fullyConnectedLayer';
import { loadQuantizedParamsTiny } from './loadQuantizedParamsTiny'; import { loadQuantizedParamsTiny } from './loadQuantizedParamsTiny';
import { DenseBlockParams, TinyNetParams } from './types'; import { DenseBlock3Params, TinyNetParams } from './types';
function denseBlock( function denseBlock(
x: tf.Tensor4D, x: tf.Tensor4D,
denseBlockParams: DenseBlockParams, denseBlockParams: DenseBlock3Params,
isFirstLayer: boolean = false isFirstLayer: boolean = false
): tf.Tensor4D { ): tf.Tensor4D {
return tf.tidy(() => { return tf.tidy(() => {
......
import { extractWeightsFactory, ParamMapping } from 'tfjs-image-recognition-base'; import { extractWeightsFactory, ParamMapping } from 'tfjs-image-recognition-base';
import { extractConvParamsFactory, extractFCParamsFactory } from 'tfjs-tiny-yolov2';
import { extractorsFactory } from './extractorsFactory';
import { NetParams } from './types'; import { NetParams } from './types';
export function extractParams(weights: Float32Array): { params: NetParams, paramMappings: ParamMapping[] } { export function extractParams(weights: Float32Array): { params: NetParams, paramMappings: ParamMapping[] } {
...@@ -12,19 +12,16 @@ export function extractParams(weights: Float32Array): { params: NetParams, param ...@@ -12,19 +12,16 @@ export function extractParams(weights: Float32Array): { params: NetParams, param
getRemainingWeights getRemainingWeights
} = extractWeightsFactory(weights) } = extractWeightsFactory(weights)
const extractConvParams = extractConvParamsFactory(extractWeights, paramMappings) const {
const extractFCParams = extractFCParamsFactory(extractWeights, paramMappings) extractDenseBlock4Params,
extractFCParams
} = extractorsFactory(extractWeights, paramMappings)
const conv0 = extractConvParams(3, 32, 3, 'conv0') const dense0 = extractDenseBlock4Params(3, 32, 'dense0', true)
const conv1 = extractConvParams(32, 64, 3, 'conv1') const dense1 = extractDenseBlock4Params(32, 64, 'dense1')
const conv2 = extractConvParams(64, 64, 3, 'conv2') const dense2 = extractDenseBlock4Params(64, 128, 'dense2')
const conv3 = extractConvParams(64, 64, 3, 'conv3') const dense3 = extractDenseBlock4Params(128, 256, 'dense3')
const conv4 = extractConvParams(64, 64, 3, 'conv4') const fc = extractFCParams(256, 136, 'fc')
const conv5 = extractConvParams(64, 128, 3, 'conv5')
const conv6 = extractConvParams(128, 128, 3, 'conv6')
const conv7 = extractConvParams(128, 256, 3, 'conv7')
const fc0 = extractFCParams(6400, 1024, 'fc0')
const fc1 = extractFCParams(1024, 136, 'fc1')
if (getRemainingWeights().length !== 0) { if (getRemainingWeights().length !== 0) {
throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`) throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`)
...@@ -32,17 +29,6 @@ export function extractParams(weights: Float32Array): { params: NetParams, param ...@@ -32,17 +29,6 @@ export function extractParams(weights: Float32Array): { params: NetParams, param
return { return {
paramMappings, paramMappings,
params: { params: { dense0, dense1, dense2, dense3, fc }
conv0,
conv1,
conv2,
conv3,
conv4,
conv5,
conv6,
conv7,
fc0,
fc1
}
} }
} }
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import { extractWeightsFactory, ParamMapping } from 'tfjs-image-recognition-base';
import { extractWeightsFactory, ExtractWeightsFunction, ParamMapping } from 'tfjs-image-recognition-base';
import { extractConvParamsFactory, FCParams } from 'tfjs-tiny-yolov2';
import { SeparableConvParams } from 'tfjs-tiny-yolov2/build/tinyYolov2/types';
import { DenseBlockParams, TinyNetParams } from './types'; import { extractorsFactory } from './extractorsFactory';
import { TinyNetParams } from './types';
function extractorsFactory(extractWeights: ExtractWeightsFunction, paramMappings: ParamMapping[]) {
function extractSeparableConvParams(channelsIn: number, channelsOut: number, mappedPrefix: string): SeparableConvParams {
const depthwise_filter = tf.tensor4d(extractWeights(3 * 3 * channelsIn), [3, 3, channelsIn, 1])
const pointwise_filter = tf.tensor4d(extractWeights(channelsIn * channelsOut), [1, 1, channelsIn, channelsOut])
const bias = tf.tensor1d(extractWeights(channelsOut))
paramMappings.push(
{ paramPath: `${mappedPrefix}/depthwise_filter` },
{ paramPath: `${mappedPrefix}/pointwise_filter` },
{ paramPath: `${mappedPrefix}/bias` }
)
return new SeparableConvParams(
depthwise_filter,
pointwise_filter,
bias
)
}
function extractFCParams(channelsIn: number, channelsOut: number, mappedPrefix: string): FCParams {
const weights = tf.tensor2d(extractWeights(channelsIn * channelsOut), [channelsIn, channelsOut])
const bias = tf.tensor1d(extractWeights(channelsOut))
paramMappings.push(
{ paramPath: `${mappedPrefix}/weights` },
{ paramPath: `${mappedPrefix}/bias` }
)
return {
weights,
bias
}
}
return {
extractSeparableConvParams,
extractFCParams
}
}
export function extractParamsTiny(weights: Float32Array): { params: TinyNetParams, paramMappings: ParamMapping[] } { export function extractParamsTiny(weights: Float32Array): { params: TinyNetParams, paramMappings: ParamMapping[] } {
...@@ -57,26 +13,13 @@ export function extractParamsTiny(weights: Float32Array): { params: TinyNetParam ...@@ -57,26 +13,13 @@ export function extractParamsTiny(weights: Float32Array): { params: TinyNetParam
} = extractWeightsFactory(weights) } = extractWeightsFactory(weights)
const { const {
extractSeparableConvParams, extractDenseBlock3Params,
extractFCParams extractFCParams
} = extractorsFactory(extractWeights, paramMappings) } = extractorsFactory(extractWeights, paramMappings)
const extractConvParams = extractConvParamsFactory(extractWeights, paramMappings) const dense0 = extractDenseBlock3Params(3, 32, 'dense0', true)
const dense1 = extractDenseBlock3Params(32, 64, 'dense1')
function extractDenseBlockParams(channelsIn: number, channelsOut: number, mappedPrefix: string, isFirstLayer: boolean = false): DenseBlockParams { const dense2 = extractDenseBlock3Params(64, 128, 'dense2')
const conv0 = isFirstLayer
? extractConvParams(channelsIn, channelsOut, 3, `${mappedPrefix}/conv0`)
: extractSeparableConvParams(channelsIn, channelsOut, `${mappedPrefix}/conv0`)
const conv1 = extractSeparableConvParams(channelsOut, channelsOut, `${mappedPrefix}/conv1`)
const conv2 = extractSeparableConvParams(channelsOut, channelsOut, `${mappedPrefix}/conv2`)
return { conv0, conv1, conv2 }
}
const dense0 = extractDenseBlockParams(3, 32, 'dense0', true)
const dense1 = extractDenseBlockParams(32, 64, 'dense1')
const dense2 = extractDenseBlockParams(64, 128, 'dense2')
const fc = extractFCParams(128, 136, 'fc') const fc = extractFCParams(128, 136, 'fc')
if (getRemainingWeights().length !== 0) { if (getRemainingWeights().length !== 0) {
......
import * as tf from '@tensorflow/tfjs-core';
import { ExtractWeightsFunction, ParamMapping } from 'tfjs-image-recognition-base';
import { extractConvParamsFactory, FCParams } from 'tfjs-tiny-yolov2';
import { SeparableConvParams } from 'tfjs-tiny-yolov2/build/tinyYolov2/types';
import { DenseBlock3Params, DenseBlock4Params } from './types';
export function extractorsFactory(extractWeights: ExtractWeightsFunction, paramMappings: ParamMapping[]) {
function extractSeparableConvParams(channelsIn: number, channelsOut: number, mappedPrefix: string): SeparableConvParams {
const depthwise_filter = tf.tensor4d(extractWeights(3 * 3 * channelsIn), [3, 3, channelsIn, 1])
const pointwise_filter = tf.tensor4d(extractWeights(channelsIn * channelsOut), [1, 1, channelsIn, channelsOut])
const bias = tf.tensor1d(extractWeights(channelsOut))
paramMappings.push(
{ paramPath: `${mappedPrefix}/depthwise_filter` },
{ paramPath: `${mappedPrefix}/pointwise_filter` },
{ paramPath: `${mappedPrefix}/bias` }
)
return new SeparableConvParams(
depthwise_filter,
pointwise_filter,
bias
)
}
function extractFCParams(channelsIn: number, channelsOut: number, mappedPrefix: string): FCParams {
const weights = tf.tensor2d(extractWeights(channelsIn * channelsOut), [channelsIn, channelsOut])
const bias = tf.tensor1d(extractWeights(channelsOut))
paramMappings.push(
{ paramPath: `${mappedPrefix}/weights` },
{ paramPath: `${mappedPrefix}/bias` }
)
return {
weights,
bias
}
}
const extractConvParams = extractConvParamsFactory(extractWeights, paramMappings)
function extractDenseBlock3Params(channelsIn: number, channelsOut: number, mappedPrefix: string, isFirstLayer: boolean = false): DenseBlock3Params {
const conv0 = isFirstLayer
? extractConvParams(channelsIn, channelsOut, 3, `${mappedPrefix}/conv0`)
: extractSeparableConvParams(channelsIn, channelsOut, `${mappedPrefix}/conv0`)
const conv1 = extractSeparableConvParams(channelsOut, channelsOut, `${mappedPrefix}/conv1`)
const conv2 = extractSeparableConvParams(channelsOut, channelsOut, `${mappedPrefix}/conv2`)
return { conv0, conv1, conv2 }
}
function extractDenseBlock4Params(channelsIn: number, channelsOut: number, mappedPrefix: string, isFirstLayer: boolean = false): DenseBlock4Params {
const { conv0, conv1, conv2 } = extractDenseBlock3Params(channelsIn, channelsOut, mappedPrefix, isFirstLayer)
const conv3 = extractSeparableConvParams(channelsOut, channelsOut, `${mappedPrefix}/conv3`)
return { conv0, conv1, conv2, conv3 }
}
return {
extractDenseBlock3Params,
extractDenseBlock4Params,
extractFCParams
}
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { extractWeightEntryFactory, ParamMapping } from 'tfjs-image-recognition-base';
import { ConvParams, FCParams } from 'tfjs-tiny-yolov2';
import { SeparableConvParams } from 'tfjs-tiny-yolov2/build/tinyYolov2/types';
import { DenseBlock3Params, DenseBlock4Params } from './types';
export function loadParamsFactory(weightMap: any, paramMappings: ParamMapping[]) {
const extractWeightEntry = extractWeightEntryFactory(weightMap, paramMappings)
function extractConvParams(prefix: string): ConvParams {
const filters = extractWeightEntry<tf.Tensor4D>(`${prefix}/filters`, 4)
const bias = extractWeightEntry<tf.Tensor1D>(`${prefix}/bias`, 1)
return { filters, bias }
}
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
)
}
function extractDenseBlock3Params(prefix: string, isFirstLayer: boolean = false): DenseBlock3Params {
const conv0 = isFirstLayer
? extractConvParams(`${prefix}/conv0`)
: extractSeparableConvParams(`${prefix}/conv0`)
const conv1 = extractSeparableConvParams(`${prefix}/conv1`)
const conv2 = extractSeparableConvParams(`${prefix}/conv2`)
return { conv0, conv1, conv2 }
}
function extractDenseBlock4Params(prefix: string, isFirstLayer: boolean = false): DenseBlock4Params {
const conv0 = isFirstLayer
? extractConvParams(`${prefix}/conv0`)
: extractSeparableConvParams(`${prefix}/conv0`)
const conv1 = extractSeparableConvParams(`${prefix}/conv1`)
const conv2 = extractSeparableConvParams(`${prefix}/conv2`)
const conv3 = extractSeparableConvParams(`${prefix}/conv3`)
return { conv0, conv1, conv2, conv3 }
}
function extractFcParams(prefix: string): FCParams {
const weights = extractWeightEntry<tf.Tensor2D>(`${prefix}/weights`, 2)
const bias = extractWeightEntry<tf.Tensor1D>(`${prefix}/bias`, 1)
return { weights, bias }
}
return {
extractDenseBlock3Params,
extractDenseBlock4Params,
extractFcParams
}
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core'; import { disposeUnusedWeightTensors, loadWeightMap, ParamMapping } from 'tfjs-image-recognition-base';
import {
disposeUnusedWeightTensors,
extractWeightEntryFactory,
loadWeightMap,
ParamMapping,
} from 'tfjs-image-recognition-base';
import { ConvParams, FCParams } from 'tfjs-tiny-yolov2';
import { loadParamsFactory } from './loadParamsFactory';
import { NetParams } from './types'; import { NetParams } from './types';
const DEFAULT_MODEL_NAME = 'face_landmark_68_model' const DEFAULT_MODEL_NAME = 'face_landmark_68_model'
function extractorsFactory(weightMap: any, paramMappings: ParamMapping[]) {
const extractWeightEntry = extractWeightEntryFactory(weightMap, paramMappings)
function extractConvParams(prefix: string, mappedPrefix: string): ConvParams {
const filters = extractWeightEntry<tf.Tensor4D>(`${prefix}/kernel`, 4, `${mappedPrefix}/filters`)
const bias = extractWeightEntry<tf.Tensor1D>(`${prefix}/bias`, 1, `${mappedPrefix}/bias`)
return { filters, bias }
}
function extractFcParams(prefix: string, mappedPrefix: string): FCParams {
const weights = extractWeightEntry<tf.Tensor2D>(`${prefix}/kernel`, 2, `${mappedPrefix}/weights`)
const bias = extractWeightEntry<tf.Tensor1D>(`${prefix}/bias`, 1, `${mappedPrefix}/bias`)
return { weights, bias }
}
return {
extractConvParams,
extractFcParams
}
}
export async function loadQuantizedParams( export async function loadQuantizedParams(
uri: string | undefined uri: string | undefined
): Promise<{ params: NetParams, paramMappings: ParamMapping[] }> { ): Promise<{ params: NetParams, paramMappings: ParamMapping[] }> {
...@@ -43,21 +13,16 @@ export async function loadQuantizedParams( ...@@ -43,21 +13,16 @@ export async function loadQuantizedParams(
const paramMappings: ParamMapping[] = [] const paramMappings: ParamMapping[] = []
const { const {
extractConvParams, extractDenseBlock4Params,
extractFcParams extractFcParams
} = extractorsFactory(weightMap, paramMappings) } = loadParamsFactory(weightMap, paramMappings)
const params = { const params = {
conv0: extractConvParams('conv2d_0', 'conv0'), dense0: extractDenseBlock4Params('dense0', true),
conv1: extractConvParams('conv2d_1', 'conv1'), dense1: extractDenseBlock4Params('dense1'),
conv2: extractConvParams('conv2d_2', 'conv2'), dense2: extractDenseBlock4Params('dense2'),
conv3: extractConvParams('conv2d_3', 'conv3'), dense3: extractDenseBlock4Params('dense3'),
conv4: extractConvParams('conv2d_4', 'conv4'), fc: extractFcParams('fc')
conv5: extractConvParams('conv2d_5', 'conv5'),
conv6: extractConvParams('conv2d_6', 'conv6'),
conv7: extractConvParams('conv2d_7', 'conv7'),
fc0: extractFcParams('dense', 'fc0'),
fc1: extractFcParams('logits', 'fc1')
} }
disposeUnusedWeightTensors(weightMap, paramMappings) disposeUnusedWeightTensors(weightMap, paramMappings)
......
import * as tf from '@tensorflow/tfjs-core'; import { disposeUnusedWeightTensors, loadWeightMap, ParamMapping } from 'tfjs-image-recognition-base';
import {
disposeUnusedWeightTensors,
extractWeightEntryFactory,
loadWeightMap,
ParamMapping,
} from 'tfjs-image-recognition-base';
import { ConvParams, FCParams } from 'tfjs-tiny-yolov2';
import { SeparableConvParams } from 'tfjs-tiny-yolov2/build/tinyYolov2/types';
import { DenseBlockParams, TinyNetParams } from './types'; import { loadParamsFactory } from './loadParamsFactory';
import { TinyNetParams } from './types';
const DEFAULT_MODEL_NAME = 'face_landmark_68_tiny_model' const DEFAULT_MODEL_NAME = 'face_landmark_68_tiny_model'
function extractorsFactory(weightMap: any, paramMappings: ParamMapping[]) {
const extractWeightEntry = extractWeightEntryFactory(weightMap, paramMappings)
function extractConvParams(prefix: string): ConvParams {
const filters = extractWeightEntry<tf.Tensor4D>(`${prefix}/filters`, 4)
const bias = extractWeightEntry<tf.Tensor1D>(`${prefix}/bias`, 1)
return { filters, bias }
}
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
)
}
function extractDenseBlockParams(prefix: string, isFirstLayer: boolean = false): DenseBlockParams {
const conv0 = isFirstLayer
? extractConvParams(`${prefix}/conv0`)
: extractSeparableConvParams(`${prefix}/conv0`)
const conv1 = extractSeparableConvParams(`${prefix}/conv1`)
const conv2 = extractSeparableConvParams(`${prefix}/conv2`)
return { conv0, conv1, conv2 }
}
function extractFcParams(prefix: string): FCParams {
const weights = extractWeightEntry<tf.Tensor2D>(`${prefix}/weights`, 2)
const bias = extractWeightEntry<tf.Tensor1D>(`${prefix}/bias`, 1)
return { weights, bias }
}
return {
extractDenseBlockParams,
extractFcParams
}
}
export async function loadQuantizedParamsTiny( export async function loadQuantizedParamsTiny(
uri: string | undefined uri: string | undefined
): Promise<{ params: TinyNetParams, paramMappings: ParamMapping[] }> { ): Promise<{ params: TinyNetParams, paramMappings: ParamMapping[] }> {
...@@ -66,14 +13,14 @@ export async function loadQuantizedParamsTiny( ...@@ -66,14 +13,14 @@ export async function loadQuantizedParamsTiny(
const paramMappings: ParamMapping[] = [] const paramMappings: ParamMapping[] = []
const { const {
extractDenseBlockParams, extractDenseBlock3Params,
extractFcParams extractFcParams
} = extractorsFactory(weightMap, paramMappings) } = loadParamsFactory(weightMap, paramMappings)
const params = { const params = {
dense0: extractDenseBlockParams('dense0', true), dense0: extractDenseBlock3Params('dense0', true),
dense1: extractDenseBlockParams('dense1'), dense1: extractDenseBlock3Params('dense1'),
dense2: extractDenseBlockParams('dense2'), dense2: extractDenseBlock3Params('dense2'),
fc: extractFcParams('fc') fc: extractFcParams('fc')
} }
......
...@@ -2,19 +2,6 @@ import * as tf from '@tensorflow/tfjs-core'; ...@@ -2,19 +2,6 @@ import * as tf from '@tensorflow/tfjs-core';
import { ConvParams, FCParams } from 'tfjs-tiny-yolov2'; import { ConvParams, FCParams } from 'tfjs-tiny-yolov2';
import { SeparableConvParams } from 'tfjs-tiny-yolov2/build/tinyYolov2/types'; import { SeparableConvParams } from 'tfjs-tiny-yolov2/build/tinyYolov2/types';
export type NetParams = {
conv0: ConvParams
conv1: ConvParams
conv2: ConvParams
conv3: ConvParams
conv4: ConvParams
conv5: ConvParams
conv6: ConvParams
conv7: ConvParams
fc0: FCParams
fc1: FCParams
}
export type ConvWithBatchNormParams = BatchNormParams & { export type ConvWithBatchNormParams = BatchNormParams & {
filter: tf.Tensor4D filter: tf.Tensor4D
} }
...@@ -35,27 +22,28 @@ export declare type FCWithBatchNormParams = BatchNormParams & { ...@@ -35,27 +22,28 @@ export declare type FCWithBatchNormParams = BatchNormParams & {
weights: tf.Tensor2D weights: tf.Tensor2D
} }
export type DenseBlockParams = { export type DenseBlock3Params = {
conv0: SeparableConvParams | ConvParams conv0: SeparableConvParams | ConvParams
conv1: SeparableConvParams conv1: SeparableConvParams
conv2: SeparableConvParams conv2: SeparableConvParams
//conv3: SeparableConvParams }
export type DenseBlock4Params = DenseBlock3Params & {
conv3: SeparableConvParams
} }
export type TinyNetParams = { export type TinyNetParams = {
dense0: DenseBlockParams dense0: DenseBlock3Params
dense1: DenseBlockParams dense1: DenseBlock3Params
dense2: DenseBlockParams dense2: DenseBlock3Params
fc: FCParams fc: FCParams
} }
export type MobileResnetParams = { export type NetParams = {
conv0: SeparableConvParams dense0: DenseBlock4Params
conv1: SeparableConvParams dense1: DenseBlock4Params
conv2: SeparableConvParams dense2: DenseBlock4Params
conv3: SeparableConvParams dense3: DenseBlock4Params
conv4: SeparableConvParams
conv5: SeparableConvParams
fc: FCParams fc: FCParams
} }
...@@ -8,6 +8,7 @@ import { FaceLandmarks68 } from './classes/FaceLandmarks68'; ...@@ -8,6 +8,7 @@ import { FaceLandmarks68 } from './classes/FaceLandmarks68';
import { FullFaceDescription } from './classes/FullFaceDescription'; import { FullFaceDescription } from './classes/FullFaceDescription';
import { FaceDetectionNet } from './faceDetectionNet/FaceDetectionNet'; import { FaceDetectionNet } from './faceDetectionNet/FaceDetectionNet';
import { FaceLandmark68Net } from './faceLandmarkNet/FaceLandmark68Net'; import { FaceLandmark68Net } from './faceLandmarkNet/FaceLandmark68Net';
import { FaceLandmark68TinyNet } from './faceLandmarkNet/FaceLandmark68TinyNet';
import { FaceRecognitionNet } from './faceRecognitionNet/FaceRecognitionNet'; import { FaceRecognitionNet } from './faceRecognitionNet/FaceRecognitionNet';
import { Mtcnn } from './mtcnn/Mtcnn'; import { Mtcnn } from './mtcnn/Mtcnn';
import { MtcnnForwardParams, MtcnnResult } from './mtcnn/types'; import { MtcnnForwardParams, MtcnnResult } from './mtcnn/types';
...@@ -22,6 +23,7 @@ export const recognitionNet = new FaceRecognitionNet() ...@@ -22,6 +23,7 @@ export const recognitionNet = new FaceRecognitionNet()
export const nets = { export const nets = {
ssdMobilenetv1: detectionNet, ssdMobilenetv1: detectionNet,
faceLandmark68Net: landmarkNet, faceLandmark68Net: landmarkNet,
faceLandmark68TinyNet: new FaceLandmark68TinyNet(),
faceRecognitionNet: recognitionNet, faceRecognitionNet: recognitionNet,
mtcnn: new Mtcnn(), mtcnn: new Mtcnn(),
tinyYolov2: new TinyYolov2() tinyYolov2: new TinyYolov2()
...@@ -35,6 +37,10 @@ export function loadFaceLandmarkModel(url: string) { ...@@ -35,6 +37,10 @@ export function loadFaceLandmarkModel(url: string) {
return nets.faceLandmark68Net.load(url) return nets.faceLandmark68Net.load(url)
} }
export function loadFaceLandmarkTinyModel(url: string) {
return nets.faceLandmark68TinyNet.load(url)
}
export function loadFaceRecognitionModel(url: string) { export function loadFaceRecognitionModel(url: string) {
return nets.faceRecognitionNet.load(url) return nets.faceRecognitionNet.load(url)
} }
...@@ -52,6 +58,7 @@ export function loadFaceDetectionModel(url: string) { ...@@ -52,6 +58,7 @@ export function loadFaceDetectionModel(url: string) {
} }
export function loadModels(url: string) { export function loadModels(url: string) {
console.warn('loadModels will be deprecated in future')
return Promise.all([ return Promise.all([
loadSsdMobilenetv1Model(url), loadSsdMobilenetv1Model(url),
loadFaceLandmarkModel(url), loadFaceLandmarkModel(url),
...@@ -76,6 +83,11 @@ export function detectLandmarks( ...@@ -76,6 +83,11 @@ export function detectLandmarks(
): Promise<FaceLandmarks68 | FaceLandmarks68[]> { ): Promise<FaceLandmarks68 | FaceLandmarks68[]> {
return nets.faceLandmark68Net.detectLandmarks(input) return nets.faceLandmark68Net.detectLandmarks(input)
} }
export function detectLandmarksTiny(
input: TNetInput
): Promise<FaceLandmarks68 | FaceLandmarks68[]> {
return nets.faceLandmark68TinyNet.detectLandmarks(input)
}
export function computeFaceDescriptor( export function computeFaceDescriptor(
input: TNetInput input: TNetInput
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
<html> <html>
<head> <head>
<script src="face-api.js"></script> <script src="face-api.js"></script>
<script src="commons.js"></script>
<script src="FileSaver.js"></script> <script src="FileSaver.js"></script>
<script src="quantization.js"></script> <script src="quantization.js"></script>
</head> </head>
...@@ -10,14 +9,20 @@ ...@@ -10,14 +9,20 @@
<script> <script>
tf = faceapi.tf tf = faceapi.tf
const modelName = 'face_landmark_68_tiny_model' const uncompressedWeightsUri = `face_landmark_68_model.weights`
const uncompressedWeightsUri = `face_landmark_68_tiny_model.weights` const net = new faceapi.FaceLandmark68LargeNet()
const net = new faceapi.FaceLandmark68TinyNet()
async function loadNetWeights(uri) { async function load() {
return new Float32Array(await (await fetch(uri)).arrayBuffer()) await net.load(new Float32Array(await (await fetch(uncompressedWeightsUri)).arrayBuffer()))
console.log('net loaded')
} }
function getNamedTensors() {
return net.getParamList().map(({ path, tensor }) => ({ name: path, tensor }))
}
const modelName = 'face_landmark_68'
function makeShards(weightArray) { function makeShards(weightArray) {
const maxLength = 4096 * 1024 const maxLength = 4096 * 1024
...@@ -41,25 +46,34 @@ ...@@ -41,25 +46,34 @@
async function quantizeAndSave() { async function quantizeAndSave() {
await net.load(await loadNetWeights(uncompressedWeightsUri))
const quantizedTensorArrays = [] const quantizedTensorArrays = []
const weightEntries = [] const weightEntries = []
net.getParamList().forEach(({ path, tensor }) => { getNamedTensors().forEach(({ name, tensor, isSkipQuantization }) => {
const { scale, min, qdata } = quantizeWeights(tensor)
const weightEntry = { const weightEntry = {
name : path, name,
shape: tensor.shape, shape: tensor.shape,
dtype: tensor.dtype, dtype: tensor.dtype
quantization: { dtype: 'uint8', scale, min }
} }
console.log({ scale, min }) if (isSkipQuantization) {
quantizedTensorArrays.push(tensor.dataSync())
weightEntries.push(weightEntry)
return
}
const { scale, min, qdata } = quantizeWeights(tensor)
console.log(name, { scale, min })
const quantizedWeightEntry = {
...weightEntry,
quantization: { dtype: 'uint8', scale, min }
}
quantizedTensorArrays.push(qdata) quantizedTensorArrays.push(qdata)
weightEntries.push(weightEntry) weightEntries.push(quantizedWeightEntry)
}) })
const quantizedWeights = quantizedTensorArrays const quantizedWeights = quantizedTensorArrays
...@@ -83,6 +97,9 @@ ...@@ -83,6 +97,9 @@
saveAs(new Blob([JSON.stringify(weightManifest)]), `${modelName}_model-weights_manifest.json`) saveAs(new Blob([JSON.stringify(weightManifest)]), `${modelName}_model-weights_manifest.json`)
} }
load()
</script> </script>
</body> </body>
</html> </html>
\ No newline at end of file
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
initSeparableConvWeights(128, 128), initSeparableConvWeights(128, 128),
initSeparableConvWeights(128, 128), initSeparableConvWeights(128, 128),
initSeparableConvWeights(128, 128), initSeparableConvWeights(128, 128),
initSeparableConvWeights(256, 256), initSeparableConvWeights(128, 256),
initSeparableConvWeights(256, 256), initSeparableConvWeights(256, 256),
initSeparableConvWeights(256, 256), initSeparableConvWeights(256, 256),
initSeparableConvWeights(256, 256) initSeparableConvWeights(256, 256)
......
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
</div> </div>
<script> <script>
const net = new faceapi.FaceLandmark68TinyNet() const net = new faceapi.FaceLandmark68LargeNet()
const modelCheckpoint = 'tmp/densenet3_conv0/checkpoints/landmarks_epoch59.weights' const modelCheckpoint = 'tmp/densenet4/checkpoints/landmarks_epoch46_lr00001_12_lr000001_18.weights'
const crops = 4 const crops = 4
async function loadNetWeights(uri) { async function loadNetWeights(uri) {
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
} }
async function load() { async function load() {
await net.load('./') //await net.load('./')
//const weights = await loadNetWeights(modelCheckpoint) const weights = await loadNetWeights(modelCheckpoint)
//await net.load(weights) await net.load(weights)
console.log('model loaded') console.log('model loaded')
} }
......
...@@ -16,10 +16,10 @@ ...@@ -16,10 +16,10 @@
// uri to weights file of last checkpoint // uri to weights file of last checkpoint
window.net = new faceapi.FaceLandmark68TinyNet() window.net = new faceapi.FaceLandmark68TinyNet()
const modelCheckpoint = '/tmp/initial_glorot.weights.weights' const modelCheckpoint = 'tmp/face_landmark_68_tiny_model_lr00001_19.weights'
const startEpoch = 0 const startEpoch = 20
const learningRate = 0.001 // 0.001 const learningRate = 0.0001 // 0.001
window.optimizer = tf.train.adam(learningRate, 0.9, 0.999, 1e-8) window.optimizer = tf.train.adam(learningRate, 0.9, 0.999, 1e-8)
window.saveEveryNthSample = Infinity window.saveEveryNthSample = Infinity
...@@ -60,10 +60,10 @@ ...@@ -60,10 +60,10 @@
} }
async function onEpochDone(epoch) { async function onEpochDone(epoch) {
saveWeights(window.net, `landmarks_epoch59_sideways71_epoch8_sideways35_epoch${epoch}.weights`) saveWeights(window.net, `face_landmark_68_tiny_model_lr00001_${epoch}.weights`)
const loss = window.lossValues[epoch] const loss = window.lossValues[epoch]
saveAs(new Blob([JSON.stringify({ loss, avgLoss: loss / window.trainIds.length })]), `landmarks_epoch59_sideways71_epoch8_sideways35_epoch${epoch}.json`) saveAs(new Blob([JSON.stringify({ loss, avgLoss: loss / window.trainIds.length })]), `face_landmark_68_tiny_model_lr00001_${epoch}.json`)
} }
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
tf = faceapi.tf tf = faceapi.tf
// uri to weights file of last checkpoint // uri to weights file of last checkpoint
window.net = new faceapi.FaceLandmark68TinyNet() window.net = new faceapi.FaceLandmark68LargeNet()
const modelCheckpoint = '/tmp/initial_glorot.weights' const modelCheckpoint = '/tmp/initial_glorot.weights'
const startEpoch = 0 const startEpoch = 0
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
window.withRandomCrop = false window.withRandomCrop = false
window.batchSize = 18 window.batchSize = 12
window.lossValue = 0 window.lossValue = 0
......
...@@ -38,7 +38,9 @@ ...@@ -38,7 +38,9 @@
<script> <script>
const modelCheckpoints = [ const modelCheckpoints = [
//'tmp/densenet3_conv0/checkpoints/landmarks_epoch59.weights' 'tmp/face_landmark_68_tiny_model_lr00001_0.weights',
'tmp/face_landmark_68_tiny_model_lr00001_13.weights',
'tmp/face_landmark_68_tiny_model_lr00001_24.weights'
] ]
let originalImage = null let originalImage = null
...@@ -131,17 +133,17 @@ ...@@ -131,17 +133,17 @@
async function run() { async function run() {
$('#imgByNr').keydown(onKeyDown) $('#imgByNr').keydown(onKeyDown)
faceapi.loadFaceLandmarkModel('./') //faceapi.loadFaceLandmarkModel('./')
//window.trainIds = (await fetch('/face_landmarks_train_ids').then(res => res.json())) //window.trainIds = (await fetch('/face_landmarks_train_ids').then(res => res.json()))
//window.testIds = (await fetch('/face_landmarks_test_ids').then(res => res.json())) //window.testIds = (await fetch('/face_landmarks_test_ids').then(res => res.json()))
window.testIds = (await fetch('/strong_sideways_test').then(res => res.json())) window.testIds = (await fetch('/strong_sideways_test').then(res => res.json()))
window.nets = [] window.nets = []
window.nets.push(faceapi) //window.nets.push(faceapi)
const net = new faceapi.FaceLandmark68TinyNet() //const net = new faceapi.FaceLandmark68TinyNet()
await net.load('./') //await net.load('./')
window.nets.push(net) //window.nets.push(net)
modelCheckpoints.forEach(async checkpoint => { modelCheckpoints.forEach(async checkpoint => {
const net = new faceapi.FaceLandmark68TinyNet() const net = new faceapi.FaceLandmark68TinyNet()
const weights = await loadNetWeights(checkpoint) const weights = await loadNetWeights(checkpoint)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
[{"weights": [{"name": "unused_Reshape/shape", "dtype": "int32", "shape": [4], "quantization": {"dtype": "uint8", "scale": 0.5058823529411764, "min": -1.011764705882353}}, {"name": "conv2d_0/kernel", "dtype": "float32", "shape": [3, 3, 3, 32], "quantization": {"dtype": "uint8", "scale": 0.006229220535240922, "min": -1.0963428142024023}}, {"name": "conv2d_0/bias", "dtype": "float32", "shape": [32], "quantization": {"dtype": "uint8", "scale": 0.009229176067838482, "min": -2.0211895588566273}}, {"name": "conv2d_1/kernel", "dtype": "float32", "shape": [3, 3, 32, 64], "quantization": {"dtype": "uint8", "scale": 0.00794055274888581, "min": -1.1513801485884423}}, {"name": "conv2d_1/bias", "dtype": "float32", "shape": [64], "quantization": {"dtype": "uint8", "scale": 0.004187015750828911, "min": -0.9839487014447941}}, {"name": "conv2d_2/kernel", "dtype": "float32", "shape": [3, 3, 64, 64], "quantization": {"dtype": "uint8", "scale": 0.013999465633841121, "min": -2.6318995391621307}}, {"name": "conv2d_2/bias", "dtype": "float32", "shape": [64], "quantization": {"dtype": "uint8", "scale": 0.0037124345699946085, "min": -0.8427226473887761}}, {"name": "conv2d_3/kernel", "dtype": "float32", "shape": [3, 3, 64, 64], "quantization": {"dtype": "uint8", "scale": 0.008715396301419128, "min": -1.368317219322803}}, {"name": "conv2d_3/bias", "dtype": "float32", "shape": [64], "quantization": {"dtype": "uint8", "scale": 0.0022804437753032236, "min": -0.5290629558703479}}, {"name": "conv2d_4/kernel", "dtype": "float32", "shape": [3, 3, 64, 64], "quantization": {"dtype": "uint8", "scale": 0.011885881891437605, "min": -2.2226599136988323}}, {"name": "conv2d_4/bias", "dtype": "float32", "shape": [64], "quantization": {"dtype": "uint8", "scale": 0.0020124191893082038, "min": -0.4809681862446607}}, {"name": "conv2d_5/kernel", "dtype": "float32", "shape": [3, 3, 64, 128], "quantization": {"dtype": "uint8", "scale": 0.011104925941018497, "min": -1.8212078543270336}}, {"name": "conv2d_5/bias", "dtype": "float32", "shape": [128], "quantization": {"dtype": "uint8", "scale": 0.0011017150592570212, "min": -0.24017388291803063}}, {"name": "conv2d_6/kernel", "dtype": "float32", "shape": [3, 3, 128, 128], "quantization": {"dtype": "uint8", "scale": 0.012181366191190831, "min": -2.009925421546487}}, {"name": "conv2d_6/bias", "dtype": "float32", "shape": [128], "quantization": {"dtype": "uint8", "scale": 0.0015788526511659809, "min": -0.3347167620471879}}, {"name": "conv2d_7/kernel", "dtype": "float32", "shape": [3, 3, 128, 256], "quantization": {"dtype": "uint8", "scale": 0.013691982100991642, "min": -2.3550209213705626}}, {"name": "conv2d_7/bias", "dtype": "float32", "shape": [256], "quantization": {"dtype": "uint8", "scale": 0.0009620819898212657, "min": -0.1452743804630111}}, {"name": "unused_flatten/Reshape/shape", "dtype": "int32", "shape": [2], "quantization": {"dtype": "uint8", "scale": 0.00784313725490196, "min": -1.003921568627451}}, {"name": "dense/kernel", "dtype": "float32", "shape": [6400, 1024], "quantization": {"dtype": "uint8", "scale": 0.01880466704275094, "min": -3.2720120654386635}}, {"name": "dense/bias", "dtype": "float32", "shape": [1024], "quantization": {"dtype": "uint8", "scale": 0.00283245981908312, "min": -0.24642400426023145}}, {"name": "logits/kernel", "dtype": "float32", "shape": [1024, 136], "quantization": {"dtype": "uint8", "scale": 0.005545294986051672, "min": -0.7818865930332858}}, {"name": "logits/bias", "dtype": "float32", "shape": [136], "quantization": {"dtype": "uint8", "scale": 0.002829533581640206, "min": 0.13660642504692078}}], "paths": ["face_landmark_68_model-shard1", "face_landmark_68_model-shard2"]}] [{"weights":[{"name":"dense0/conv0/filters","shape":[3,3,3,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004853619781194949,"min":-0.5872879935245888}},{"name":"dense0/conv0/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004396426443960153,"min":-0.7298067896973853}},{"name":"dense0/conv1/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00635151559231328,"min":-0.5589333721235686}},{"name":"dense0/conv1/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009354315552057004,"min":-1.2628325995276957}},{"name":"dense0/conv1/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0029380727048013726,"min":-0.5846764682554731}},{"name":"dense0/conv2/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0049374802439820535,"min":-0.6171850304977566}},{"name":"dense0/conv2/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009941946758943446,"min":-1.3421628124573652}},{"name":"dense0/conv2/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0030300481062309416,"min":-0.5272283704841838}},{"name":"dense0/conv3/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005672684837790097,"min":-0.7431217137505026}},{"name":"dense0/conv3/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010712201455060173,"min":-1.5639814124387852}},{"name":"dense0/conv3/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0030966934035806097,"min":-0.3839899820439956}},{"name":"dense1/conv0/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0039155554537679636,"min":-0.48161332081345953}},{"name":"dense1/conv0/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01023082966898002,"min":-1.094698774580862}},{"name":"dense1/conv0/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0027264176630506327,"min":-0.3871513081531898}},{"name":"dense1/conv1/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004583378632863362,"min":-0.5454220573107401}},{"name":"dense1/conv1/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00915846403907327,"min":-1.117332612766939}},{"name":"dense1/conv1/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003091680419211294,"min":-0.5966943209077797}},{"name":"dense1/conv2/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005407439727409214,"min":-0.708374604290607}},{"name":"dense1/conv2/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00946493943532308,"min":-1.2399070660273235}},{"name":"dense1/conv2/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004409168514550901,"min":-0.9788354102303}},{"name":"dense1/conv3/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004478132958505668,"min":-0.6493292789833219}},{"name":"dense1/conv3/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.011063695888893277,"min":-1.2501976354449402}},{"name":"dense1/conv3/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003909627596537272,"min":-0.6646366914113363}},{"name":"dense2/conv0/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003213915404151468,"min":-0.3374611174359041}},{"name":"dense2/conv0/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010917326048308728,"min":-1.4520043644250609}},{"name":"dense2/conv0/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002800439152063108,"min":-0.38085972468058266}},{"name":"dense2/conv1/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0050568851770139206,"min":-0.6927932692509071}},{"name":"dense2/conv1/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01074961213504567,"min":-1.3222022926106174}},{"name":"dense2/conv1/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0030654204242369708,"min":-0.5487102559384177}},{"name":"dense2/conv2/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00591809165244009,"min":-0.917304206128214}},{"name":"dense2/conv2/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01092823346455892,"min":-1.366029183069865}},{"name":"dense2/conv2/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002681120470458386,"min":-0.36463238398234055}},{"name":"dense2/conv3/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0048311497650894465,"min":-0.5797379718107336}},{"name":"dense2/conv3/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.011227761062921263,"min":-1.4483811771168429}},{"name":"dense2/conv3/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0034643323982463162,"min":-0.3360402426298927}},{"name":"dense3/conv0/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003394978887894574,"min":-0.49227193874471326}},{"name":"dense3/conv0/pointwise_filter","shape":[1,1,128,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010051267287310432,"min":-1.2765109454884247}},{"name":"dense3/conv0/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003142924752889895,"min":-0.4588670139219247}},{"name":"dense3/conv1/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00448304671867221,"min":-0.5872791201460595}},{"name":"dense3/conv1/pointwise_filter","shape":[1,1,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.016063522357566685,"min":-2.3613377865623026}},{"name":"dense3/conv1/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00287135781026354,"min":-0.47664539650374765}},{"name":"dense3/conv2/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006002906724518421,"min":-0.7923836876364315}},{"name":"dense3/conv2/pointwise_filter","shape":[1,1,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.017087187019048954,"min":-1.6061955797906016}},{"name":"dense3/conv2/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003124481205846749,"min":-0.46242321846531886}},{"name":"dense3/conv3/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006576311588287353,"min":-1.0193282961845398}},{"name":"dense3/conv3/pointwise_filter","shape":[1,1,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015590153955945782,"min":-1.99553970636106}},{"name":"dense3/conv3/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004453541601405424,"min":-0.6546706154065973}},{"name":"fc/weights","shape":[256,136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010417488509533453,"min":-1.500118345372817}},{"name":"fc/bias","shape":[136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0025084222648658005,"min":0.07683877646923065}}],"paths":["face_landmark_68_model-shard1"]}]
\ No newline at end of file \ No newline at end of file
[{"weights":[{"name":"dense0/conv0/filters","shape":[3,3,3,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.007822331026488659,"min":-0.8761010749667297}},{"name":"dense0/conv0/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0061304877786075365,"min":-0.8460073134478401}},{"name":"dense0/conv1/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006931193669637044,"min":-0.928779951731364}},{"name":"dense0/conv1/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01667951135074391,"min":-2.201695498298196}},{"name":"dense0/conv1/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00381035027550716,"min":-0.7658804053769392}},{"name":"dense0/conv2/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006376917455710617,"min":-0.9437837834451713}},{"name":"dense0/conv2/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013428742745343376,"min":-1.2757305608076208}},{"name":"dense0/conv2/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003760007666606529,"min":-0.6091212419902577}},{"name":"dense1/conv0/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003171338637669881,"min":-0.38373197515805557}},{"name":"dense1/conv0/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014757957645491059,"min":-1.8447447056863824}},{"name":"dense1/conv0/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0032720065584369734,"min":-0.369736741103378}},{"name":"dense1/conv1/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006221360318800983,"min":-0.6096933112424963}},{"name":"dense1/conv1/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.011515324723486807,"min":-1.6236607860116399}},{"name":"dense1/conv1/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002638959300284292,"min":-0.316675116034115}},{"name":"dense1/conv2/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005790043110940971,"min":-0.7237553888676214}},{"name":"dense1/conv2/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013147306442260743,"min":-1.6960025310516358}},{"name":"dense1/conv2/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0036364357845455994,"min":-0.5163738814054751}},{"name":"dense2/conv0/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0025823556909374164,"min":-0.3279591727490519}},{"name":"dense2/conv0/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014951597475538066,"min":-1.8689496844422582}},{"name":"dense2/conv0/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0034451217043633556,"min":-0.561554837811227}},{"name":"dense2/conv1/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00580287587408926,"min":-0.7775853671279609}},{"name":"dense2/conv1/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.020558691024780272,"min":-2.2203386306762694}},{"name":"dense2/conv1/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003580525459027758,"min":-0.47262936059166405}},{"name":"dense2/conv2/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.007787894267661899,"min":-0.996850466260723}},{"name":"dense2/conv2/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0294371997608858,"min":-3.6207755705889535}},{"name":"dense2/conv2/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0037439118413364184,"min":-0.40434247886433317}},{"name":"fc/weights","shape":[128,136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013749843485215131,"min":-1.8424790270188276}},{"name":"fc/bias","shape":[136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002984718394045736,"min":0.0885973796248436}}],"paths":["face_landmark_68_tiny_model-shard1"]}] [{"weights":[{"name":"dense0/conv0/filters","shape":[3,3,3,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008194216092427571,"min":-0.9423348506291708}},{"name":"dense0/conv0/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006839508168837603,"min":-0.8412595047670252}},{"name":"dense0/conv1/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009194007106855804,"min":-1.2779669878529567}},{"name":"dense0/conv1/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0036026100317637128,"min":-0.3170296827952067}},{"name":"dense0/conv1/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.000740380117706224,"min":-0.06367269012273527}},{"name":"dense0/conv2/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":1,"min":0}},{"name":"dense0/conv2/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":1,"min":0}},{"name":"dense0/conv2/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0037702228508743585,"min":-0.6220867703942692}},{"name":"dense1/conv0/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0033707996209462483,"min":-0.421349952618281}},{"name":"dense1/conv0/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014611541991140328,"min":-1.8556658328748217}},{"name":"dense1/conv0/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002832523046755323,"min":-0.30307996600281956}},{"name":"dense1/conv1/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006593170586754294,"min":-0.6329443763284123}},{"name":"dense1/conv1/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.012215249211180444,"min":-1.6001976466646382}},{"name":"dense1/conv1/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002384825547536214,"min":-0.3028728445370992}},{"name":"dense1/conv2/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005859645441466687,"min":-0.7617539073906693}},{"name":"dense1/conv2/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013121426806730382,"min":-1.7845140457153321}},{"name":"dense1/conv2/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0032247188044529336,"min":-0.46435950784122243}},{"name":"dense2/conv0/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002659512618008782,"min":-0.32977956463308894}},{"name":"dense2/conv0/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015499923743453681,"min":-1.9839902391620712}},{"name":"dense2/conv0/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0032450980999890497,"min":-0.522460794098237}},{"name":"dense2/conv1/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005911862382701799,"min":-0.792189559282041}},{"name":"dense2/conv1/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.021025861478319356,"min":-2.2077154552235325}},{"name":"dense2/conv1/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00349616945958605,"min":-0.46149436866535865}},{"name":"dense2/conv2/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008104994250278847,"min":-1.013124281284856}},{"name":"dense2/conv2/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.029337059282789044,"min":-3.5791212325002633}},{"name":"dense2/conv2/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0038808938334969913,"min":-0.4230174278511721}},{"name":"fc/weights","shape":[128,136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014016061670639936,"min":-1.8921683255363912}},{"name":"fc/bias","shape":[136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0029505149698724935,"min":0.088760145008564}}],"paths":["face_landmark_68_tiny_model-shard1"]}]
\ No newline at end of file \ No newline at end of file
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