UNPKG

clmtrackr

Version:

Javascript library for precise tracking of facial features via Constrained Local Models

330 lines (280 loc) 10 kB
<!doctype html> <html lang="en"> <head> <title>Gender detection</title> <meta charset="utf-8"> <link href="./styles/bootstrap.min.css" rel="stylesheet" type="text/css"> <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; -o-transform : scaleX(-1); -webkit-transform : scaleX(-1); transform : scaleX(-1); -ms-filter : fliph; /*IE*/ filter : fliph; /*IE*/ } #videoel { -o-transform : scaleX(-1); -webkit-transform : scaleX(-1); transform : scaleX(-1); -ms-filter : fliph; /*IE*/ filter : fliph; /*IE*/ } #container { position : relative; width : 370px; /*margin : 0px auto;*/ } #content { margin-top : 50px; margin-left : auto; margin-right : auto; max-width: 600px; } h2 { font-weight : 400; } .btn { font-family: 'Lato'; font-size: 16px; } #controls { text-align : center; } /* d3 */ .bar { fill : steelblue; fill-opacity : .9; } #emotion_chart { text-align : center; } </style> <script> // getUserMedia only works over https in Chrome 47+, so we redirect to https. Also notify user if running from file. if (window.location.protocol == "file:") { alert("You seem to be running this example directly from a file. Note that these examples only work when served from a server or localhost due to canvas cross-domain restrictions."); } else if (window.location.hostname !== "localhost" && window.location.protocol !== "https:"){ window.location.protocol = "https"; } </script> <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-32642923-1']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> </head> <body> <script src="./js/libs/utils.js"></script> <script src="../build/clmtrackr.js"></script> <script src="../models/model_pca_20_svm.js"></script> <script src="./js/libs/Stats.js"></script> <script src="./js/libs/d3.min.js"></script> <script src="./js/emotion_classifier.js"></script> <script src="./js/gendermodel.js"></script> <div id="content"> <h2>Gender detection example</h2> <p>This a test of gender detection based on parameter output from <em>clmtrackr</em>.</p> <div id="container"> <video id="videoel" width="400" height="300" preload="auto" loop playsinline autoplay> </video> <canvas id="overlay" width="400" height="300"></canvas> </div> <div id="emotion_container"> <div id='emotion_chart'></div> </div> <div id="controls"> <input class="btn" type="button" value="wait, loading video" disabled="disabled" onclick="startVideo()" id="startbutton"></input> </div> <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> var vid = document.getElementById('videoel'); var vid_width = vid.width; var vid_height = vid.height; var overlay = document.getElementById('overlay'); var overlayCC = overlay.getContext('2d'); /********** check and set up video/webcam **********/ function enablestart() { var startbutton = document.getElementById('startbutton'); startbutton.value = "start"; startbutton.disabled = null; } var insertAltVideo = function(video) { if (supports_video()) { if (supports_webm_video()) { video.src = "./media/cap12_edit.webm"; } else if (supports_h264_baseline_video()) { video.src = "./media/cap12_edit.mp4"; } else { return false; } return true; } else return false; } function adjustVideoProportions() { // resize overlay and video if proportions are not 4:3 // keep same height, just change width var proportion = vid.videoWidth/vid.videoHeight; vid_width = Math.round(vid_height * proportion); vid.width = vid_width; overlay.width = vid_width; } function gumSuccess( stream ) { // add camera stream if getUserMedia succeeded if ("srcObject" in vid) { vid.srcObject = stream; } else { vid.src = (window.URL && window.URL.createObjectURL(stream)); } vid.onloadedmetadata = function() { adjustVideoProportions(); vid.play(); } vid.onresize = function() { adjustVideoProportions(); if (trackingStarted) { ctrack.stop(); ctrack.reset(); ctrack.start(vid); } } } function gumFail() { // fall back to video if getUserMedia failed insertAltVideo(vid); alert("There was some problem trying to fetch video from your webcam. If you have a webcam, please make sure to accept when the browser asks for access to your webcam."); } navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; window.URL = window.URL || window.webkitURL || window.msURL || window.mozURL; // check for camerasupport if (navigator.mediaDevices) { navigator.mediaDevices.getUserMedia({video : true}).then(gumSuccess).catch(gumFail); } else if (navigator.getUserMedia) { navigator.getUserMedia({video : true}, gumSuccess, gumFail); } else { insertAltVideo(vid); alert("This demo depends on getUserMedia, which your browser does not seem to support. :("); } vid.addEventListener('canplay', enablestart, false); /*********** setup of emotion detection *************/ // set eigenvector 9 and 11 to not be regularized. This is to better detect motion of the eyebrows pModel.shapeModel.nonRegularizedVectors.push(9); pModel.shapeModel.nonRegularizedVectors.push(11); var ctrack = new clm.tracker({useWebGL : true}); ctrack.init(pModel); var trackingStarted = false; function startVideo() { // start video vid.play(); // start tracking ctrack.start(vid); trackingStarted = true; // start loop to draw face drawLoop(); } var gender = undefined; function drawLoop() { requestAnimFrame(drawLoop); overlayCC.clearRect(0, 0, vid_width, vid_height); //psrElement.innerHTML = "score :" + ctrack.getScore().toFixed(4); if (ctrack.getCurrentPosition()) { ctrack.draw(overlay); } var cp = ctrack.getCurrentParameters(); var er = ec.meanPredict(cp); if (er) { updateData(er); } } var ec = new emotionClassifier(); ec.init(emotionModel); var emotionData = ec.getBlank(); /************ d3 code for barchart *****************/ var margin = {top : 20, right : 40, bottom : 10, left : 40}, width = 200 - margin.left - margin.right, height = 100 - margin.top - margin.bottom; var barWidth = 30; var formatPercent = d3.format(".0%"); var x = d3.scale.linear() .domain([0, ec.getEmotions().length-1]).range([margin.left-barWidth/2, width+margin.left-barWidth/2]); var y = d3.scale.linear() .domain([0,1]).range([0, height]); var svg = d3.select("#emotion_chart").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) svg.selectAll("rect"). data(emotionData). enter(). append("svg:rect"). attr("x", function(datum, index) { return x(index); }). attr("y", function(datum) { return height - y(datum.value); }). attr("height", function(datum) { return y(datum.value); }). attr("width", barWidth). attr("fill", "#2d578b"); svg.selectAll("text.labels"). data(emotionData). enter(). append("svg:text"). attr("x", function(datum, index) { return x(index) + barWidth; }). attr("y", function(datum) { return height - y(datum.value); }). attr("dx", -barWidth/2). attr("dy", "1.2em"). attr("text-anchor", "middle"). text(function(datum) { return datum.value;}). attr("fill", "white"). attr("class", "labels"); svg.selectAll("text.yAxis"). data(emotionData). enter().append("svg:text"). attr("x", function(datum, index) { return x(index) + barWidth; }). attr("y", height). attr("dx", -barWidth/2). attr("text-anchor", "middle"). attr("style", "font-size: 12"). text(function(datum) { return datum.emotion;}). attr("transform", "translate(0, 18)"). attr("class", "yAxis"); function updateData(data) { // update var rects = svg.selectAll("rect") .data(data) .attr("y", function(datum) { return height - y(datum.value); }) .attr("height", function(datum) { return y(datum.value); }); var texts = svg.selectAll("text.labels") .data(data) .attr("y", function(datum) { return height - y(datum.value); }) .text(function(datum) { return datum.value.toFixed(1);}); // enter rects.enter().append("svg:rect"); texts.enter().append("svg:text"); // exit rects.exit().remove(); texts.exit().remove(); } /******** stats ********/ stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; document.getElementById('container').appendChild( stats.domElement ); // update stats on every iteration document.addEventListener('clmtrackrIteration', function(event) { stats.update(); }, false); </script> </div> </body> </html>