clmtrackr
Version:
Javascript library for precise tracking of facial features via Constrained Local Models
253 lines (216 loc) • 7.7 kB
HTML
<html lang="en">
<head>
<title>Face Tracker</title>
<meta charset="utf-8">
<style>
@import url(https://fonts.googleapis.com/css?family=Lato:300italic,700italic,300,700);
body {
font-family: 'Lato';
background-color: #f0f0f0;
margin: 0px auto;
max-width: 1150px;
}
#overlay {
position: absolute;
top: 0px;
left: 0px;
}
#container {
position : relative;
width : 700px;
height : 500px;
/*margin : 0px auto;*/
}
#content {
margin-top : 70px;
margin-left : 100px;
margin-right : 100px;
max-width: 950px;
}
#sketch {
display: none;
}
#filter {
display: none;
}
#convergence {
display : inline;
}
h2 {
font-weight : 400;
}
.btn {
font-family: 'Lato';
font-size: 16px;
}
.hide {
display : none;
}
</style>
</script>-->
</head>
<body>
<script src="./js/libs/utils.js"></script>
<script src="./js/libs/dat.gui.min.js"></script>
<script src="../dist/clmtrackr.js"></script>
<script src="./js/libs/Stats.js"></script>
<link rel="stylesheet" type="text/css" href="./styles/imgareaselect-default.css" />
<script src="./js/libs/jquery.min.js"></script>
<script src="./js/libs/jquery.imgareaselect.pack.js"></script>
<div id="content">
<h2>Face tracking in images</h2>
<div id="container">
<canvas id="image" width="625" height="500"></canvas>
<canvas id="overlay" width="625" height="500"></canvas>
</div>
<br/>
<input type="button" class="btn" value="start" onclick="animateClean()"></input>
<input type="button" class="btn" value="manually select face" onclick="selectBox()"></input>
<input type="file" class="btn" id="files" name="files[]" />
<p id="convergence"></p>
<div id="text">
<p>This is an example of precise face-tracking in an image using the javascript library <a href="https://github.com/auduno/clmtrackr"><em>clmtrackr</em></a>. To try it out, simply click start.</p>
<span id="loadimagetext"><p>To try it out with your own image, choose a file above by clicking "choose file". If the tracking has problems, try selecting the face in the image manually by clicking "manually select face", and click and hold to drag a square around the face in the image.</p></span>
</div>
<p>The image is from the <a href="http://www-prima.inrialpes.fr/FGnet/data/01-TalkingFace/talking_face.html">FG-net Talking Face</a> project</p>
<a href="https://github.com/auduno/clmtrackr"><img style="position: absolute; top: 0; left: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_left_green_007200.png" alt="Fork me on GitHub"></a>
<script>
// load json with all the images to test, as well as the annotations
// load image
// precision : measure ratio of bounding box that overlaps with actual ellipse. Discrete score : 1 if score > 0.5.
// face alignment : score mean squared error from the 5 points
//
var cc = document.getElementById('image').getContext('2d');
var overlay = document.getElementById('overlay');
var overlayCC = overlay.getContext('2d');
var img = new Image();
img.onload = function() {
cc.drawImage(img,0,0,625, 500);
};
img.src = './media/franck_02159.jpg';
var ctrack = new clm.tracker({stopOnConvergence : true, faceDetection: {useWebWorkers : true}});
ctrack.init();
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
document.getElementById('container').appendChild( stats.domElement );
var drawRequest;
function animateClean() {
ctrack.start(document.getElementById('image'));
drawLoop();
}
function animate(box) {
ctrack.start(document.getElementById('image'), box);
drawLoop();
}
function drawLoop() {
drawRequest = requestAnimFrame(drawLoop);
overlayCC.clearRect(0, 0, 720, 576);
if (ctrack.getCurrentPosition()) {
ctrack.draw(overlay);
}
}
// detect if tracker fails to find a face
document.addEventListener("clmtrackrNotFound", function(event) {
ctrack.stop();
alert("The tracking had problems with finding a face in this image. Try selecting the face in the image manually.")
}, false);
// detect if tracker loses tracking of face
document.addEventListener("clmtrackrLost", function(event) {
ctrack.stop();
alert("The tracking had problems converging on a face in this image. Try selecting the face in the image manually.")
}, false);
// detect if tracker has converged
document.addEventListener("clmtrackrConverged", function(event) {
document.getElementById('convergence').innerHTML = "CONVERGED";
document.getElementById('convergence').style.backgroundColor = "#00FF00";
// stop drawloop
cancelRequestAnimFrame(drawRequest);
}, false);
// update stats on iteration
document.addEventListener("clmtrackrIteration", function(event) {
stats.update();
}, false);
// manual selection of faces (with jquery imgareaselect plugin)
function selectBox() {
overlayCC.clearRect(0, 0, 720, 576);
document.getElementById('convergence').innerHTML = "";
ctrack.reset();
$('#overlay').addClass('hide');
$('#image').imgAreaSelect({
handles : true,
onSelectEnd : function(img, selection) {
// create box
var box = [selection.x1, selection.y1, selection.width, selection.height];
// do fitting
animate(box);
$('#overlay').removeClass('hide');
},
autoHide : true
});
}
// function to start showing images
function loadImage() {
if (fileList.indexOf(fileIndex) < 0) {
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
// check if positions already exist in storage
// Render thumbnail.
var canvas = document.getElementById('image')
var cc = canvas.getContext('2d');
var img = new Image();
img.onload = function() {
if (img.height > 500 || img.width > 700) {
var rel = img.height/img.width;
var neww = 700;
var newh = neww*rel;
if (newh > 500) {
newh = 500;
neww = newh/rel;
}
canvas.setAttribute('width', neww);
canvas.setAttribute('height', newh);
cc.drawImage(img,0,0,neww, newh);
} else {
canvas.setAttribute('width', img.width);
canvas.setAttribute('height', img.height);
cc.drawImage(img,0,0,img.width, img.height);
}
}
img.src = e.target.result;
};
})(fileList[fileIndex]);
reader.readAsDataURL(fileList[fileIndex]);
overlayCC.clearRect(0, 0, 720, 576);
document.getElementById('convergence').innerHTML = "";
ctrack.reset();
}
}
// set up file selector and variables to hold selections
var fileList, fileIndex;
if (window.File && window.FileReader && window.FileList) {
function handleFileSelect(evt) {
var files = evt.target.files;
fileList = [];
for (var i = 0;i < files.length;i++) {
if (!files[i].type.match('image.*')) {
continue;
}
fileList.push(files[i]);
}
if (files.length > 0) {
fileIndex = 0;
}
loadImage();
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
} else {
$('#files').addClass("hide");
$('#loadimagetext').addClass("hide");
}
</script>
</div>
</body>
</html>