Skip to content

Commit e908bbd

Browse files
init age gender example + some fixes
1 parent 7cbd750 commit e908bbd

File tree

4 files changed

+194
-6
lines changed

4 files changed

+194
-6
lines changed

examples/examples-browser/public/js/commons.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ function renderNavBar(navbarId, exampleUri) {
3636
uri: 'face_expression_recognition',
3737
name: 'Face Expression Recognition'
3838
},
39+
{
40+
uri: 'age_and_gender_recognition',
41+
name: 'Age and Gender Recognition'
42+
},
3943
{
4044
uri: 'face_recognition',
4145
name: 'Face Recognition'

examples/examples-browser/server.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ app.get('/', (req, res) => res.redirect('/face_detection'))
1919
app.get('/face_detection', (req, res) => res.sendFile(path.join(viewsDir, 'faceDetection.html')))
2020
app.get('/face_landmark_detection', (req, res) => res.sendFile(path.join(viewsDir, 'faceLandmarkDetection.html')))
2121
app.get('/face_expression_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'faceExpressionRecognition.html')))
22+
app.get('/age_and_gender_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'ageAndGenderRecognition.html')))
2223
app.get('/face_extraction', (req, res) => res.sendFile(path.join(viewsDir, 'faceExtraction.html')))
2324
app.get('/face_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'faceRecognition.html')))
2425
app.get('/video_face_tracking', (req, res) => res.sendFile(path.join(viewsDir, 'videoFaceTracking.html')))
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<script src="face-api.js"></script>
5+
<script src="js/commons.js"></script>
6+
<script src="js/drawing.js"></script>
7+
<script src="js/faceDetectionControls.js"></script>
8+
<script src="js/imageSelectionControls.js"></script>
9+
<link rel="stylesheet" href="styles.css">
10+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css">
11+
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
12+
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
13+
</head>
14+
<body>
15+
<div id="navbar"></div>
16+
<div class="center-content page-container">
17+
18+
<div class="progress" id="loader">
19+
<div class="indeterminate"></div>
20+
</div>
21+
<div style="position: relative" class="margin">
22+
<img id="inputImg" src="" style="max-width: 800px;" />
23+
<canvas id="overlay" />
24+
</div>
25+
26+
<div class="row side-by-side">
27+
<!-- image_selection_control -->
28+
<div id="selectList"></div>
29+
<div class="row">
30+
<label for="imgUrlInput">Get image from URL:</label>
31+
<input id="imgUrlInput" type="text" class="bold">
32+
</div>
33+
<button
34+
class="waves-effect waves-light btn"
35+
onclick="loadImageFromUrl()"
36+
>
37+
Ok
38+
</button>
39+
<!-- image_selection_control -->
40+
</div>
41+
42+
<div class="row side-by-side">
43+
44+
<!-- face_detector_selection_control -->
45+
<div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
46+
<select id="selectFaceDetector">
47+
<option value="ssd_mobilenetv1">SSD Mobilenet V1</option>
48+
<option value="tiny_face_detector">Tiny Face Detector</option>
49+
<option value="mtcnn">MTCNN</option>
50+
</select>
51+
<label>Select Face Detector</label>
52+
</div>
53+
<!-- face_detector_selection_control -->
54+
55+
</div>
56+
57+
<!-- ssd_mobilenetv1_controls -->
58+
<span id="ssd_mobilenetv1_controls">
59+
<div class="row side-by-side">
60+
<div class="row">
61+
<label for="minConfidence">Min Confidence:</label>
62+
<input disabled value="0.5" id="minConfidence" type="text" class="bold">
63+
</div>
64+
<button
65+
class="waves-effect waves-light btn"
66+
onclick="onDecreaseMinConfidence()"
67+
>
68+
<i class="material-icons left">-</i>
69+
</button>
70+
<button
71+
class="waves-effect waves-light btn"
72+
onclick="onIncreaseMinConfidence()"
73+
>
74+
<i class="material-icons left">+</i>
75+
</button>
76+
</div>
77+
</span>
78+
<!-- ssd_mobilenetv1_controls -->
79+
80+
<!-- tiny_face_detector_controls -->
81+
<span id="tiny_face_detector_controls">
82+
<div class="row side-by-side">
83+
<div class="row input-field" style="margin-right: 20px;">
84+
<select id="inputSize">
85+
<option value="" disabled selected>Input Size:</option>
86+
<option value="160">160 x 160</option>
87+
<option value="224">224 x 224</option>
88+
<option value="320">320 x 320</option>
89+
<option value="416">416 x 416</option>
90+
<option value="512">512 x 512</option>
91+
<option value="608">608 x 608</option>
92+
</select>
93+
<label>Input Size</label>
94+
</div>
95+
<div class="row">
96+
<label for="scoreThreshold">Score Threshold:</label>
97+
<input disabled value="0.5" id="scoreThreshold" type="text" class="bold">
98+
</div>
99+
<button
100+
class="waves-effect waves-light btn"
101+
onclick="onDecreaseScoreThreshold()"
102+
>
103+
<i class="material-icons left">-</i>
104+
</button>
105+
<button
106+
class="waves-effect waves-light btn"
107+
onclick="onIncreaseScoreThreshold()"
108+
>
109+
<i class="material-icons left">+</i>
110+
</button>
111+
</div>
112+
</span>
113+
<!-- tiny_face_detector_controls -->
114+
115+
<!-- mtcnn_controls -->
116+
<span id="mtcnn_controls">
117+
<div class="row side-by-side">
118+
<div class="row">
119+
<label for="minFaceSize">Minimum Face Size:</label>
120+
<input disabled value="20" id="minFaceSize" type="text" class="bold">
121+
</div>
122+
<button
123+
class="waves-effect waves-light btn"
124+
onclick="onDecreaseMinFaceSize()"
125+
>
126+
<i class="material-icons left">-</i>
127+
</button>
128+
<button
129+
class="waves-effect waves-light btn"
130+
onclick="onIncreaseMinFaceSize()"
131+
>
132+
<i class="material-icons left">+</i>
133+
</button>
134+
</div>
135+
</span>
136+
<!-- mtcnn_controls -->
137+
138+
</body>
139+
140+
<script>
141+
142+
window.net = new faceapi.AgeGenderNet()
143+
144+
async function updateResults() {
145+
if (!isFaceDetectionModelLoaded()) {
146+
return
147+
}
148+
149+
const inputImgEl = $('#inputImg').get(0)
150+
const options = getFaceDetectorOptions()
151+
152+
const result = await faceapi.detectSingleFace(inputImgEl, options)
153+
154+
if (!result) return
155+
156+
const face = (await faceapi.extractFaces(inputImgEl, [result]))[0]
157+
const { age, gender, genderProbability } = await window.net.predictAgeAndGender(face)
158+
159+
console.log('age', age)
160+
console.log('gender', gender, genderProbability)
161+
}
162+
163+
async function run() {
164+
// load face detection and face expression recognition models
165+
await changeFaceDetector(SSD_MOBILENETV1)
166+
167+
const weights = await faceapi.fetchNetWeights('tmp/age_gender.weights')
168+
console.log(weights.length)
169+
await window.net.load(weights)
170+
171+
// start processing image
172+
updateResults()
173+
}
174+
175+
$(document).ready(function() {
176+
renderNavBar('#navbar', 'age_and_gender_recognition')
177+
initImageSelectionControls('happy.jpg', true)
178+
initFaceDetectionControls()
179+
run()
180+
})
181+
</script>
182+
</body>
183+
</html>

src/ageGenderNet/AgeGenderNet.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ export class AgeGenderNet extends NeuralNetwork<NetParams> {
3434
? this.faceFeatureExtractor.forwardInput(input)
3535
: input
3636

37-
const bottleneckFeatures2d = bottleneckFeatures.as2D(bottleneckFeatures.shape[0], -1)
38-
const age = fullyConnectedLayer(bottleneckFeatures2d, params.fc.age).as1D()
39-
const gender = fullyConnectedLayer(bottleneckFeatures2d, params.fc.gender)
37+
const pooled = tf.avgPool(bottleneckFeatures, [7, 7], [2, 2], 'valid').as2D(bottleneckFeatures.shape[0], -1)
38+
const age = fullyConnectedLayer(pooled, params.fc.age).as1D()
39+
const gender = fullyConnectedLayer(pooled, params.fc.gender)
4040
return { age, gender }
4141
})
4242
}
@@ -53,8 +53,8 @@ export class AgeGenderNet extends NeuralNetwork<NetParams> {
5353
public async predictAgeAndGender(input: TNetInput): Promise<{ age: number, gender: string, genderProbability: number }> {
5454
const netInput = await toNetInput(input)
5555
const out = await this.forwardInput(netInput)
56-
const age = await out.age.data()[0] as number
57-
const probMale = await out.gender.data()[0] as number
56+
const age = (await out.age.data())[0]
57+
const probMale = (await out.gender.data())[0]
5858

5959
const isMale = probMale > 0.5
6060
const gender = isMale ? 'male' : 'female'
@@ -93,7 +93,7 @@ export class AgeGenderNet extends NeuralNetwork<NetParams> {
9393

9494
protected extractParams(weights: Float32Array) {
9595

96-
const classifierWeightSize = (512 * 1) + (512 * 2)
96+
const classifierWeightSize = (512 * 1 + 1) + (512 * 2 + 2)
9797

9898
const featureExtractorWeights = weights.slice(0, weights.length - classifierWeightSize)
9999
const classifierWeights = weights.slice(weights.length - classifierWeightSize)

0 commit comments

Comments
 (0)