-
-
Save haruiz/c1c270644e61bdf213290136504a556c to your computer and use it in GitHub Desktop.
index.html code post: Microsoft Cognitive Services Notes: Face API (Node.js)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html xmlns="http://www.w3.org/1999/xhtml"> | |
<head> | |
<meta charset="utf-8" /> | |
<title></title> | |
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" type="text/css" rel="stylesheet"/> | |
<style> | |
</style> | |
</head> | |
<body> | |
<div class="panel panel-default"> | |
<div class="panel-body text-center"> | |
<input id="file" class="center-block" type="file" name="file"><br /> | |
<div class="btn-group"> | |
<button type="button" action="faces" class="btn btn-primary">Detect Faces</button> | |
<button type="button" action="landmarks" class="btn btn-primary">Draw Landmarks</button> | |
<button type="button" action="fun" class="btn btn-primary">Fun Photo</button> | |
</div> | |
<br /> | |
<br /> | |
<canvas id="c" class="center-block" width="800" height="600" style="background-color:aliceblue"></canvas> | |
<br /> | |
</div> | |
</div> | |
<div class="row"> | |
<div class="panel-body"> | |
<div class="panel-heading">Api Response</div> | |
<div class="panel-body" style="padding:20px;"> | |
<pre id="txtCode"> </pre> | |
</div> | |
</div> | |
</div> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> | |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" type="text/javascript"></script> | |
<script type="text/javascript"> | |
var canvas = document.getElementById("c"); | |
var ctx = canvas.getContext("2d"); | |
var preferedSize = { w: 800, h: 600}; | |
//calcular la distancia entre 2 puntos | |
function getDistanceBetwen2Points(x1, y1, x2, y2) { | |
var a = x1 - x2 | |
var b = y1 - y2 | |
var c = Math.sqrt(a * a + b * b); | |
return c; | |
} | |
//evalua el angulo entre 2 puntos, esta funcion es util para obtener | |
//la orientaci'on de cada uno de los rostros y ubicar los accesories | |
//en la posici'on correcta | |
function calcularAngleBetwen2Points(pt1, pt2) { | |
var deltaY = pt2.y - pt1.y; | |
var deltaX = pt2.x - pt1.x; | |
var angle = Math.atan2(deltaY, deltaX); | |
return angle; | |
} | |
//dibujar un punto | |
function drawPoint(x, y, ctx) { | |
ctx.beginPath(); ctx.arc(x, y, 2, 0, 2 * Math.PI, true); ctx.fill(); | |
} | |
function drawLine(x1, y1, x2, y2, ctx) { | |
ctx.strokeStyle = '#DF0174'; | |
ctx.beginPath(); | |
ctx.moveTo(x1, y1); | |
ctx.lineTo(x2, y2); | |
ctx.stroke(); | |
} | |
function drawPolygon(poly, ctx) { | |
ctx.fillStyle = '#DF0174'; | |
ctx.beginPath(); | |
ctx.moveTo(poly[0], poly[1]); | |
for (var item = 2 ; item < poly.length - 1 ; item += 2) { | |
ctx.lineTo(poly[item], poly[item + 1]) | |
} | |
ctx.closePath(); | |
ctx.globalAlpha = 0.8; | |
ctx.fill(); | |
} | |
//encierra con un rectangulo cada rostro detectado | |
function drawFace(face) { | |
var rec = face.faceRectangle; | |
ctx.fillStyle = '#DF0174'; | |
ctx.globalAlpha = 0.3; | |
ctx.fillRect(rec.left, rec.top, rec.width, rec.height); | |
ctx.globalAlpha = 1; | |
drawPoint(rec.left, rec.top, ctx); | |
drawPoint(rec.left + rec.width, rec.top, ctx); | |
drawPoint(rec.left, rec.top + rec.height, ctx); | |
drawPoint(rec.left + rec.width, rec.top + rec.height, ctx); | |
ctx.strokeStyle = 'red'; | |
ctx.fillStyle = '#DF0174'; | |
ctx.font = "20px Arial"; | |
ctx.stroke(); | |
} | |
//este me'todo obtiene la posici'on de cada rostro y algunos puntos de interes | |
//y sobrepone sobre cada uno (en la imagen), las gafas, el cigarro y la gorra, aprovechando | |
//las bondades de html5 (se puede mejorar) | |
function drawFun(face) { | |
var faceRectangle = face.faceRectangle; | |
var faceLandmarks = face.faceLandmarks; | |
//ctx.fillStyle = '#DF0174'; | |
//drawPoint(faceLandmarks.pupilLeft.x, faceLandmarks.pupilLeft.y, ctx); | |
//drawPoint(faceLandmarks.pupilRight.x, faceLandmarks.pupilRight.y, ctx); | |
//drawPoint(faceLandmarks.eyebrowLeftOuter.x, faceLandmarks.eyebrowLeftOuter.y, ctx); | |
//drawPoint(faceLandmarks.eyebrowRightOuter.x, faceLandmarks.eyebrowRightOuter.y, ctx); | |
var pt1 = { x: faceLandmarks.eyebrowLeftOuter.x, y: faceLandmarks.eyebrowLeftOuter.y }; | |
var pt2 = { x: faceLandmarks.eyebrowRightOuter.x, y: faceLandmarks.eyebrowRightOuter.y }; | |
var d = getDistanceBetwen2Points(pt1.x, pt1.y, pt2.x, pt2.y); | |
var deltaY = pt2.y - pt1.y; | |
var deltaX = pt2.x - pt1.x; | |
var angle = Math.atan2(deltaY, deltaX); | |
//solo si la persona no tiene gafas | |
if (face.faceAttributes.glasses == "NoGlasses") { | |
var glasses = new Image(); | |
glasses.src = "public/images/glasses_3.png"; | |
glasses.onload = function () { | |
var aspectRatio = d / this.width; | |
ctx.save(); | |
ctx.translate(pt1.x, pt1.y); | |
ctx.rotate(angle); | |
ctx.translate(-pt1.x, -pt1.y); | |
ctx.drawImage(this, pt1.x, pt1.y, this.width * aspectRatio, this.height * aspectRatio); | |
ctx.restore(); | |
}; | |
} | |
var gorra = new Image(); | |
gorra.src = "public/images/gorra.png"; | |
gorra.onload = function () { | |
var aspectRatio = (faceRectangle.width) / this.width; | |
ctx.save(); | |
ctx.translate(pt1.x, pt1.y); | |
ctx.rotate(angle); | |
ctx.translate(-pt1.x, -pt1.y); | |
ctx.drawImage(this, faceRectangle.left, (faceRectangle.top - faceRectangle.height) + 10, this.width * aspectRatio, this.height * aspectRatio); | |
ctx.restore(); | |
}; | |
var cigarro = new Image(); | |
cigarro.src = "public/images/cigarro.png"; | |
cigarro.onload = function () { | |
var pt1 = { x: faceLandmarks.mouthLeft.x, y: faceLandmarks.mouthLeft.y }; | |
var pt2 = { x: faceLandmarks.mouthRight.x, y: faceLandmarks.mouthRight.y }; | |
var d = getDistanceBetwen2Points(pt1.x, pt1.y, pt2.x, pt2.y); | |
var aspectRatio = d / this.width; | |
ctx.drawImage(this, faceLandmarks.underLipTop.x - d, faceLandmarks.underLipTop.y - 5, d, this.height * aspectRatio); | |
}; | |
var logo = new Image(); | |
logo.src = "public/images/logo.png"; | |
logo.onload = function () { | |
var aspectRatio = 200 / this.width; | |
ctx.drawImage(this, (canvas.width - (this.width * aspectRatio)) - 10, (canvas.height - (this.height * aspectRatio)) - 10, 200, this.height * aspectRatio); | |
}; | |
} | |
function drawLandmarks(face) { | |
var faceLandmarks = face.faceLandmarks; | |
//draw eyebrows | |
drawLine( | |
faceLandmarks.eyebrowLeftOuter.x, | |
faceLandmarks.eyebrowLeftOuter.y, | |
faceLandmarks.eyebrowLeftInner.x, | |
faceLandmarks.eyebrowLeftInner.y | |
, ctx); | |
drawLine( | |
faceLandmarks.eyebrowRightOuter.x, | |
faceLandmarks.eyebrowRightOuter.y, | |
faceLandmarks.eyebrowRightInner.x, | |
faceLandmarks.eyebrowRightInner.y | |
, ctx); | |
//draw eyes | |
drawPolygon([ | |
faceLandmarks.eyeLeftOuter.x, | |
faceLandmarks.eyeLeftOuter.y, | |
faceLandmarks.eyeLeftTop.x, | |
faceLandmarks.eyeLeftTop.y, | |
faceLandmarks.eyeLeftInner.x, | |
faceLandmarks.eyeLeftInner.y, | |
faceLandmarks.eyeLeftBottom.x, | |
faceLandmarks.eyeLeftBottom.y | |
], ctx); | |
drawPolygon([ | |
faceLandmarks.eyeRightOuter.x, | |
faceLandmarks.eyeRightOuter.y, | |
faceLandmarks.eyeRightTop.x, | |
faceLandmarks.eyeRightTop.y, | |
faceLandmarks.eyeRightInner.x, | |
faceLandmarks.eyeRightInner.y, | |
faceLandmarks.eyeRightBottom.x, | |
faceLandmarks.eyeRightBottom.y | |
], ctx); | |
//draw mouth | |
drawPolygon([ | |
faceLandmarks.mouthLeft.x, | |
faceLandmarks.mouthLeft.y, | |
faceLandmarks.upperLipTop.x, | |
faceLandmarks.upperLipTop.y, | |
faceLandmarks.mouthRight.x, | |
faceLandmarks.mouthRight.y, | |
faceLandmarks.underLipBottom.x, | |
faceLandmarks.underLipBottom.y | |
], ctx); | |
//draw Nose | |
drawPolygon([ | |
faceLandmarks.noseRootLeft.x, | |
faceLandmarks.noseRootLeft.y, | |
faceLandmarks.noseLeftAlarTop.x, | |
faceLandmarks.noseLeftAlarTop.y, | |
faceLandmarks.noseLeftAlarOutTip.x, | |
faceLandmarks.noseLeftAlarOutTip.y, | |
faceLandmarks.noseTip.x, | |
faceLandmarks.noseTip.y, | |
faceLandmarks.noseRightAlarOutTip.x, | |
faceLandmarks.noseRightAlarOutTip.y, | |
faceLandmarks.noseRightAlarTop.x, | |
faceLandmarks.noseRightAlarTop.y, | |
faceLandmarks.noseRootRight.x, | |
faceLandmarks.noseRootRight.y | |
], ctx); | |
} | |
//la funcion draw se ejecuta cada vez que hagamos click sobre alguno de los botones | |
//desde la interfaz | |
function draw(apiResponse,action) { | |
var faces = JSON.parse(apiResponse); | |
$("#txtCode").empty().html(JSON.stringify(faces[0], null, ' ')); | |
$.each(faces, function (index, face) { | |
switch(action){ | |
case "faces": drawFace(face); break; | |
case "fun": drawFun(face); break; | |
case "landmarks": drawLandmarks(face); break; | |
} | |
}); | |
} | |
/*toma el contenido del canvas, y lo envía en forma de imagen al server*/ | |
function sendImageToServer(action) { | |
var dataURL = canvas.toDataURL("image/png"); | |
var encodedImage = dataURL.replace(/^data:image\/(png|jpg);base64,/, ""); | |
$.ajax({ | |
url: '/detectfaces', | |
data: { image: encodedImage }, | |
type: 'POST', | |
cache: false, | |
success: function (data) { | |
draw(data, action); | |
}, | |
error: function (err) { | |
console.log(err);//JSON.parse(err.responseText).message); | |
} | |
}); | |
} | |
$("button").click(function (e) { sendImageToServer($(this).attr("action")); }); | |
var handleFileSelect = function (evt) { | |
//obtenemos la lista de archivos cargados | |
var files = evt.target.files; | |
//validamos que el usuario haya seleccionado almenos uno | |
if (files && files.length > 0) { | |
//Accedemos al archivo cargado | |
var blob = files[0]; | |
//Validamos de que sea una imagen | |
if (blob.type.includes("image")) { | |
/*Obtenemos su extension*/ | |
var ext = blob.type.split('/')[1]; | |
//Leemos el contenido de la imagen | |
var reader = new FileReader(); | |
reader.readAsBinaryString(blob); | |
reader.onload = function (ev) { | |
var binaryString = ev.target.result; | |
var base64String = btoa(binaryString); | |
//document.getElementById("base64textarea").value = btoa(binaryString); | |
//visualizamos la imagen | |
var image = new Image(); | |
image.onload = function () { | |
//obtenemos las dimensiones de la imagen | |
var w = this.width; | |
var h = this.height; | |
var aspecRatio = preferedSize.w / w; | |
canvas.width = w * aspecRatio; | |
canvas.height = h * aspecRatio; | |
ctx.clearRect(0, 0, canvas.width, canvas.height); | |
ctx.drawImage(this, 0, 0, w * aspecRatio, h * aspecRatio); | |
}; | |
image.src = "data:"+blob.type+";base64,"+base64String; | |
}; | |
} | |
} | |
}; | |
//chequeamos que el browser se compatible con el API de lectura de archivos | |
if (window.File && window.FileReader && window.FileList && window.Blob) { | |
document.getElementById('file').addEventListener('change', handleFileSelect, false); | |
} else { | |
alert('The File APIs are not fully supported in this browser.'); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment