Skip to content

Commit 7396324

Browse files
toggle control for face landmark detection in video and webcam examples
1 parent 0ea55f9 commit 7396324

File tree

9 files changed

+157
-93
lines changed

9 files changed

+157
-93
lines changed

examples/public/js/commons.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ function renderNavBar(navbarId, exampleUri) {
127127
})
128128

129129
$('.button-collapse').sideNav({
130-
menuWidth: 280
130+
menuWidth: 240
131131
})
132132
}
133133

examples/public/js/drawing.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
function resizeCanvasAndResults(dimensions, canvas, results) {
2+
const { width, height } = dimensions instanceof HTMLVideoElement
3+
? faceapi.getMediaDimensions(dimensions)
4+
: dimensions
5+
canvas.width = width
6+
canvas.height = height
7+
8+
// resize detections (and landmarks) in case displayed image is smaller than
9+
// original size
10+
return results.map(res => res.forSize(width, height))
11+
}
12+
13+
function drawDetections(dimensions, canvas, detections) {
14+
const resizedDetections = resizeCanvasAndResults(dimensions, canvas, detections)
15+
faceapi.drawDetection(canvas, resizedDetections)
16+
}
17+
18+
function drawLandmarks(dimensions, canvas, results, withBoxes = true) {
19+
const resizedResults = resizeCanvasAndResults(dimensions, canvas, results)
20+
21+
if (withBoxes) {
22+
const alignedFaceRectangles = resizedResults.map(det => det.alignedRect)
23+
faceapi.drawDetection(canvas, alignedFaceRectangles)
24+
}
25+
26+
const faceLandmarks = resizedResults.map(det => det.landmarks)
27+
const drawLandmarksOptions = {
28+
lineWidth: 2,
29+
drawLines: true,
30+
color: 'green'
31+
}
32+
faceapi.drawLandmarks(canvas, faceLandmarks, drawLandmarksOptions)
33+
}

examples/public/js/faceDetectionControls.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ async function changeFaceDetector(detector) {
9393
.forEach(id => $(id).hide())
9494

9595
selectedFaceDetector = detector
96-
$('#selectFaceDetector').val(detector)
96+
const faceDetectorSelect = $('#selectFaceDetector')
97+
faceDetectorSelect.val(detector)
98+
faceDetectorSelect.material_select()
9799

98100
$('#loader').show()
99101
if (!isFaceDetectionModelLoaded()) {

examples/public/styles.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
right: 0;
44
margin: auto;
55
margin-top: 20px;
6-
padding-left: 300px;
6+
padding-left: 260px;
77
display: inline-flex !important;
88
}
99

examples/views/faceDetection.html

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

148149
const detections = await faceapi.detectAllFaces(inputImgEl, options)
149150

150-
drawDetections(detections)
151-
}
152-
153-
function drawDetections(detections) {
154-
const { width, height } = $('#inputImg').get(0)
155-
const canvas = $('#overlay').get(0)
156-
canvas.width = width
157-
canvas.height = height
158-
faceapi.drawDetection(canvas, detections.map(det => det.forSize(width, height)))
151+
drawDetections(inputImgEl, $('#overlay').get(0), detections)
159152
}
160153

161154
async function run() {

examples/views/faceLandmarkDetection.html

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<head>
44
<script src="face-api.js"></script>
55
<script src="js/commons.js"></script>
6+
<script src="js/drawing.js"></script>
67
<script src="js/faceDetectionControls.js"></script>
78
<script src="js/imageSelectionControls.js"></script>
89
<link rel="stylesheet" href="styles.css">
@@ -147,33 +148,10 @@
147148
const options = getFaceDetectorOptions()
148149

149150
const results = await faceapi
150-
.detectAllFaces($('#inputImg').get(0), options)
151+
.detectAllFaces(inputImgEl, options)
151152
.withFaceLandmarks()
152153

153-
drawLandmarks(results)
154-
}
155-
156-
function drawLandmarks(results) {
157-
// draw results
158-
const { width, height } = $('#inputImg').get(0)
159-
const canvas = $('#overlay').get(0)
160-
canvas.width = width
161-
canvas.height = height
162-
163-
// resize detection and landmarks in case displayed image is smaller than
164-
// original size
165-
results = results.map(res => res.forSize(width, height))
166-
167-
const alignedFaceRectangles = results.map(det => det.alignedRect)
168-
faceapi.drawDetection(canvas, alignedFaceRectangles)
169-
170-
const faceLandmarks = results.map(det => det.landmarks)
171-
const drawLandmarksOptions = {
172-
lineWidth: 2,
173-
drawLines: true,
174-
color: 'green'
175-
}
176-
faceapi.drawLandmarks(canvas, faceLandmarks, drawLandmarksOptions)
154+
drawLandmarks(inputImgEl, $('#overlay').get(0), results)
177155
}
178156

