<!DOCTYPE html> <html> <head> <script src="https://download.affectiva.com/js/3.2.1/affdex.js"></script> <script> /* * Must run on a remote server, and access via https not http. */ // Make this global so callback functions can access var detector window.onload = function () { // SDK Needs to create video and canvas nodes in the DOM in order to function // Here we are adding those nodes a predefined div. let divRoot = document.getElementById("affdex_elements") let width = 640; let height = 480; //Construct a CameraDetector and specify the image width / height and face detector mode. detector = new affdex.CameraDetector(divRoot, width, height, affdex.FaceDetectorMode.LARGE_FACES); //*1 Set up detector //Enable detection of all Expressions, Emotions and Emojis classifiers. detector.detectAllEmotions(); //*1 detector.detectAllExpressions(); //*1 detector.detectAllEmojis(); //*1 detector.detectAllAppearance(); //*1 //Add a callback to notify when the detector is initialized and ready for runing. detector.addEventListener("onInitializeSuccess", function() { log("logs", "The detector reports initialized"); //Display canvas instead of video feed because we want to draw the feature points on it document.getElementById("face_video_canvas").style.display = "block"; document.getElementById("face_video").style.display = "none"; }); //Add a callback to notify when camera access is allowed detector.addEventListener("onWebcamConnectSuccess", function() { log("logs", "Webcam access allowed"); }); //Add a callback to notify when camera access is denied detector.addEventListener("onWebcamConnectFailure", function() { log("logs", "webcam denied"); console.log("Webcam access denied"); }); //Add a callback to notify when detector is stopped detector.addEventListener("onStopSuccess", function() { log("logs", "The detector reports stopped"); document.getElementById("results").innerHTML = "" }); //Add a callback to receive the results from processing an image. //The faces object contains the list of the faces detected in an image. //Faces object contains probabilities for all the different expressions, emotions and appearance metrics detector.addEventListener("onImageResultsSuccess", function(faces, image, timestamp) { //*2 Callback when get results document.getElementById("results").innerHTML = "" log("results", "Timestamp: " + timestamp.toFixed(2)); //*2 if (faces.length > 0) { log("results", "Appearance: " + JSON.stringify(faces[0].appearance)); //*2 log("results", "Emotions: " + JSON.stringify(faces[0].emotions, function(key, val) { //*2 return val.toFixed ? Number(val.toFixed(0)) : val; })); log("results", "Expressions: " + JSON.stringify(faces[0].expressions, function(key, val) { //*2 return val.toFixed ? Number(val.toFixed(0)) : val; })); log("results", "Emoji: " + faces[0].emojis.dominantEmoji); //*2 drawFeaturePoints(image, faces[0].featurePoints); // Primitive text UI for happy if (faces[0].emotions["joy"]>75) { //*3 Primitive text UI document.getElementById("myuitext").innerHTML = "Happy!!!" //*3 } else { //*3 document.getElementById("myuitext").innerHTML = "" //*3 } // Now update the graphic UI let c = document.getElementById ("myuicanvas"); //*4 Graphic UI let gc = c.getContext("2d") gc.clearRect (0, 0, c.width, c.height); // Background gc.fillStyle = "lightblue" //*4 gc.beginPath() gc.rect(0, 0, c.width, c.height) //*4 gc.fill() //*4 gc.closePath() // Ball rises/falls based on amount of smile let rad = 50; let y = c.height - rad - faces[0].expressions["smile"] * (c.height - 2 * rad) / 100 //*5 Compute ball height from smile // Draw the ball at appropriate y height gc.fillStyle = "red" //*6 Draw ball gc.beginPath() //*6 gc.arc(c.width/2, y, rad, 0, 2*Math.PI); //*6 gc.fill() //*6 gc.closePath() //*6 } }); //Draw the detected facial feature points on the image function drawFeaturePoints(img, featurePoints) { let c = document.getElementById("face_video_canvas"); if (c==null) return; let contxt = c.getContext('2d'); let hRatio = contxt.canvas.width / img.width; let vRatio = contxt.canvas.height / img.height; let ratio = Math.min(hRatio, vRatio); contxt.strokeStyle = "#FFFFFF"; for (let id in featurePoints) { contxt.beginPath(); contxt.arc(featurePoints[id].x, featurePoints[id].y, 2, 0, 2 * Math.PI); contxt.stroke(); } } } //function executes when Start button is pushed. function onStart() { if (detector && !detector.isRunning) { document.getElementById("results").innerHTML = "" document.getElementById("logs").innerHTML = "" detector.start(); } log("logs", "Clicked the start button"); } //function executes when the Stop button is pushed. function onStop() { log("logs", "Clicked the stop button"); if (detector && detector.isRunning) { detector.removeEventListener(); detector.stop(); } }; //function executes when the Reset button is pushed. function onReset() { log("logs", "Clicked the reset button"); if (detector && detector.isRunning) { detector.reset(); document.getElementById("results").innerHTML = "" } } function log (node_name, msg) { document.getElementById(node_name).innerHTML += "<span>" + msg + "</span><br/>" } </script> </head> <body> <div> <div> <button id="start" onclick="onStart()">Start</button> <button id="stop" onclick="onStop()">Stop</button> <button id="reset" onclick="onReset()">Reset</button> <h3>Affectiva JS SDK CameraDetector to track different emotions.</h3> <p> <strong>Instructions</strong> </br> Press the start button to start the detector. <br/> When a face is detected, the probabilities of the different emotions are written to the DOM. <br/> Press the stop button to end the detector. </p> </div> <div> <div id="affdex_elements" style="width:680px;height:480px;"></div> <div> <div> <br/><br/> <strong>Example text and graphic UIs</strong> <br/><br/> <div id="myuitext" style="color:red;"></div> <br/><br/> <canvas id="myuicanvas" width="300" height="300"></canvas> <br/><br/> </div> </div> <div style="height:25em;"> <strong>Emotion Tracking Results</strong> <div id="results" style="word-wrap:break-word;"></div> </div> <div> <strong>Detector Log Msgs</strong> <div id="logs"></div> </div> </div> </div </body> </html>