Skip to content

Commit 622a49a

Browse files
added face expression recognition examples
1 parent 8330911 commit 622a49a

18 files changed

+821
-50
lines changed

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

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,16 @@ async function requestExternalImage(imageUrl) {
2525
function renderNavBar(navbarId, exampleUri) {
2626
const examples = [
2727
{
28-
uri: 'face_and_landmark_detection',
29-
name: 'Face And Landmark Detection'
28+
uri: 'face_detection',
29+
name: 'Face Detection'
30+
},
31+
{
32+
uri: 'face_landmark_detection',
33+
name: 'Face Landmark Detection'
34+
},
35+
{
36+
uri: 'face_expression_recognition',
37+
name: 'Face Expression Recognition'
3038
},
3139
{
3240
uri: 'face_recognition',
@@ -41,8 +49,16 @@ function renderNavBar(navbarId, exampleUri) {
4149
name: 'Video Face Tracking'
4250
},
4351
{
44-
uri: 'webcam_face_tracking',
45-
name: 'Webcam Face Tracking'
52+
uri: 'webcam_face_detection',
53+
name: 'Webcam Face Detection'
54+
},
55+
{
56+
uri: 'webcam_face_landmark_detection',
57+
name: 'Webcam Face Landmark Detection'
58+
},
59+
{
60+
uri: 'webcam_face_expression_recognition',
61+
name: 'Webcam Face Expression Recognition'
4662
},
4763
{
4864
uri: 'bbt_face_landmark_detection',
@@ -112,7 +128,7 @@ function renderNavBar(navbarId, exampleUri) {
112128
li.style.background='#b0b0b0'
113129
}
114130
const a = document.createElement('a')
115-
a.classList.add('waves-effect', 'waves-light')
131+
a.classList.add('waves-effect', 'waves-light', 'pad-sides-sm')
116132
a.href = ex.uri
117133
const span = document.createElement('span')
118134
span.innerHTML = ex.name
@@ -123,7 +139,7 @@ function renderNavBar(navbarId, exampleUri) {
123139
})
124140

125141
$('.button-collapse').sideNav({
126-
menuWidth: 240
142+
menuWidth: 260
127143
})
128144
}
129145

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,34 @@ function drawLandmarks(dimensions, canvas, results, withBoxes = true) {
2929
color: 'green'
3030
}
3131
faceapi.drawLandmarks(canvas, faceLandmarks, drawLandmarksOptions)
32+
}
33+
34+
function drawExpressions(dimensions, canvas, results, thresh, withBoxes = true) {
35+
const resizedResults = resizeCanvasAndResults(dimensions, canvas, results)
36+
37+
if (withBoxes) {
38+
faceapi.drawDetection(canvas, resizedResults.map(det => det.detection), { withScore: false })
39+
}
40+
41+
resizedResults.forEach(res => {
42+
const { box, imageDims } = res.detection
43+
const { expressions } = res
44+
45+
const sorted = expressions.sort((a, b) => b.probability - a.probability)
46+
const resultsToDisplay = sorted.filter(expr => expr.probability > thresh)
47+
48+
let offset = (box.y + box.height + resultsToDisplay.length * 22) > imageDims.height
49+
? - (resultsToDisplay.length * 22)
50+
: 0
51+
resultsToDisplay.forEach((expr, i) => {
52+
const text = `${expr.expression} (${faceapi.round(expr.probability)})`
53+
faceapi.drawText(
54+
faceapi.getContext2dOrThrow($('#overlay').get(0)),
55+
box.x,
56+
box.y + box.height + i * 22 + offset,
57+
text,
58+
{ textColor: i === 0 ? 'red' : 'blue', fontSize: i === 0 ? 22 : 16 }
59+
)
60+
})
61+
})
3262
}

examples/examples-browser/public/js/imageSelectionControls.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,21 @@ async function loadImageFromUrl(url) {
1010
updateResults()
1111
}
1212

13-
function renderImageSelectList(selectListId, onChange, initialValue) {
14-
const images = [1, 2, 3, 4, 5].map(idx => `bbt${idx}.jpg`)
13+
function renderImageSelectList(selectListId, onChange, initialValue, withFaceExpressionImages) {
14+
let images = [1, 2, 3, 4, 5].map(idx => `bbt${idx}.jpg`)
15+
16+
if (withFaceExpressionImages) {
17+
images = [
18+
'happy.jpg',
19+
'sad.jpg',
20+
'angry.jpg',
21+
'disgusted.jpg',
22+
'surprised.jpg',
23+
'fearful.jpg',
24+
'neutral.jpg'
25+
].concat(images)
26+
}
27+
1528
function renderChildren(select) {
1629
images.forEach(imageName =>
1730
renderOption(
@@ -30,13 +43,14 @@ function renderImageSelectList(selectListId, onChange, initialValue) {
3043
)
3144
}
3245

33-
function initImageSelectionControls() {
46+
function initImageSelectionControls(initialValue = 'bbt1.jpg', withFaceExpressionImages = false) {
3447
renderImageSelectList(
3548
'#selectList',
3649
async (uri) => {
3750
await onSelectedImageChanged(uri)
3851
},
39-
'bbt1.jpg'
52+
initialValue,
53+
withFaceExpressionImages
4054
)
4155
onSelectedImageChanged($('#selectList select').val())
4256
}

examples/examples-browser/public/styles.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
5353
padding: 0 10px !important;
5454
}
5555

56+
.pad-sides-sm {
57+
padding: 0 8px !important;
58+
}
59+
5660
#github-link {
5761
display: flex !important;
5862
justify-content: center;

examples/examples-browser/server.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@ app.use(express.static(path.join(__dirname, '../media')))
1515
app.use(express.static(path.join(__dirname, '../../weights')))
1616
app.use(express.static(path.join(__dirname, '../../dist')))
1717

18-
app.get('/', (req, res) => res.redirect('/face_and_landmark_detection'))
19-
app.get('/face_and_landmark_detection', (req, res) => res.sendFile(path.join(viewsDir, 'faceAndLandmarkDetection.html')))
18+
app.get('/', (req, res) => res.redirect('/face_detection'))
19+
app.get('/face_detection', (req, res) => res.sendFile(path.join(viewsDir, 'faceDetection.html')))
20+
app.get('/face_landmark_detection', (req, res) => res.sendFile(path.join(viewsDir, 'faceLandmarkDetection.html')))
21+
app.get('/face_expression_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'faceExpressionRecognition.html')))
2022
app.get('/face_extraction', (req, res) => res.sendFile(path.join(viewsDir, 'faceExtraction.html')))
2123
app.get('/face_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'faceRecognition.html')))
2224
app.get('/video_face_tracking', (req, res) => res.sendFile(path.join(viewsDir, 'videoFaceTracking.html')))
23-
app.get('/webcam_face_tracking', (req, res) => res.sendFile(path.join(viewsDir, 'webcamFaceTracking.html')))
25+
app.get('/webcam_face_detection', (req, res) => res.sendFile(path.join(viewsDir, 'webcamFaceDetection.html')))
26+
app.get('/webcam_face_landmark_detection', (req, res) => res.sendFile(path.join(viewsDir, 'webcamFaceLandmarkDetection.html')))
27+
app.get('/webcam_face_expression_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'webcamFaceExpressionRecognition.html')))
2428
app.get('/bbt_face_landmark_detection', (req, res) => res.sendFile(path.join(viewsDir, 'bbtFaceLandmarkDetection.html')))
2529
app.get('/bbt_face_similarity', (req, res) => res.sendFile(path.join(viewsDir, 'bbtFaceSimilarity.html')))
2630
app.get('/bbt_face_matching', (req, res) => res.sendFile(path.join(viewsDir, 'bbtFaceMatching.html')))
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
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+
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+
151+
drawDetections(inputImgEl, $('#overlay').get(0), results)
152+
}
153+
154+
async function run() {
155+
// load face detection
156+
await changeFaceDetector(SSD_MOBILENETV1)
157+
158+
// start processing image
159+
updateResults()
160+
}
161+
162+
$(document).ready(function() {
163+
renderNavBar('#navbar', 'face_detection')
164+
initImageSelectionControls()
165+
initFaceDetectionControls()
166+
run()
167+
})
168+
</script>
169+
</body>
170+
</html>

0 commit comments

Comments
 (0)