Skip to content

Commit d50c2b1

Browse files
check in age_gender_model + AgeGenderNet loading from weightmap
1 parent 58e1e11 commit d50c2b1

File tree

10 files changed

+92
-35
lines changed

10 files changed

+92
-35
lines changed

examples/examples-browser/views/ageAndGenderRecognition.html

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,11 @@
170170
}
171171

172172
async function run() {
173-
// load face detection and face expression recognition models
173+
// load face detection and age and gender recognition models
174+
// and load face landmark model for face alignment
174175
await changeFaceDetector(SSD_MOBILENETV1)
175176
await faceapi.loadFaceLandmarkModel('/')
176-
177-
// TODO
178-
const weights = await faceapi.fetchNetWeights('tmp/age_gender.weights')
179-
await faceapi.nets.ageGenderNet.load(weights)
177+
await faceapi.nets.ageGenderNet.load('/')
180178

181179
// start processing image
182180
updateResults()

src/ageGenderNet/extractParams.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export function extractParams(weights: Float32Array): { params: NetParams, param
1313

1414
const extractFCParams = TfjsImageRecognitionBase.extractFCParamsFactory(extractWeights, paramMappings)
1515

16-
const age = extractFCParams(512, 1, 'fc_age')
17-
const gender = extractFCParams(512, 2, 'fc_gender')
16+
const age = extractFCParams(512, 1, 'fc/age')
17+
const gender = extractFCParams(512, 2, 'fc/gender')
1818

1919
if (getRemainingWeights().length !== 0) {
2020
throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`)

src/ageGenderNet/extractParamsFromWeigthMap.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ export function extractParamsFromWeigthMap(
1919

2020
const params = {
2121
fc: {
22-
age: extractFcParams('fc_age'),
23-
gender: extractFcParams('fc_gender')
22+
age: extractFcParams('fc/age'),
23+
gender: extractFcParams('fc/gender')
2424
}
2525
}
2626

src/common/loadConvParamsFactory.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as tf from '@tensorflow/tfjs-core';
2+
import { TfjsImageRecognitionBase } from 'tfjs-image-recognition-base';
3+
4+
export function loadConvParamsFactory(extractWeightEntry: <T>(originalPath: string, paramRank: number) => T) {
5+
return function(prefix: string): TfjsImageRecognitionBase.ConvParams {
6+
const filters = extractWeightEntry<tf.Tensor4D>(`${prefix}/filters`, 4)
7+
const bias = extractWeightEntry<tf.Tensor1D>(`${prefix}/bias`, 1)
8+
9+
return { filters, bias }
10+
}
11+
}

src/faceFeatureExtractor/loadParamsFactory.ts

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,14 @@
1-
import * as tf from '@tensorflow/tfjs-core';
21
import { TfjsImageRecognitionBase } from 'tfjs-image-recognition-base';
32

3+
import { loadConvParamsFactory } from '../common/loadConvParamsFactory';
44
import { DenseBlock3Params, DenseBlock4Params } from './types';
55

66
export function loadParamsFactory(weightMap: any, paramMappings: TfjsImageRecognitionBase.ParamMapping[]) {
77

88
const extractWeightEntry = TfjsImageRecognitionBase.extractWeightEntryFactory(weightMap, paramMappings)
99

10-
function extractConvParams(prefix: string): TfjsImageRecognitionBase.ConvParams {
11-
const filters = extractWeightEntry<tf.Tensor4D>(`${prefix}/filters`, 4)
12-
const bias = extractWeightEntry<tf.Tensor1D>(`${prefix}/bias`, 1)
13-
14-
return { filters, bias }
15-
}
16-
17-
function extractSeparableConvParams(prefix: string): TfjsImageRecognitionBase.SeparableConvParams {
18-
const depthwise_filter = extractWeightEntry<tf.Tensor4D>(`${prefix}/depthwise_filter`, 4)
19-
const pointwise_filter = extractWeightEntry<tf.Tensor4D>(`${prefix}/pointwise_filter`, 4)
20-
const bias = extractWeightEntry<tf.Tensor1D>(`${prefix}/bias`, 1)
21-
22-
return new TfjsImageRecognitionBase.SeparableConvParams(
23-
depthwise_filter,
24-
pointwise_filter,
25-
bias
26-
)
27-
}
10+
const extractConvParams = loadConvParamsFactory(extractWeightEntry)
11+
const extractSeparableConvParams = TfjsImageRecognitionBase.loadSeparableConvParamsFactory(extractWeightEntry)
2812

2913
function extractDenseBlock3Params(prefix: string, isFirstLayer: boolean = false): DenseBlock3Params {
3014
const conv0 = isFirstLayer

src/globalApi/nets.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ export const loadFaceLandmarkModel = (url: string) => nets.faceLandmark68Net.loa
137137
export const loadFaceLandmarkTinyModel = (url: string) => nets.faceLandmark68TinyNet.load(url)
138138
export const loadFaceRecognitionModel = (url: string) => nets.faceRecognitionNet.load(url)
139139
export const loadFaceExpressionModel = (url: string) => nets.faceExpressionNet.load(url)
140+
export const loadAgeGenderModel = (url: string) => nets.ageGenderNet.load(url)
140141

141142
// backward compatibility
142143
export const loadFaceDetectionModel = loadSsdMobilenetv1Model

src/xception/TinyXception.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export class TinyXception extends NeuralNetwork<TinyXceptionParams> {
8181
}
8282

8383
protected extractParamsFromWeigthMap(weightMap: tf.NamedTensorMap) {
84-
return extractParamsFromWeigthMap(weightMap)
84+
return extractParamsFromWeigthMap(weightMap, this._numMainBlocks)
8585
}
8686

8787
protected extractParams(weights: Float32Array) {
Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,80 @@
11
import * as tf from '@tensorflow/tfjs-core';
2-
import { TfjsImageRecognitionBase } from 'tfjs-image-recognition-base';
2+
import { TfjsImageRecognitionBase, range } from 'tfjs-image-recognition-base';
33

4-
import { TinyXceptionParams } from './types';
4+
import { loadConvParamsFactory } from '../common/loadConvParamsFactory';
5+
import { MainBlockParams, ReductionBlockParams, TinyXceptionParams } from './types';
6+
7+
function loadParamsFactory(weightMap: any, paramMappings: TfjsImageRecognitionBase.ParamMapping[]) {
8+
9+
const extractWeightEntry = TfjsImageRecognitionBase.extractWeightEntryFactory(weightMap, paramMappings)
10+
11+
const extractConvParams = loadConvParamsFactory(extractWeightEntry)
12+
const extractSeparableConvParams = TfjsImageRecognitionBase.loadSeparableConvParamsFactory(extractWeightEntry)
13+
14+
function extractReductionBlockParams(mappedPrefix: string): ReductionBlockParams {
15+
16+
const separable_conv0 = extractSeparableConvParams(`${mappedPrefix}/separable_conv0`)
17+
const separable_conv1 = extractSeparableConvParams(`${mappedPrefix}/separable_conv1`)
18+
const expansion_conv = extractConvParams(`${mappedPrefix}/expansion_conv`)
19+
20+
return { separable_conv0, separable_conv1, expansion_conv }
21+
}
22+
23+
function extractMainBlockParams(mappedPrefix: string): MainBlockParams {
24+
25+
const separable_conv0 = extractSeparableConvParams(`${mappedPrefix}/separable_conv0`)
26+
const separable_conv1 = extractSeparableConvParams(`${mappedPrefix}/separable_conv1`)
27+
const separable_conv2 = extractSeparableConvParams(`${mappedPrefix}/separable_conv2`)
28+
29+
return { separable_conv0, separable_conv1, separable_conv2 }
30+
}
31+
32+
return {
33+
extractConvParams,
34+
extractSeparableConvParams,
35+
extractReductionBlockParams,
36+
extractMainBlockParams
37+
}
38+
}
539

640
export function extractParamsFromWeigthMap(
7-
weightMap: tf.NamedTensorMap
41+
weightMap: tf.NamedTensorMap,
42+
numMainBlocks: number
843
): { params: TinyXceptionParams, paramMappings: TfjsImageRecognitionBase.ParamMapping[] } {
944

10-
throw "extractParamsFromWeigthMap not implemented";
45+
const paramMappings: TfjsImageRecognitionBase.ParamMapping[] = []
1146

47+
const {
48+
extractConvParams,
49+
extractSeparableConvParams,
50+
extractReductionBlockParams,
51+
extractMainBlockParams
52+
} = loadParamsFactory(weightMap, paramMappings)
1253

13-
const paramMappings: TfjsImageRecognitionBase.ParamMapping[] = []
54+
const entry_flow_conv_in = extractConvParams('entry_flow/conv_in')
55+
const entry_flow_reduction_block_0 = extractReductionBlockParams('entry_flow/reduction_block_0')
56+
const entry_flow_reduction_block_1 = extractReductionBlockParams('entry_flow/reduction_block_1')
57+
58+
const entry_flow = {
59+
conv_in: entry_flow_conv_in,
60+
reduction_block_0: entry_flow_reduction_block_0,
61+
reduction_block_1: entry_flow_reduction_block_1
62+
}
63+
64+
const middle_flow = {}
65+
range(numMainBlocks, 0, 1).forEach((idx) => {
66+
middle_flow[`main_block_${idx}`] = extractMainBlockParams(`middle_flow/main_block_${idx}`)
67+
})
68+
69+
const exit_flow_reduction_block = extractReductionBlockParams('exit_flow/reduction_block')
70+
const exit_flow_separable_conv = extractSeparableConvParams('exit_flow/separable_conv')
71+
72+
const exit_flow = {
73+
reduction_block: exit_flow_reduction_block,
74+
separable_conv: exit_flow_separable_conv
75+
}
1476

1577
TfjsImageRecognitionBase.disposeUnusedWeightTensors(weightMap, paramMappings)
1678

17-
return { params: {} as any, paramMappings }
79+
return { params: { entry_flow, middle_flow, exit_flow }, paramMappings }
1880
}

weights/age_gender_model-shard1

420 KB
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"weights":[{"name":"entry_flow/conv_in/filters","shape":[3,3,3,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005431825039433498,"min":-0.7441600304023892}},{"name":"entry_flow/conv_in/bias","shape":[32],"dtype":"float32"},{"name":"entry_flow/reduction_block_0/separable_conv0/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005691980614381678,"min":-0.6090419257388395}},{"name":"entry_flow/reduction_block_0/separable_conv0/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009089225881239947,"min":-1.1179747833925135}},{"name":"entry_flow/reduction_block_0/separable_conv0/bias","shape":[64],"dtype":"float32"},{"name":"entry_flow/reduction_block_0/separable_conv1/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00683894624897078,"min":-0.8138346036275228}},{"name":"entry_flow/reduction_block_0/separable_conv1/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.011632566358528886,"min":-1.3028474321552352}},{"name":"entry_flow/reduction_block_0/separable_conv1/bias","shape":[64],"dtype":"float32"},{"name":"entry_flow/reduction_block_0/expansion_conv/filters","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010254812240600587,"min":-0.9229331016540528}},{"name":"entry_flow/reduction_block_0/expansion_conv/bias","shape":[64],"dtype":"float32"},{"name":"entry_flow/reduction_block_1/separable_conv0/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0052509616403018725,"min":-0.6406173201168285}},{"name":"entry_flow/reduction_block_1/separable_conv0/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010788509424994973,"min":-1.4564487723743214}},{"name":"entry_flow/reduction_block_1/separable_conv0/bias","shape":[128],"dtype":"float32"},{"name":"entry_flow/reduction_block_1/separable_conv1/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00553213918910307,"min":-0.7025816770160899}},{"name":"entry_flow/reduction_block_1/separable_conv1/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013602388606351965,"min":-1.6186842441558837}},{"name":"entry_flow/reduction_block_1/separable_conv1/bias","shape":[128],"dtype":"float32"},{"name":"entry_flow/reduction_block_1/expansion_conv/filters","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.007571851038465313,"min":-1.158493208885193}},{"name":"entry_flow/reduction_block_1/expansion_conv/bias","shape":[128],"dtype":"float32"},{"name":"middle_flow/main_block_0/separable_conv0/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005766328409606335,"min":-0.6688940955143349}},{"name":"middle_flow/main_block_0/separable_conv0/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.012136116214826995,"min":-1.5776951079275094}},{"name":"middle_flow/main_block_0/separable_conv0/bias","shape":[128],"dtype":"float32"},{"name":"middle_flow/main_block_0/separable_conv1/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004314773222979377,"min":-0.5652352922102984}},{"name":"middle_flow/main_block_0/separable_conv1/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01107162026798024,"min":-1.2400214700137868}},{"name":"middle_flow/main_block_0/separable_conv1/bias","shape":[128],"dtype":"float32"},{"name":"middle_flow/main_block_0/separable_conv2/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0036451735917259667,"min":-0.4848080876995536}},{"name":"middle_flow/main_block_0/separable_conv2/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008791744942758598,"min":-1.134135097615859}},{"name":"middle_flow/main_block_0/separable_conv2/bias","shape":[128],"dtype":"float32"},{"name":"middle_flow/main_block_1/separable_conv0/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004915751896652521,"min":-0.6095532351849126}},{"name":"middle_flow/main_block_1/separable_conv0/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010868691463096469,"min":-1.3368490499608656}},{"name":"middle_flow/main_block_1/separable_conv0/bias","shape":[128],"dtype":"float32"},{"name":"middle_flow/main_block_1/separable_conv1/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005010117269029804,"min":-0.6012140722835765}},{"name":"middle_flow/main_block_1/separable_conv1/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010311148213405235,"min":-1.3816938605963016}},{"name":"middle_flow/main_block_1/separable_conv1/bias","shape":[128],"dtype":"float32"},{"name":"middle_flow/main_block_1/separable_conv2/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004911523706772748,"min":-0.7367285560159123}},{"name":"middle_flow/main_block_1/separable_conv2/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008976466047997568,"min":-1.2207993825276693}},{"name":"middle_flow/main_block_1/separable_conv2/bias","shape":[128],"dtype":"float32"},{"name":"exit_flow/reduction_block/separable_conv0/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005074804436926748,"min":-0.7104726211697447}},{"name":"exit_flow/reduction_block/separable_conv0/pointwise_filter","shape":[1,1,128,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.011453078307357489,"min":-1.4545409450344011}},{"name":"exit_flow/reduction_block/separable_conv0/bias","shape":[256],"dtype":"float32"},{"name":"exit_flow/reduction_block/separable_conv1/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.007741751390344957,"min":-1.1380374543807086}},{"name":"exit_flow/reduction_block/separable_conv1/pointwise_filter","shape":[1,1,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.011347713189966538,"min":-1.497898141075583}},{"name":"exit_flow/reduction_block/separable_conv1/bias","shape":[256],"dtype":"float32"},{"name":"exit_flow/reduction_block/expansion_conv/filters","shape":[1,1,128,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006717281014311547,"min":-0.8329428457746318}},{"name":"exit_flow/reduction_block/expansion_conv/bias","shape":[256],"dtype":"float32"},{"name":"exit_flow/separable_conv/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0027201742518181892,"min":-0.3237007359663645}},{"name":"exit_flow/separable_conv/pointwise_filter","shape":[1,1,256,512],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010076364348916447,"min":-1.330080094056971}},{"name":"exit_flow/separable_conv/bias","shape":[512],"dtype":"float32"},{"name":"fc/age/weights","shape":[512,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008674054987290326,"min":-1.2664120281443876}},{"name":"fc/age/bias","shape":[1],"dtype":"float32"},{"name":"fc/gender/weights","shape":[512,2],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0029948226377075793,"min":-0.34140978069866407}},{"name":"fc/gender/bias","shape":[2],"dtype":"float32"}],"paths":["age_gender_model-shard1"]}]

0 commit comments

Comments
 (0)