Skip to content

Commit e1d7085

Browse files
Merge pull request justadudewhohacks#287 from justadudewhohacks/age-gender
age and gender recognition
2 parents 2d885bb + 49114d2 commit e1d7085

File tree

84 files changed

+2784
-806
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+2784
-806
lines changed

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
sudo: required
22
language: node_js
33
node_js:
4-
- "node"
4+
#- "node"
5+
- "11"
56
- "10"
67
- "8"
78
# node 6 is not compatible with tfjs-node

README.md

Lines changed: 291 additions & 176 deletions
Large diffs are not rendered by default.

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

Lines changed: 8 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'
@@ -60,6 +64,10 @@ function renderNavBar(navbarId, exampleUri) {
6064
uri: 'webcam_face_expression_recognition',
6165
name: 'Webcam Face Expression Recognition'
6266
},
67+
{
68+
uri: 'webcam_age_and_gender_recognition',
69+
name: 'Webcam Age and Gender Recognition'
70+
},
6371
{
6472
uri: 'bbt_face_landmark_detection',
6573
name: 'BBT Face Landmark Detection'

examples/examples-browser/public/js/drawing.js

Lines changed: 0 additions & 42 deletions
This file was deleted.

examples/examples-browser/server.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ 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')))
2526
app.get('/webcam_face_detection', (req, res) => res.sendFile(path.join(viewsDir, 'webcamFaceDetection.html')))
2627
app.get('/webcam_face_landmark_detection', (req, res) => res.sendFile(path.join(viewsDir, 'webcamFaceLandmarkDetection.html')))
2728
app.get('/webcam_face_expression_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'webcamFaceExpressionRecognition.html')))
29+
app.get('/webcam_age_and_gender_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'webcamAgeAndGenderRecognition.html')))
2830
app.get('/bbt_face_landmark_detection', (req, res) => res.sendFile(path.join(viewsDir, 'bbtFaceLandmarkDetection.html')))
2931
app.get('/bbt_face_similarity', (req, res) => res.sendFile(path.join(viewsDir, 'bbtFaceSimilarity.html')))
3032
app.get('/bbt_face_matching', (req, res) => res.sendFile(path.join(viewsDir, 'bbtFaceMatching.html')))
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
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/faceDetectionControls.js"></script>
7+
<script src="js/imageSelectionControls.js"></script>
8+
<link rel="stylesheet" href="styles.css">
9+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css">
10+
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
11+
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
12+
</head>
13+
<body>
14+
<div id="navbar"></div>
15+
<div class="center-content page-container">
16+
17+
<div class="progress" id="loader">
18+
<div class="indeterminate"></div>
19+
</div>
20+
<div style="position: relative" class="margin">
21+
<img id="inputImg" src="" style="max-width: 800px;" />
22+
<canvas id="overlay" />
23+
</div>
24+
25+
<div class="row side-by-side">
26+
<!-- image_selection_control -->
27+
<div id="selectList"></div>
28+
<div class="row">
29+
<label for="imgUrlInput">Get image from URL:</label>
30+
<input id="imgUrlInput" type="text" class="bold">
31+
</div>
32+
<button
33+
class="waves-effect waves-light btn"
34+
onclick="loadImageFromUrl()"
35+
>
36+
Ok
37+
</button>
38+
<!-- image_selection_control -->
39+
</div>
40+
41+
<div class="row side-by-side">
42+
43+
<!-- face_detector_selection_control -->
44+
<div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
45+
<select id="selectFaceDetector">
46+
<option value="ssd_mobilenetv1">SSD Mobilenet V1</option>
47+
<option value="tiny_face_detector">Tiny Face Detector</option>
48+
<option value="mtcnn">MTCNN</option>
49+
</select>
50+
<label>Select Face Detector</label>
51+
</div>
52+
<!-- face_detector_selection_control -->
53+
54+
</div>
55+
56+
<!-- ssd_mobilenetv1_controls -->
57+
<span id="ssd_mobilenetv1_controls">
58+
<div class="row side-by-side">
59+
<div class="row">
60+
<label for="minConfidence">Min Confidence:</label>
61+
<input disabled value="0.5" id="minConfidence" type="text" class="bold">
62+
</div>
63+
<button
64+
class="waves-effect waves-light btn"
65+
onclick="onDecreaseMinConfidence()"
66+
>
67+
<i class="material-icons left">-</i>
68+
</button>
69+
<button
70+
class="waves-effect waves-light btn"
71+
onclick="onIncreaseMinConfidence()"
72+
>
73+
<i class="material-icons left">+</i>
74+
</button>
75+
</div>
76+
</span>
77+
<!-- ssd_mobilenetv1_controls -->
78+
79+
<!-- tiny_face_detector_controls -->
80+
<span id="tiny_face_detector_controls">
81+
<div class="row side-by-side">
82+
<div class="row input-field" style="margin-right: 20px;">
83+
<select id="inputSize">
84+
<option value="" disabled selected>Input Size:</option>
85+
<option value="160">160 x 160</option>
86+
<option value="224">224 x 224</option>
87+
<option value="320">320 x 320</option>
88+
<option value="416">416 x 416</option>
89+
<option value="512">512 x 512</option>
90+
<option value="608">608 x 608</option>
91+
</select>
92+
<label>Input Size</label>
93+
</div>
94+
<div class="row">
95+
<label for="scoreThreshold">Score Threshold:</label>
96+
<input disabled value="0.5" id="scoreThreshold" type="text" class="bold">
97+
</div>
98+
<button
99+
class="waves-effect waves-light btn"
100+
onclick="onDecreaseScoreThreshold()"
101+
>
102+
<i class="material-icons left">-</i>
103+
</button>
104+
<button
105+
class="waves-effect waves-light btn"
106+
onclick="onIncreaseScoreThreshold()"
107+
>
108+
<i class="material-icons left">+</i>
109+
</button>
110+
</div>
111+
</span>
112+
<!-- tiny_face_detector_controls -->
113+
114+
<!-- mtcnn_controls -->
115+
<span id="mtcnn_controls">
116+
<div class="row side-by-side">
117+
<div class="row">
118+
<label for="minFaceSize">Minimum Face Size:</label>
119+
<input disabled value="20" id="minFaceSize" type="text" class="bold">
120+
</div>
121+
<button
122+
class="waves-effect waves-light btn"
123+
onclick="onDecreaseMinFaceSize()"
124+
>
125+
<i class="material-icons left">-</i>
126+
</button>
127+
<button
128+
class="waves-effect waves-light btn"
129+
onclick="onIncreaseMinFaceSize()"
130+
>
131+
<i class="material-icons left">+</i>
132+
</button>
133+
</div>
134+
</span>
135+
<!-- mtcnn_controls -->
136+
137+
</body>
138+
139+
<script>
140+
141+
async function updateResults() {
142+
if (!isFaceDetectionModelLoaded()) {
143+
return
144+
}
145+
146+
const inputImgEl = $('#inputImg').get(0)
147+
const options = getFaceDetectorOptions()
148+
149+
const results = await faceapi.detectAllFaces(inputImgEl, options)
150+
// compute face landmarks to align faces for better accuracy
151+
.withFaceLandmarks()
152+
.withAgeAndGender()
153+
154+
const canvas = $('#overlay').get(0)
155+
faceapi.matchDimensions(canvas, inputImgEl)
156+
157+
const resizedResults = faceapi.resizeResults(results, inputImgEl)
158+
faceapi.draw.drawDetections(canvas, resizedResults)
159+
160+
resizedResults.forEach(result => {
161+
const { age, gender, genderProbability } = result
162+
new faceapi.draw.DrawTextField(
163+
[
164+
`${faceapi.round(age, 0)} years`,
165+
`${gender} (${faceapi.round(genderProbability)})`
166+
],
167+
result.detection.box.bottomLeft
168+
).draw(canvas)
169+
})
170+
}
171+
172+
async function run() {
173+
// load face detection and age and gender recognition models
174+
// and load face landmark model for face alignment
175+
await changeFaceDetector(SSD_MOBILENETV1)
176+
await faceapi.loadFaceLandmarkModel('/')
177+
await faceapi.nets.ageGenderNet.load('/')
178+
179+
// start processing image
180+
updateResults()
181+
}
182+
183+
$(document).ready(function() {
184+
renderNavBar('#navbar', 'age_and_gender_recognition')
185+
initImageSelectionControls('happy.jpg', true)
186+
initFaceDetectionControls()
187+
run()
188+
})
189+
</script>
190+
</body>
191+
</html>

examples/examples-browser/views/batchFaceLandmarks.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
function drawLandmarkCanvas(img, landmarks) {
6666
const canvas = faceapi.createCanvasFromMedia(img)
6767
$('#faceContainer').append(canvas)
68-
faceapi.drawLandmarks(canvas, landmarks, { lineWidth: 2 , drawLines: true })
68+
new faceapi.draw.DrawFaceLandmarks(landmarks).draw(canvas)
6969
}
7070

7171
async function runLandmarkDetection(useBatchInput) {

examples/examples-browser/views/batchFaceRecognition.html

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,10 @@
6868
$('#faceContainer').append(canvas)
6969

7070
const x = 20, y = canvas.height - 20
71-
faceapi.drawText(
72-
canvas.getContext('2d'),
73-
x,
74-
y,
75-
faceMatcher.findBestMatch(descriptor).toString(),
76-
Object.assign(faceapi.getDefaultDrawOptions(), { color: 'red', fontSize: 16 })
77-
)
71+
const ctx = faceapi.getContext2dOrThrow(canvas)
72+
ctx.font = '16px Georgia'
73+
ctx.fillStyle = 'red'
74+
ctx.fillText(faceMatcher.findBestMatch(descriptor).toString(), x, y)
7875
}
7976

8077
async function runComputeFaceDescriptors(useBatchInput) {

examples/examples-browser/views/bbtFaceLandmarkDetection.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@
4343
const canvas = faceapi.createCanvasFromMedia(currentImg)
4444
$('#faceContainer').empty()
4545
$('#faceContainer').append(canvas)
46-
faceapi.drawLandmarks(canvas, landmarks, { lineWidth: drawLines ? 2 : 4, drawLines })
46+
new faceapi.draw.DrawFaceLandmarks(landmarks, { drawLines }).draw(canvas)
4747
}
4848

4949
async function onSelectionChanged(uri) {
5050
currentImg = await faceapi.fetchImage(uri)
51-
landmarks = await faceapi.detectLandmarks(currentImg)
51+
landmarks = await faceapi.detectFaceLandmarks(currentImg)
5252
redraw()
5353
}
5454

examples/examples-browser/views/bbtFaceRecognition.html

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
<head>
44
<script src="face-api.js"></script>
55
<script src="js/commons.js"></script>
6-
<script src="js/drawing.js"></script>
76
<script src="js/faceDetectionControls.js"></script>
87
<script src="js/imageSelectionControls.js"></script>
98
<script src="js/bbt.js"></script>
@@ -159,17 +158,19 @@
159158

160159
function drawFaceRecognitionResults(results) {
161160
const canvas = $('#overlay').get(0)
161+
const inputImgEl = $('#inputImg').get(0)
162+
163+
faceapi.matchDimensions(canvas, inputImgEl)
162164
// resize detection and landmarks in case displayed image is smaller than
163165
// original size
164-
resizedResults = resizeCanvasAndResults($('#inputImg').get(0), canvas, results)
165-
166-
const boxesWithText = resizedResults.map(({ detection, descriptor }) =>
167-
new faceapi.BoxWithText(
168-
detection.box,
169-
faceMatcher.findBestMatch(descriptor).toString()
170-
)
171-
)
172-
faceapi.drawDetection(canvas, boxesWithText)
166+
const resizedResults = faceapi.resizeResults(results, inputImgEl)
167+
168+
resizedResults.forEach(({ detection, descriptor }) => {
169+
const label = faceMatcher.findBestMatch(descriptor).toString()
170+
const options = { label }
171+
const drawBox = new faceapi.draw.DrawBox(detection.box, options)
172+
drawBox.draw(canvas)
173+
})
173174
}
174175

175176
async function run() {

examples/examples-browser/views/faceDetection.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
<head>
44
<script src="face-api.js"></script>
55
<script src="js/commons.js"></script>
6-
<script src="js/drawing.js"></script>
76
<script src="js/faceDetectionControls.js"></script>
87
<script src="js/imageSelectionControls.js"></script>
98
<link rel="stylesheet" href="styles.css">
@@ -148,7 +147,9 @@
148147

149148
const results = await faceapi.detectAllFaces(inputImgEl, options)
150149

151-
drawDetections(inputImgEl, $('#overlay').get(0), results)
150+
const canvas = $('#overlay').get(0)
151+
faceapi.matchDimensions(canvas, inputImgEl)
152+
faceapi.draw.drawDetections(canvas, faceapi.resizeResults(results, inputImgEl))
152153
}
153154

154155
async function run() {

0 commit comments

Comments
 (0)