179157
async function run() {

examples/views/faceRecognition.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<head>
44
<script src="face-api.js"></script>
55
<script src="js/commons.js"></script>
6+
<script src="js/drawing.js"></script>
67
<script src="js/faceDetectionControls.js"></script>
78
<script src="js/imageSelectionControls.js"></script>
89
<script src="js/bbt.js"></script>

examples/views/videoFaceTracking.html

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<head>
44
<script src="face-api.js"></script>
55
<script src="js/commons.js"></script>
6+
<script src="js/drawing.js"></script>
67
<script src="js/faceDetectionControls.js"></script>
78
<link rel="stylesheet" href="styles.css">
89
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css">
@@ -21,29 +22,40 @@
2122
<canvas id="overlay" />
2223
</div>
2324

24-
<!-- fps_meter -->
25-
<div id="fps_meter" class="row side-by-side">
26-
<div class="row">
27-
<label for="time">Time:</label>
28-
<input disabled value="-" id="time" type="text" class="bold">
25+
<div class="row side-by-side">
26+
27+
<!-- face_detector_selection_control -->
28+
<div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
29+
<select id="selectFaceDetector">
30+
<option value="ssd_mobilenetv1">SSD Mobilenet V1</option>
31+
<option value="tiny_face_detector">Tiny Face Detector</option>
32+
<option value="mtcnn">MTCNN</option>
33+
</select>
34+
<label>Select Face Detector</label>
2935
</div>
30-
<div class="row">
31-
<label for="fps">Estimated Fps:</label>
32-
<input disabled value="-" id="fps" type="text" class="bold">
36+
<!-- face_detector_selection_control -->
37+
38+
<!-- check boxes -->
39+
<div class="row" style="width: 220px;">
40+
<input type="checkbox" id="withFaceLandmarksCheckbox" onchange="onChangeWithFaceLandmarks(event)" />
41+
<label for="withFaceLandmarksCheckbox">Detect Face Landmarks</label>
42+
<input type="checkbox" id="hideBoundingBoxesCheckbox" onchange="onChangeHideBoundingBoxes(event)" />
43+
<label for="hideBoundingBoxesCheckbox">Hide Bounding Boxes</label>
3344
</div>
45+
<!-- check boxes -->
46+
47+
<!-- fps_meter -->
48+
<div id="fps_meter" class="row side-by-side">
49+
<div>
50+
<label for="time">Time:</label>
51+
<input disabled value="-" id="time" type="text" class="bold">
52+
<label for="fps">Estimated Fps:</label>
53+
<input disabled value="-" id="fps" type="text" class="bold">
54+
</div>
55+
</div>
56+
<!-- fps_meter -->
57+
3458
</div>
35-
<!-- fps_meter -->
36-
37-
<!-- face_detector_selection_control -->
38-
<div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
39-
<select id="selectFaceDetector">
40-
<option value="ssd_mobilenetv1">SSD Mobilenet V1</option>
41-
<option value="tiny_face_detector">Tiny Face Detector</option>
42-
<option value="mtcnn">MTCNN</option>
43-
</select>
44-
<label>Select Face Detector</label>
45-
</div>
46-
<!-- face_detector_selection_control -->
4759

4860
<!-- ssd_mobilenetv1_controls -->
4961
<span id="ssd_mobilenetv1_controls">
@@ -130,6 +142,16 @@
130142

131143
<script>
132144
let forwardTimes = []
145+
let withFaceLandmarks = false
146+
let withBoxes = true
147+
148+
function onChangeWithFaceLandmarks(e) {
149+
withFaceLandmarks = $(e.target).prop('checked')
150+
}
151+
152+
function onChangeHideBoundingBoxes(e) {
153+
withBoxes = !$(e.target).prop('checked')
154+
}
133155

134156
function updateTimeStats(timeInMs) {
135157
forwardTimes = [timeInMs].concat(forwardTimes).slice(0, 30)
@@ -144,23 +166,29 @@
144166

145167

146168
const options = getFaceDetectorOptions()
169+
147170
const ts = Date.now()
148-
const detections = await faceapi.detectAllFaces(videoEl, options)
171+
172+
const faceDetectionTask = faceapi.detectAllFaces(videoEl, options)
173+
const results = withFaceLandmarks
174+
? await faceDetectionTask.withFaceLandmarks()
175+
: await faceDetectionTask
176+
149177
updateTimeStats(Date.now() - ts)
150178

151-
// draw results
152-
const canvas = $('#overlay').get(0)
153-
const { width, height } = faceapi.getMediaDimensions(videoEl)
154-
canvas.width = width
155-
canvas.height = height
156-
faceapi.drawDetection(canvas, detections.map(det => det.forSize(width, height)))
179+
const drawFunction = withFaceLandmarks
180+
? drawLandmarks
181+
: drawDetections
182+
183+
drawFunction(videoEl, $('#overlay').get(0), results, withBoxes)
157184

158185
setTimeout(() => onPlay(videoEl))
159186
}
160187

161188
async function run() {
162-
// load face detection model
189+
// load face detection and face landmark models
163190
await changeFaceDetector(TINY_FACE_DETECTOR)
191+
await faceapi.loadFaceLandmarkModel('/')
164192
changeInputSize(416)
165193

166194
// start processing frames

examples/views/webcamFaceTracking.html

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<head>
44
<script src="face-api.js"></script>
55
<script src="js/commons.js"></script>
6+
<script src="js/drawing.js"></script>
67
<script src="js/faceDetectionControls.js"></script>
78
<link rel="stylesheet" href="styles.css">
89
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css">
@@ -21,29 +22,41 @@
2122
<canvas id="overlay" />
2223
</div>
2324

24-
<!-- fps_meter -->
25-
<div id="fps_meter" class="row side-by-side">
26-
<div class="row">
27-
<label for="time">Time:</label>
28-
<input disabled value="-" id="time" type="text" class="bold">
25+
<div class="row side-by-side">
26+
27+
<!-- face_detector_selection_control -->
28+
<div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
29+
<select id="selectFaceDetector">
30+
<option value="ssd_mobilenetv1">SSD Mobilenet V1</option>
31+
<option value="tiny_face_detector">Tiny Face Detector</option>
32+
<option value="mtcnn">MTCNN</option>
33+
</select>
34+
<label>Select Face Detector</label>
2935
</div>
30-
<div class="row">
31-
<label for="fps">Estimated Fps:</label>
32-
<input disabled value="-" id="fps" type="text" class="bold">
36+
<!-- face_detector_selection_control -->
37+
38+
<!-- check boxes -->
39+
<div class="row" style="width: 220px;">
40+
<input type="checkbox" id="withFaceLandmarksCheckbox" onchange="onChangeWithFaceLandmarks(event)" />
41+
<label for="withFaceLandmarksCheckbox">Detect Face Landmarks</label>
42+
<input type="checkbox" id="hideBoundingBoxesCheckbox" onchange="onChangeHideBoundingBoxes(event)" />
43+
<label for="hideBoundingBoxesCheckbox">Hide Bounding Boxes</label>
3344
</div>
45+
<!-- check boxes -->
46+
47+
<!-- fps_meter -->
48+
<div id="fps_meter" class="row side-by-side">
49+
<div>
50+
<label for="time">Time:</label>
51+
<input disabled value="-" id="time" type="text" class="bold">
52+
<label for="fps">Estimated Fps:</label>
53+
<input disabled value="-" id="fps" type="text" class="bold">
54+
</div>
55+
</div>
56+
<!-- fps_meter -->
57+
3458
</div>
35-
<!-- fps_meter -->
36-
37-
<!-- face_detector_selection_control -->
38-
<div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
39-
<select id="selectFaceDetector">
40-
<option value="ssd_mobilenetv1">SSD Mobilenet V1</option>
41-
<option value="tiny_face_detector">Tiny Face Detector</option>
42-
<option value="mtcnn">MTCNN</option>
43-
</select>
44-
<label>Select Face Detector</label>
45-
</div>
46-
<!-- face_detector_selection_control -->
59+
4760

4861
<!-- ssd_mobilenetv1_controls -->
4962
<span id="ssd_mobilenetv1_controls">
@@ -131,6 +144,16 @@
131144

132145
<script>
133146
let forwardTimes = []
147+
let withFaceLandmarks = false
148+
let withBoxes = true
149+
150+
function onChangeWithFaceLandmarks(e) {
151+
withFaceLandmarks = $(e.target).prop('checked')
152+
}
153+
154+
function onChangeHideBoundingBoxes(e) {
155+
withBoxes = !$(e.target).prop('checked')
156+
}
134157

135158
function updateTimeStats(timeInMs) {
136159
forwardTimes = [timeInMs].concat(forwardTimes).slice(0, 30)
@@ -145,23 +168,29 @@
145168

146169

147170
const options = getFaceDetectorOptions()
171+
148172
const ts = Date.now()
149-
const detections = await faceapi.detectAllFaces(videoEl, options)
173+
174+
const faceDetectionTask = faceapi.detectAllFaces(videoEl, options)
175+
const results = withFaceLandmarks
176+
? await faceDetectionTask.withFaceLandmarks()
177+
: await faceDetectionTask
178+
150179
updateTimeStats(Date.now() - ts)
151180

152-
// draw results
153-
const canvas = $('#overlay').get(0)
154-
const { width, height } = faceapi.getMediaDimensions(videoEl)
155-
canvas.width = width
156-
canvas.height = height
157-
faceapi.drawDetection(canvas, detections.map(det => det.forSize(width, height)))
181+
const drawFunction = withFaceLandmarks
182+
? drawLandmarks
183+
: drawDetections
184+
185+
drawFunction(videoEl, $('#overlay').get(0), results, withBoxes)
158186

159187
setTimeout(() => onPlay(videoEl))
160188
}
161189

162190
async function run() {
163-
// load face detection model
191+
// load face detection and face landmark models
164192
await changeFaceDetector(TINY_FACE_DETECTOR)
193+
await faceapi.loadFaceLandmarkModel('/')
165194
changeInputSize(128)
166195

167196
// try to access users webcam and stream the images

0 commit comments

Comments
 (0)