Commit 7396324d by vincent

toggle control for face landmark detection in video and webcam examples

parent 0ea55f92
...@@ -127,7 +127,7 @@ function renderNavBar(navbarId, exampleUri) { ...@@ -127,7 +127,7 @@ function renderNavBar(navbarId, exampleUri) {
}) })
$('.button-collapse').sideNav({ $('.button-collapse').sideNav({
menuWidth: 280 menuWidth: 240
}) })
} }
......
function resizeCanvasAndResults(dimensions, canvas, results) {
const { width, height } = dimensions instanceof HTMLVideoElement
? faceapi.getMediaDimensions(dimensions)
: dimensions
canvas.width = width
canvas.height = height
// resize detections (and landmarks) in case displayed image is smaller than
// original size
return results.map(res => res.forSize(width, height))
}
function drawDetections(dimensions, canvas, detections) {
const resizedDetections = resizeCanvasAndResults(dimensions, canvas, detections)
faceapi.drawDetection(canvas, resizedDetections)
}
function drawLandmarks(dimensions, canvas, results, withBoxes = true) {
const resizedResults = resizeCanvasAndResults(dimensions, canvas, results)
if (withBoxes) {
const alignedFaceRectangles = resizedResults.map(det => det.alignedRect)
faceapi.drawDetection(canvas, alignedFaceRectangles)
}
const faceLandmarks = resizedResults.map(det => det.landmarks)
const drawLandmarksOptions = {
lineWidth: 2,
drawLines: true,
color: 'green'
}
faceapi.drawLandmarks(canvas, faceLandmarks, drawLandmarksOptions)
}
\ No newline at end of file
...@@ -93,7 +93,9 @@ async function changeFaceDetector(detector) { ...@@ -93,7 +93,9 @@ async function changeFaceDetector(detector) {
.forEach(id => $(id).hide()) .forEach(id => $(id).hide())
selectedFaceDetector = detector selectedFaceDetector = detector
$('#selectFaceDetector').val(detector) const faceDetectorSelect = $('#selectFaceDetector')
faceDetectorSelect.val(detector)
faceDetectorSelect.material_select()
$('#loader').show() $('#loader').show()
if (!isFaceDetectionModelLoaded()) { if (!isFaceDetectionModelLoaded()) {
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
right: 0; right: 0;
margin: auto; margin: auto;
margin-top: 20px; margin-top: 20px;
padding-left: 300px; padding-left: 260px;
display: inline-flex !important; display: inline-flex !important;
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
<head> <head>
<script src="face-api.js"></script> <script src="face-api.js"></script>
<script src="js/commons.js"></script> <script src="js/commons.js"></script>
<script src="js/drawing.js"></script>
<script src="js/faceDetectionControls.js"></script> <script src="js/faceDetectionControls.js"></script>
<script src="js/imageSelectionControls.js"></script> <script src="js/imageSelectionControls.js"></script>
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
...@@ -147,15 +148,7 @@ ...@@ -147,15 +148,7 @@
const detections = await faceapi.detectAllFaces(inputImgEl, options) const detections = await faceapi.detectAllFaces(inputImgEl, options)
drawDetections(detections) drawDetections(inputImgEl, $('#overlay').get(0), detections)
}
function drawDetections(detections) {
const { width, height } = $('#inputImg').get(0)
const canvas = $('#overlay').get(0)
canvas.width = width
canvas.height = height
faceapi.drawDetection(canvas, detections.map(det => det.forSize(width, height)))
} }
async function run() { async function run() {
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
<head> <head>
<script src="face-api.js"></script> <script src="face-api.js"></script>
<script src="js/commons.js"></script> <script src="js/commons.js"></script>
<script src="js/drawing.js"></script>
<script src="js/faceDetectionControls.js"></script> <script src="js/faceDetectionControls.js"></script>
<script src="js/imageSelectionControls.js"></script> <script src="js/imageSelectionControls.js"></script>
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
...@@ -147,33 +148,10 @@ ...@@ -147,33 +148,10 @@
const options = getFaceDetectorOptions() const options = getFaceDetectorOptions()
const results = await faceapi const results = await faceapi
.detectAllFaces($('#inputImg').get(0), options) .detectAllFaces(inputImgEl, options)
.withFaceLandmarks() .withFaceLandmarks()
drawLandmarks(results) drawLandmarks(inputImgEl, $('#overlay').get(0), results)
}
function drawLandmarks(results) {
// draw results
const { width, height } = $('#inputImg').get(0)
const canvas = $('#overlay').get(0)
canvas.width = width
canvas.height = height
// resize detection and landmarks in case displayed image is smaller than
// original size
results = results.map(res => res.forSize(width, height))
const alignedFaceRectangles = results.map(det => det.alignedRect)
faceapi.drawDetection(canvas, alignedFaceRectangles)
const faceLandmarks = results.map(det => det.landmarks)
const drawLandmarksOptions = {
lineWidth: 2,
drawLines: true,
color: 'green'
}
faceapi.drawLandmarks(canvas, faceLandmarks, drawLandmarksOptions)
} }
async function run() { async function run() {
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
<head> <head>
<script src="face-api.js"></script> <script src="face-api.js"></script>
<script src="js/commons.js"></script> <script src="js/commons.js"></script>
<script src="js/drawing.js"></script>
<script src="js/faceDetectionControls.js"></script> <script src="js/faceDetectionControls.js"></script>
<script src="js/imageSelectionControls.js"></script> <script src="js/imageSelectionControls.js"></script>
<script src="js/bbt.js"></script> <script src="js/bbt.js"></script>
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
<head> <head>
<script src="face-api.js"></script> <script src="face-api.js"></script>
<script src="js/commons.js"></script> <script src="js/commons.js"></script>
<script src="js/drawing.js"></script>
<script src="js/faceDetectionControls.js"></script> <script src="js/faceDetectionControls.js"></script>
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css">
...@@ -21,29 +22,40 @@ ...@@ -21,29 +22,40 @@
<canvas id="overlay" /> <canvas id="overlay" />
</div> </div>
<!-- fps_meter --> <div class="row side-by-side">
<div id="fps_meter" class="row side-by-side">
<div class="row"> <!-- face_detector_selection_control -->
<label for="time">Time:</label> <div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
<input disabled value="-" id="time" type="text" class="bold"> <select id="selectFaceDetector">
<option value="ssd_mobilenetv1">SSD Mobilenet V1</option>
<option value="tiny_face_detector">Tiny Face Detector</option>
<option value="mtcnn">MTCNN</option>
</select>
<label>Select Face Detector</label>
</div> </div>
<div class="row"> <!-- face_detector_selection_control -->
<label for="fps">Estimated Fps:</label>
<input disabled value="-" id="fps" type="text" class="bold"> <!-- check boxes -->
<div class="row" style="width: 220px;">
<input type="checkbox" id="withFaceLandmarksCheckbox" onchange="onChangeWithFaceLandmarks(event)" />
<label for="withFaceLandmarksCheckbox">Detect Face Landmarks</label>
<input type="checkbox" id="hideBoundingBoxesCheckbox" onchange="onChangeHideBoundingBoxes(event)" />
<label for="hideBoundingBoxesCheckbox">Hide Bounding Boxes</label>
</div> </div>
<!-- check boxes -->
<!-- fps_meter -->
<div id="fps_meter" class="row side-by-side">
<div>
<label for="time">Time:</label>
<input disabled value="-" id="time" type="text" class="bold">
<label for="fps">Estimated Fps:</label>
<input disabled value="-" id="fps" type="text" class="bold">
</div>
</div>
<!-- fps_meter -->
</div> </div>
<!-- fps_meter -->
<!-- face_detector_selection_control -->
<div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
<select id="selectFaceDetector">
<option value="ssd_mobilenetv1">SSD Mobilenet V1</option>
<option value="tiny_face_detector">Tiny Face Detector</option>
<option value="mtcnn">MTCNN</option>
</select>
<label>Select Face Detector</label>
</div>
<!-- face_detector_selection_control -->
<!-- ssd_mobilenetv1_controls --> <!-- ssd_mobilenetv1_controls -->
<span id="ssd_mobilenetv1_controls"> <span id="ssd_mobilenetv1_controls">
...@@ -130,6 +142,16 @@ ...@@ -130,6 +142,16 @@
<script> <script>
let forwardTimes = [] let forwardTimes = []
let withFaceLandmarks = false
let withBoxes = true
function onChangeWithFaceLandmarks(e) {
withFaceLandmarks = $(e.target).prop('checked')
}
function onChangeHideBoundingBoxes(e) {
withBoxes = !$(e.target).prop('checked')
}
function updateTimeStats(timeInMs) { function updateTimeStats(timeInMs) {
forwardTimes = [timeInMs].concat(forwardTimes).slice(0, 30) forwardTimes = [timeInMs].concat(forwardTimes).slice(0, 30)
...@@ -144,23 +166,29 @@ ...@@ -144,23 +166,29 @@
const options = getFaceDetectorOptions() const options = getFaceDetectorOptions()
const ts = Date.now() const ts = Date.now()
const detections = await faceapi.detectAllFaces(videoEl, options)
const faceDetectionTask = faceapi.detectAllFaces(videoEl, options)
const results = withFaceLandmarks
? await faceDetectionTask.withFaceLandmarks()
: await faceDetectionTask
updateTimeStats(Date.now() - ts) updateTimeStats(Date.now() - ts)
// draw results const drawFunction = withFaceLandmarks
const canvas = $('#overlay').get(0) ? drawLandmarks
const { width, height } = faceapi.getMediaDimensions(videoEl) : drawDetections
canvas.width = width
canvas.height = height drawFunction(videoEl, $('#overlay').get(0), results, withBoxes)
faceapi.drawDetection(canvas, detections.map(det => det.forSize(width, height)))
setTimeout(() => onPlay(videoEl)) setTimeout(() => onPlay(videoEl))
} }
async function run() { async function run() {
// load face detection model // load face detection and face landmark models
await changeFaceDetector(TINY_FACE_DETECTOR) await changeFaceDetector(TINY_FACE_DETECTOR)
await faceapi.loadFaceLandmarkModel('/')
changeInputSize(416) changeInputSize(416)
// start processing frames // start processing frames
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
<head> <head>
<script src="face-api.js"></script> <script src="face-api.js"></script>
<script src="js/commons.js"></script> <script src="js/commons.js"></script>
<script src="js/drawing.js"></script>
<script src="js/faceDetectionControls.js"></script> <script src="js/faceDetectionControls.js"></script>
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css">
...@@ -21,29 +22,41 @@ ...@@ -21,29 +22,41 @@
<canvas id="overlay" /> <canvas id="overlay" />
</div> </div>
<!-- fps_meter --> <div class="row side-by-side">
<div id="fps_meter" class="row side-by-side">
<div class="row"> <!-- face_detector_selection_control -->
<label for="time">Time:</label> <div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
<input disabled value="-" id="time" type="text" class="bold"> <select id="selectFaceDetector">
<option value="ssd_mobilenetv1">SSD Mobilenet V1</option>
<option value="tiny_face_detector">Tiny Face Detector</option>
<option value="mtcnn">MTCNN</option>
</select>
<label>Select Face Detector</label>
</div> </div>
<div class="row"> <!-- face_detector_selection_control -->
<label for="fps">Estimated Fps:</label>
<input disabled value="-" id="fps" type="text" class="bold"> <!-- check boxes -->
<div class="row" style="width: 220px;">
<input type="checkbox" id="withFaceLandmarksCheckbox" onchange="onChangeWithFaceLandmarks(event)" />
<label for="withFaceLandmarksCheckbox">Detect Face Landmarks</label>
<input type="checkbox" id="hideBoundingBoxesCheckbox" onchange="onChangeHideBoundingBoxes(event)" />
<label for="hideBoundingBoxesCheckbox">Hide Bounding Boxes</label>
</div> </div>
<!-- check boxes -->
<!-- fps_meter -->
<div id="fps_meter" class="row side-by-side">
<div>
<label for="time">Time:</label>
<input disabled value="-" id="time" type="text" class="bold">
<label for="fps">Estimated Fps:</label>
<input disabled value="-" id="fps" type="text" class="bold">
</div>
</div>
<!-- fps_meter -->
</div> </div>
<!-- fps_meter -->
<!-- face_detector_selection_control -->
<div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
<select id="selectFaceDetector">
<option value="ssd_mobilenetv1">SSD Mobilenet V1</option>
<option value="tiny_face_detector">Tiny Face Detector</option>
<option value="mtcnn">MTCNN</option>
</select>
<label>Select Face Detector</label>
</div>
<!-- face_detector_selection_control -->
<!-- ssd_mobilenetv1_controls --> <!-- ssd_mobilenetv1_controls -->
<span id="ssd_mobilenetv1_controls"> <span id="ssd_mobilenetv1_controls">
...@@ -131,6 +144,16 @@ ...@@ -131,6 +144,16 @@
<script> <script>
let forwardTimes = [] let forwardTimes = []
let withFaceLandmarks = false
let withBoxes = true
function onChangeWithFaceLandmarks(e) {
withFaceLandmarks = $(e.target).prop('checked')
}
function onChangeHideBoundingBoxes(e) {
withBoxes = !$(e.target).prop('checked')
}
function updateTimeStats(timeInMs) { function updateTimeStats(timeInMs) {
forwardTimes = [timeInMs].concat(forwardTimes).slice(0, 30) forwardTimes = [timeInMs].concat(forwardTimes).slice(0, 30)
...@@ -145,23 +168,29 @@ ...@@ -145,23 +168,29 @@
const options = getFaceDetectorOptions() const options = getFaceDetectorOptions()
const ts = Date.now() const ts = Date.now()
const detections = await faceapi.detectAllFaces(videoEl, options)
const faceDetectionTask = faceapi.detectAllFaces(videoEl, options)
const results = withFaceLandmarks
? await faceDetectionTask.withFaceLandmarks()
: await faceDetectionTask
updateTimeStats(Date.now() - ts) updateTimeStats(Date.now() - ts)
// draw results const drawFunction = withFaceLandmarks
const canvas = $('#overlay').get(0) ? drawLandmarks
const { width, height } = faceapi.getMediaDimensions(videoEl) : drawDetections
canvas.width = width
canvas.height = height drawFunction(videoEl, $('#overlay').get(0), results, withBoxes)
faceapi.drawDetection(canvas, detections.map(det => det.forSize(width, height)))
setTimeout(() => onPlay(videoEl)) setTimeout(() => onPlay(videoEl))
} }
async function run() { async function run() {
// load face detection model // load face detection and face landmark models
await changeFaceDetector(TINY_FACE_DETECTOR) await changeFaceDetector(TINY_FACE_DETECTOR)
await faceapi.loadFaceLandmarkModel('/')
changeInputSize(128) changeInputSize(128)
// try to access users webcam and stream the images // try to access users webcam and stream the images
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment