Animating eyebrows and mouth based on relationship between face points.
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.3/seedrandom.min.js"></script>
<script src="https://d3js.org/d3-random.v1.min.js"></script>
<script src="z_clmtrackr.js"></script>
<script src="z_model_pca_20_svm.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="z_focused_random.js"></script>
<script language="javascript" type="text/javascript" src="z_face_system.js"></script>
<script language="javascript" type="text/javascript" src="z_kdTree.js"></script>
<script language="javascript" type="text/javascript" src="z_face-api.js"></script>
<script language="javascript" type="text/javascript" src="z_training_images.js"></script>
<script language="javascript" type="text/javascript" src="z_testing_images.js"></script>
<script language="javascript" type="text/javascript" src="face.js"></script>
<script language="javascript" type="text/javascript" src="system_runner.js"></script>
<style>
body { padding: 0; margin: 0; }
.inner { position: absolute; }
#controls {
font: 300 12px "Helvetica Neue";
padding: 5;
margin: 5;
background: #f0f0f0;
opacity: 0.0;
-webkit-transition: opacity 0.2s ease;
-moz-transition: opacity 0.2s ease;
-o-transition: opacity 0.2s ease;
-ms-transition: opacity 0.2s ease;
}
#controls:hover { opacity: 0.9; }
</style>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner" id="controls" height="500">
<table>
<tr>
<td>setting 1</td>
<td id="slider1Container"></td>
</tr>
<tr>
<td>setting 2</td>
<td id="slider2Container"></td>
</tr>
<tr>
<td>setting 3</td>
<td id="slider3Container"></td>
</tr>
<tr>
<td>setting 4</td>
<td id="slider4Container"></td>
</tr>
<tr>
<td>setting 5</td>
<td id="slider5Container"></td>
</tr>
<tr>
<td>setting 6</td>
<td id="slider6Container"></td>
</tr>
<tr>
<td>setting 7</td>
<td id="slider7Container"></td>
</tr>
<tr>
<td>setting 8</td>
<td id="slider8Container"></td>
</tr>
<!-- YOU CAN ADD MORE SLIDERS HERE, LIKE THIS
<tr>
<td>setting 9</td>
<td id="slider9Container"></td>
</tr>
<tr>
<td>setting 10</td>
<td id="slider10Container"></td>
</tr>
<tr>
<td>setting 11</td>
<td id="slider11Container"></td>
</tr>
<tr>
<td>setting 12</td>
<td id="slider12Container"></td>
</tr>
... AND KEEP GOING
-->
<tr>
</tr>
<tr>
<td>show target</td>
<td id="sliderTintContainer"></td>
</tr>
<tr>
<td>Draw function</td>
<td id="selector1Container"></td>
</tr>
<tr>
<td>Face Draw</td>
<td id="checkbox1Container"></td>
</tr>
<tr>
<td>Face Targets</td>
<td id="checkbox2Container"></td>
</tr>
<tr>
<td>Face Points</td>
<td id="checkbox3Container"></td>
</tr>
<tr>
<td></td>
<td id="button1Container"></td>
</tr>
<tr>
<td></td>
<td id="button2Container"></td>
</tr>
<tr>
<td></td>
<td id="button3Container"></td>
</tr>
<tr>
<td></td>
<td id="button4Container"></td>
</tr>
</table>
</div>
<div>
<div id="canvasContainer"></div>
<a href="face.js">face code</a><br>
<a href="sketch.html">sketches</a>
</div>
</div>
<pre>
<p id="output">
</p>
</pre>
</body>
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
// var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
var NUM_SLIDERS = 8;
// other variables can be in here too
// these control the colors used
const bg_color = [225, 206, 187];
const fg_color = [151, 102, 52];
const stroke_color = [95, 52, 8];
function Face() {
// these are state variables for a face
// (your variables may be different)
this.bread = 3; // 1-5
this.jam = 5; // 0-10
/*
* Draw a face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
// let bread = int(map(s1, 0, 100, 1, 5));
// let mouth = map(s2, 0, 100, 0, 10);
// let blush = map(s3, 0, 100, 0, 10);
// let jam = map(s4, 0, 100, 0, 10);
// let jam_col = map(s5, 0, 100, 0, 10);
// let jam_size = int(map(s6, 0, 100, 0, 10));
// let eyebrows_rotate = map(s7, 0, 100, 0, 20);
// let glasses = int(map(s8, 0, 100, 0, 10));
// let pupil = int(map(s9, 0, 100, 1, 10));
let bread = this.bread;
let mouth = 5;
let blush = 5;
let jam = this.jam;
let jam_col = 5;
let jam_size = 5;
let eyebrows_rotate=10;
let glasses = 5;
let pupil = 5;
// Colour Sets
let bread1 = '#fffaf5';
let bread2 = '#f5f2ea';
let bread3 = '#dbb58c';
let bread4 = '#c48d52';
let bread5 = '#36210d';
let breadColour;
let left_eye = average_point(positions.left_eye);
let right_eye = average_point(positions.right_eye);
let left_eyebrow = average_point(positions.left_eyebrow);
let right_eyebrow = average_point(positions.right_eyebrow);
let left_d = dist(left_eye[0], left_eye[1], left_eyebrow[0], left_eyebrow[1]);
let right_d = dist(right_eye[0], right_eye[1], right_eyebrow[0], right_eyebrow[1]);
let left_eb_move = map(left_d, 0.4, 0.7, 0, 2, true);
let right_eb_move = map(right_d, 0.4, 0.7, 0, 2, true);
// print(left_d);
left_eye[0] *= 3;
left_eye[1] *= 3;
right_eye[0] *= 3;
right_eye[1] *= 3;
push();
scale(0.33);
// Bread (Brown)
fill(221,168,128);
strokeWeight(0.3);
stroke(0);
beginShape();
vertex(-6.45, -5);
quadraticVertex(-4, -8, -0.5, -6);
quadraticVertex(3.5, -9, 6.5, -5.6);
quadraticVertex(7.8, -3.8, 6.5, -1.5);
quadraticVertex(6.8, 3, 6.3, 5.5);
quadraticVertex(6, 6, 5.1, 6.5);
endShape();
// Bread Colour
if(bread == 1){
breadColour = bread1; //***ALMOST WHITE***//
}else if (bread == 2){
breadColour = bread2; //***IVORY***//
}else if (bread == 3){
breadColour = bread3; //***WELL DONE***//
}else if (bread == 4){
breadColour = bread4; //***OVERCOOKED***//
}else{
breadColour = bread5; //***BURNT***//
}
fill(breadColour);
strokeWeight(0.3);
stroke(0);
rect(-6, -4.5, 11, 11);
push();
angleMode(RADIANS);
arc(-3.9, -3, 6.8, 6, -4, -0.4);
arc(2.4, -3.2, 6.8, 6, -2.8, 0.65);
pop();
// Jam (Colour, Spread)
let amount = map(jam_col, 0, 10, 0, 1);
let colourPink = color('#ed3267');
let colourPurple = color('#edd532');
let jamColour = lerpColor(colourPink, colourPurple, amount);
let jamSpread = map(jam, 0, 100, 0, 100);
let jamS = map(jam_size, 0, 100, 1.3, 15);
strokeWeight(jamS);
stroke(jamColour);
if (jamSpread == 0){
}
if (jamSpread >= 2){
line(-3.5, -2, 2.5, -3);
}
if (jamSpread >=4){
line(2.5, -3, -3, 1);
}
if (jamSpread >=6){
line(-3, 1, 2, 0);
}
if (jamSpread >=8){
line(2, 0, -3.5, 4);
}
if (jamSpread >=10){
line(-3.5, 4, 2.5, 3);
}
// Mouth
strokeWeight(0.4);
stroke(0);
line(-1.55, -1, -0.05, -1);
let top_lip_point = positions.top_lip[9];
let bottom_lip_point = positions.bottom_lip[9];
// fill(255, 0, 0);
let d = dist(top_lip_point[0], top_lip_point[1], bottom_lip_point[0], bottom_lip_point[1])
// print(d);
// Mouth Open
if(d < 0.1) {
d = 0;
}
mouth = map(d, 0, 0.5, 0, 10);
let mouth_size = map(mouth, 0, 10, 0, 3.5);
strokeWeight(0.3);
fill('#fffcf7');
rect(-1.6, -1, 1.6, mouth_size, 0.08);
/*
push();
scale(5);
noStroke();
textSize(0.2);
for (let i=0; i<positions.bottom_lip.length; i++) {
let p = positions.bottom_lip[i]
fill(255, 0, 0);
ellipse(p[0], p[1], 0.2);
fill(0);
text(i, p[0], p[1]);
}
pop();
push();
scale(5);
noStroke();
textSize(0.2);
for (let i=0; i<positions.top_lip.length; i++) {
let p = positions.top_lip[i]
fill(0, 0, 255);
ellipse(p[0], p[1], 0.2);
fill(0);
text(i, p[0], p[1]);
}
pop();
*/
// Blush
noStroke();
if (blush > 3 && blush < 6){ //***PINK BLUSH***//
fill('#ff87b1');
ellipse(-2.6, -1.1, 1.5, 0.8);
ellipse(1.1, -1.1, 1.5, 0.8);
}
else if (blush > 5 && blush <= 8){ //***RED BLUSH***//
stroke('#bf304d');
strokeWeight(0.2);
line(-3.5, -0.9, -3.2, -1.2); //***LEFT***//
line(-2.9, -0.9, -2.6, -1.2);
line(-2.3, -0.9, -2, -1.2);
line(0.5, -0.9, 0.8, -1.2); //***RIGHT***//
line(1.1, -0.9, 1.4, -1.2);
line(1.7, -0.9, 2, -1.2);
}
else if (blush >7 && blush <= 10){ //***TEARS***//
noStroke();
fill('#49a3e6');
triangle(-3.3, -1.19, -2.9, -0.85, -2.75, -1.55);
ellipse(-3.2, -0.9, 0.6, 0.6);
triangle(1.81, -1.24, 1.36, -0.87, 1.2, -1.7);
ellipse(1.65, -1, 0.6, 0.6);
}
// Eyes
noStroke();
fill(0);
// ellipse(-2.2, -2, 1.1, 1.1);
// ellipse(0.5, -2, 1.1, 1.1);
ellipse(left_eye[0], left_eye[1], 1.1, 1.1);
ellipse(right_eye[0], right_eye[1], 1.1, 1.1);
// Pupil
if (pupil > 3 && pupil < 6) {
fill('black');
ellipse(left_eye[0]-0.1, left_eye[1]-0.1, 0.3, 0.3); //***LEFT TOP***//
ellipse(left_eye[0]+0.15, left_eye[1]+0.1, 0.2, 0.2); //***LEFT BOTTOM***//
ellipse(left_eye[0]-0.1, left_eye[1]-0.1, 0.3, 0.3); //***RIGHT TOP***//
ellipse(left_eye[0]+0.15, left_eye[1]+0.1, 0.2, 0.2); //***RIGHT BOTTOM***//
// ellipse(-2.3, -2.1, 0.3, 0.3); //***LEFT TOP***//
// ellipse(-2.05, -1.9, 0.2, 0.2); //***LEFT BOTTOM***//
// ellipse(0.4, -2.1, 0.3, 0.3); //***RIGHT TOP***//
// ellipse(0.65, -1.9, 0.2, 0.2); //***RIGHT BOTTOM***//
}
else if (pupil > 5 && pupil <= 10) {
// fill('white');
// ellipse(-2.3, -2.1, 0.3, 0.3); //***LEFT TOP***//
// ellipse(-2.05, -1.9, 0.2, 0.2); //***LEFT BOTTOM***//
// ellipse(0.4, -2.1, 0.3, 0.3); //***RIGHT TOP***//
// ellipse(0.65, -1.9, 0.2, 0.2); //***RIGHT BOTTOM***//
}
// Eyebrows
strokeWeight(0.4);
stroke(0);
push();
angleMode(DEGREES);
translate(left_eye[0]-0.1, left_eye[1]-1);
translate(0, -left_eb_move);
rotate(eyebrows_rotate);
line(-0.3, 0, 0.5, 0);
pop();
push();
angleMode(DEGREES);
translate(right_eye[0]-0.2, right_eye[1]-1);
translate(0, -right_eb_move);
rotate(-eyebrows_rotate);
line(-0.3, 0, 0.5, 0);
pop();
// Glasses
if (glasses > 5 && glasses < 8){
stroke(0);
strokeWeight(0.35);
noFill();
ellipse(-2.3, -2.4, 2.6, 2.6);
ellipse(0.6, -2.4, 2.6, 2.6);
}
// Sunglasses
else if (glasses > 7 && glasses <= 10){
stroke(0);
strokeWeight(0.3);
fill('white');
ellipse(-2.6, -2.4, 3, 2.6);
ellipse(1, -2.4, 3, 2.6);
noStroke();
fill('black');
ellipse(-2.6, -2.37, 2.4, 2);
ellipse(1, -2.37, 2.4, 2);
stroke(0);
strokeWeight(0.3);
line(-1.1, -2.5, -0.65, -2.5);
}
pop();
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.bread = int(map(settings[0], 0, 100, 1, 5));
this.jam = int(map(settings[1], 0, 100, 0, 10));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(2);
settings[0] = map(this.bread, 1, 5, 0, 100);
settings[1] = map(this.jam, 0, 10, 0, 100);
return settings;
}
}
// given an array of [x,y] points, return the average
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for(var i=0; i<list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
[
"five_faces.jpg",
"williams.jpg",
"oscar_selfie.jpg"
]
<head>
<style> body {padding: 0; margin: 0;} </style>
</head>
<body style="background-color:white">
<img src="same_pose.jpg" width="960" height="500"/><br>
Same Pose
<hr>
<img src="same_subject.jpg" width="960" height="500"/><br>
Same Subject
<p>
<a href="index.html">program</a>
</body>
{
"000001": [
0,
100
],
"000002": [
0,
100
],
"000005": [
0,
100
],
"000006": [
50,
100
],
"000007": [
25,
0
],
"000009": [
25,
100
],
"000010": [
25,
100
],
"000013": [
25,
0
],
"000014": [
75,
100
],
"000015": [
25,
0
],
"000016": [
25,
0
],
"000018": [
25,
100
],
"000020": [
25,
0
],
"000023": [
25,
0
],
"000025": [
25,
0
],
"000028": [
25,
100
],
"000029": [
25,
100
],
"000030": [
25,
0
],
"000031": [
0,
100
],
"000032": [
0,
0
],
"000035": [
0,
100
],
"000037": [
50,
0
],
"000038": [
0,
0
],
"000040": [
0,
90
],
"000041": [
0,
0
],
"000042": [
0,
100
],
"000043": [
0,
100
],
"000044": [
50,
100
],
"000045": [
0,
100
],
"000047": [
50,
100
],
"000048": [
0,
0
],
"000050": [
0,
0
],
"000051": [
0,
0
],
"000052": [
0,
0
],
"000054": [
0,
100
],
"000055": [
0,
0
],
"000056": [
0,
100
],
"000058": [
0,
100
],
"000060": [
100,
0
],
"000064": [
0,
0
],
"000065": [
50,
0
],
"000068": [
0,
0
],
"000069": [
0,
0
],
"000071": [
0,
100
],
"000073": [
0,
100
],
"000076": [
0,
0
],
"000077": [
0,
100
],
"000078": [
50,
100
],
"000079": [
0,
0
],
"000080": [
0,
0
],
"000081": [
0,
0
],
"000083": [
0,
100
],
"000085": [
0,
100
],
"000086": [
25,
100
],
"000088": [
0,
100
],
"000091": [
0,
0
],
"000092": [
0,
100
],
"000096": [
0,
100
],
"000097": [
0,
100
],
"000099": [
25,
100
],
"000100": [
0,
100
],
"000103": [
25,
100
],
"000104": [
25,
0
],
"000106": [
25,
0
],
"000108": [
25,
100
],
"000109": [
0,
0
],
"000110": [
25,
100
],
"000111": [
50,
100
],
"000114": [
0,
0
],
"000115": [
25,
0
],
"000116": [
0,
0
],
"000117": [
100,
100
],
"000118": [
25,
100
],
"000121": [
25,
100
],
"000122": [
0,
100
],
"000125": [
0,
0
],
"000126": [
0,
100
],
"000129": [
0,
0
],
"000131": [
25,
100
],
"000132": [
50,
100
],
"000133": [
0,
100
],
"000134": [
100,
0
],
"000135": [
75,
0
],
"000137": [
0,
0
],
"000140": [
0,
100
],
"000142": [
0,
100
],
"000143": [
0,
0
],
"000145": [
0,
100
],
"000146": [
0,
100
],
"000147": [
0,
100
],
"000148": [
0,
100
],
"000150": [
0,
0
],
"000151": [
50,
70
],
"000152": [
0,
0
],
"000153": [
0,
0
],
"000155": [
25,
100
],
"000156": [
0,
100
],
"000157": [
0,
100
],
"000160": [
0,
0
],
"000161": [
0,
90
]
}
[{"weights":[{"name":"dense0/conv0/filters","shape":[3,3,3,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004853619781194949,"min":-0.5872879935245888}},{"name":"dense0/conv0/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004396426443960153,"min":-0.7298067896973853}},{"name":"dense0/conv1/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00635151559231328,"min":-0.5589333721235686}},{"name":"dense0/conv1/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009354315552057004,"min":-1.2628325995276957}},{"name":"dense0/conv1/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0029380727048013726,"min":-0.5846764682554731}},{"name":"dense0/conv2/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0049374802439820535,"min":-0.6171850304977566}},{"name":"dense0/conv2/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009941946758943446,"min":-1.3421628124573652}},{"name":"dense0/conv2/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0030300481062309416,"min":-0.5272283704841838}},{"name":"dense0/conv3/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005672684837790097,"min":-0.7431217137505026}},{"name":"dense0/conv3/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010712201455060173,"min":-1.5639814124387852}},{"name":"dense0/conv3/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0030966934035806097,"min":-0.3839899820439956}},{"name":"dense1/conv0/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0039155554537679636,"min":-0.48161332081345953}},{"name":"dense1/conv0/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01023082966898002,"min":-1.094698774580862}},{"name":"dense1/conv0/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0027264176630506327,"min":-0.3871513081531898}},{"name":"dense1/conv1/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004583378632863362,"min":-0.5454220573107401}},{"name":"dense1/conv1/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00915846403907327,"min":-1.117332612766939}},{"name":"dense1/conv1/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003091680419211294,"min":-0.5966943209077797}},{"name":"dense1/conv2/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005407439727409214,"min":-0.708374604290607}},{"name":"dense1/conv2/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00946493943532308,"min":-1.2399070660273235}},{"name":"dense1/conv2/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004409168514550901,"min":-0.9788354102303}},{"name":"dense1/conv3/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004478132958505668,"min":-0.6493292789833219}},{"name":"dense1/conv3/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.011063695888893277,"min":-1.2501976354449402}},{"name":"dense1/conv3/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003909627596537272,"min":-0.6646366914113363}},{"name":"dense2/conv0/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003213915404151468,"min":-0.3374611174359041}},{"name":"dense2/conv0/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010917326048308728,"min":-1.4520043644250609}},{"name":"dense2/conv0/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002800439152063108,"min":-0.38085972468058266}},{"name":"dense2/conv1/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0050568851770139206,"min":-0.6927932692509071}},{"name":"dense2/conv1/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01074961213504567,"min":-1.3222022926106174}},{"name":"dense2/conv1/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0030654204242369708,"min":-0.5487102559384177}},{"name":"dense2/conv2/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00591809165244009,"min":-0.917304206128214}},{"name":"dense2/conv2/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01092823346455892,"min":-1.366029183069865}},{"name":"dense2/conv2/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002681120470458386,"min":-0.36463238398234055}},{"name":"dense2/conv3/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0048311497650894465,"min":-0.5797379718107336}},{"name":"dense2/conv3/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.011227761062921263,"min":-1.4483811771168429}},{"name":"dense2/conv3/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0034643323982463162,"min":-0.3360402426298927}},{"name":"dense3/conv0/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003394978887894574,"min":-0.49227193874471326}},{"name":"dense3/conv0/pointwise_filter","shape":[1,1,128,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010051267287310432,"min":-1.2765109454884247}},{"name":"dense3/conv0/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003142924752889895,"min":-0.4588670139219247}},{"name":"dense3/conv1/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00448304671867221,"min":-0.5872791201460595}},{"name":"dense3/conv1/pointwise_filter","shape":[1,1,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.016063522357566685,"min":-2.3613377865623026}},{"name":"dense3/conv1/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00287135781026354,"min":-0.47664539650374765}},{"name":"dense3/conv2/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006002906724518421,"min":-0.7923836876364315}},{"name":"dense3/conv2/pointwise_filter","shape":[1,1,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.017087187019048954,"min":-1.6061955797906016}},{"name":"dense3/conv2/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003124481205846749,"min":-0.46242321846531886}},{"name":"dense3/conv3/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006576311588287353,"min":-1.0193282961845398}},{"name":"dense3/conv3/pointwise_filter","shape":[1,1,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015590153955945782,"min":-1.99553970636106}},{"name":"dense3/conv3/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004453541601405424,"min":-0.6546706154065973}},{"name":"fc/weights","shape":[256,136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010417488509533453,"min":-1.500118345372817}},{"name":"fc/bias","shape":[136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0025084222648658005,"min":0.07683877646923065}}],"paths":["z_face_landmark_68_model-shard1"]}]
[{"weights":[{"name":"conv32_down/conv/filters","shape":[7,7,3,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0005260649557207145,"min":-0.07101876902229645}},{"name":"conv32_down/conv/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":8.471445956577858e-7,"min":-0.00014740315964445472}},{"name":"conv32_down/scale/weights","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.06814416062598135,"min":5.788674831390381}},{"name":"conv32_down/scale/biases","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008471635042452345,"min":-0.931879854669758}},{"name":"conv32_1/conv1/conv/filters","shape":[3,3,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0007328585666768691,"min":-0.0974701893680236}},{"name":"conv32_1/conv1/conv/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":1.5952091238361e-8,"min":-0.000001978059313556764}},{"name":"conv32_1/conv1/scale/weights","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.02146628510718252,"min":3.1103382110595703}},{"name":"conv32_1/conv1/scale/biases","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0194976619645661,"min":-2.3787147596770644}},{"name":"conv32_1/conv2/conv/filters","shape":[3,3,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0004114975824075587,"min":-0.05267169054816751}},{"name":"conv32_1/conv2/conv/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":4.600177166424806e-9,"min":-5.70421968636676e-7}},{"name":"conv32_1/conv2/scale/weights","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.03400764932819441,"min":2.1677730083465576}},{"name":"conv32_1/conv2/scale/biases","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010974494616190593,"min":-1.240117891629537}},{"name":"conv32_2/conv1/conv/filters","shape":[3,3,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0005358753251094444,"min":-0.0760942961655411}},{"name":"conv32_2/conv1/conv/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":5.9886454383719385e-9,"min":-7.366033889197485e-7}},{"name":"conv32_2/conv1/scale/weights","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014633869657329485,"min":2.769575357437134}},{"name":"conv32_2/conv1/scale/biases","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.022131107367721257,"min":-2.5229462399202234}},{"name":"conv32_2/conv2/conv/filters","shape":[3,3,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00030145110452876373,"min":-0.03949009469326805}},{"name":"conv32_2/conv2/conv/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":6.8779549306497095e-9,"min":-9.010120959151119e-7}},{"name":"conv32_2/conv2/scale/weights","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.03929369870354148,"min":4.8010945320129395}},{"name":"conv32_2/conv2/scale/biases","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010553357180427103,"min":-1.2452961472903983}},{"name":"conv32_3/conv1/conv/filters","shape":[3,3,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0003133527642371608,"min":-0.040735859350830905}},{"name":"conv32_3/conv1/conv/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":4.1064200719547974e-9,"min":-3.0387508532465503e-7}},{"name":"conv32_3/conv1/scale/weights","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009252088210161994,"min":2.333256721496582}},{"name":"conv32_3/conv1/scale/biases","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.007104101251153385,"min":-0.34810096130651585}},{"name":"conv32_3/conv2/conv/filters","shape":[3,3,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00029995629892629733,"min":-0.031195455088334923}},{"name":"conv32_3/conv2/conv/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":5.62726418316814e-9,"min":-6.921534945296811e-7}},{"name":"conv32_3/conv2/scale/weights","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0467432975769043,"min":5.362040996551514}},{"name":"conv32_3/conv2/scale/biases","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010314425300149357,"min":-1.268674311918371}},{"name":"conv64_down/conv1/conv/filters","shape":[3,3,32,64],"dtype":"float32"},{"name":"conv64_down/conv1/conv/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":8.373908033218849e-10,"min":-1.172347124650639e-7}},{"name":"conv64_down/conv1/scale/weights","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0066875364266189875,"min":2.5088400840759277}},{"name":"conv64_down/conv1/scale/biases","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01691421620986041,"min":-2.0973628100226906}},{"name":"conv64_down/conv2/conv/filters","shape":[3,3,64,64],"dtype":"float32"},{"name":"conv64_down/conv2/conv/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":2.3252014483766877e-9,"min":-2.673981665633191e-7}},{"name":"conv64_down/conv2/scale/weights","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.032557439804077146,"min":2.6351239681243896}},{"name":"conv64_down/conv2/scale/biases","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015429047509735706,"min":-1.5429047509735707}},{"name":"conv64_1/conv1/conv/filters","shape":[3,3,64,64],"dtype":"float32"},{"name":"conv64_1/conv1/conv/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":1.1319172039756998e-9,"min":-1.4941307092479238e-7}},{"name":"conv64_1/conv1/scale/weights","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.007802607031429515,"min":3.401733160018921}},{"name":"conv64_1/conv1/scale/biases","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01425027146058924,"min":-0.6982633015688727}},{"name":"conv64_1/conv2/conv/filters","shape":[3,3,64,64],"dtype":"float32"},{"name":"conv64_1/conv2/conv/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":2.5635019893325435e-9,"min":-2.717312108692496e-7}},{"name":"conv64_1/conv2/scale/weights","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.04062801716374416,"min":3.542381525039673}},{"name":"conv64_1/conv2/scale/biases","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.007973166306813557,"min":-0.7415044665336609}},{"name":"conv64_2/conv1/conv/filters","shape":[3,3,64,64],"dtype":"float32"},{"name":"conv64_2/conv1/conv/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":1.2535732661062331e-9,"min":-1.8302169685151004e-7}},{"name":"conv64_2/conv1/scale/weights","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005631206549850164,"min":2.9051668643951416}},{"name":"conv64_2/conv1/scale/biases","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01859012585060269,"min":-2.3795361088771445}},{"name":"conv64_2/conv2/conv/filters","shape":[3,3,64,64],"dtype":"float32"},{"name":"conv64_2/conv2/conv/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":2.486726369919351e-9,"min":-3.5311514452854786e-7}},{"name":"conv64_2/conv2/scale/weights","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.03740917467603497,"min":5.571568965911865}},{"name":"conv64_2/conv2/scale/biases","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006418555858088475,"min":-0.5263215803632549}},{"name":"conv64_3/conv1/conv/filters","shape":[3,3,64,64],"dtype":"float32"},{"name":"conv64_3/conv1/conv/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":7.432564576875473e-10,"min":-8.47312361763804e-8}},{"name":"conv64_3/conv1/scale/weights","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006400122362024644,"min":2.268010377883911}},{"name":"conv64_3/conv1/scale/biases","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010945847922680425,"min":-1.3353934465670119}},{"name":"conv64_3/conv2/conv/filters","shape":[3,3,64,64],"dtype":"float32"},{"name":"conv64_3/conv2/conv/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":2.278228722014533e-9,"min":-3.212302498040492e-7}},{"name":"conv64_3/conv2/scale/weights","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.029840927498013366,"min":7.038398265838623}},{"name":"conv64_3/conv2/scale/biases","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.010651412197187834,"min":-1.161003929493474}},{"name":"conv128_down/conv1/conv/filters","shape":[3,3,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00020040544662989823,"min":-0.022245004575918704}},{"name":"conv128_down/conv1/conv/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":4.3550543563576545e-10,"min":-4.311503812794078e-8}},{"name":"conv128_down/conv1/scale/weights","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.007448580685783835,"min":2.830846071243286}},{"name":"conv128_down/conv1/scale/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01211262824488621,"min":-1.6957679542840696}},{"name":"conv128_down/conv2/conv/filters","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00022380277514457702,"min":-0.02484210804104805}},{"name":"conv128_down/conv2/conv/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":9.031058637304466e-10,"min":-1.1650065642122761e-7}},{"name":"conv128_down/conv2/scale/weights","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.027663578706629135,"min":3.1111555099487305}},{"name":"conv128_down/conv2/scale/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008878476946961646,"min":-1.029903325847551}},{"name":"conv128_1/conv1/conv/filters","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00022380667574265425,"min":-0.032899581334170175}},{"name":"conv128_1/conv1/conv/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":4.4147297756478345e-10,"min":-5.253528433020923e-8}},{"name":"conv128_1/conv1/scale/weights","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013599334978589825,"min":3.634530782699585}},{"name":"conv128_1/conv1/scale/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014059314073300829,"min":-1.4059314073300828}},{"name":"conv128_1/conv2/conv/filters","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00021715293474057143,"min":-0.02909849325523657}},{"name":"conv128_1/conv2/conv/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":9.887046963276768e-10,"min":-1.1370104007768284e-7}},{"name":"conv128_1/conv2/scale/weights","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.029993299409454943,"min":3.630716562271118}},{"name":"conv128_1/conv2/scale/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00782704236460667,"min":-0.7200878975438136}},{"name":"conv128_2/conv1/conv/filters","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00017718105923895743,"min":-0.022324813464108636}},{"name":"conv128_2/conv1/conv/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":3.567012027797675e-10,"min":-5.243507680862582e-8}},{"name":"conv128_2/conv1/scale/weights","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.007940645778880399,"min":4.927767753601074}},{"name":"conv128_2/conv1/scale/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015933452867994122,"min":-1.5614783810634238}},{"name":"conv128_2/conv2/conv/filters","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0001451439717236687,"min":-0.01712698866339291}},{"name":"conv128_2/conv2/conv/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":1.0383988570966347e-9,"min":-1.2356946399449953e-7}},{"name":"conv128_2/conv2/scale/weights","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.02892604528688917,"min":4.750600814819336}},{"name":"conv128_2/conv2/scale/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00797275748907351,"min":-0.7414664464838364}},{"name":"conv256_down/conv1/conv/filters","shape":[3,3,128,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0002698827827093648,"min":-0.03994265184098599}},{"name":"conv256_down/conv1/conv/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":5.036909834755123e-10,"min":-6.396875490139006e-8}},{"name":"conv256_down/conv1/scale/weights","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014870181738161573,"min":4.269900798797607}},{"name":"conv256_down/conv1/scale/biases","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.022031106200872685,"min":-3.1063859743230484}},{"name":"conv256_down/conv2/conv/filters","shape":[3,3,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00046430734150549946,"min":-0.03946612402796745}},{"name":"conv256_down/conv2/conv/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":6.693064577513153e-10,"min":-7.630093618364995e-8}},{"name":"conv256_down/conv2/scale/weights","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.03475512242784687,"min":3.608360528945923}},{"name":"conv256_down/conv2/scale/biases","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01290142021927179,"min":-1.1482263995151893}},{"name":"conv256_1/conv1/conv/filters","shape":[3,3,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00037147209924810076,"min":-0.04234781931428348}},{"name":"conv256_1/conv1/conv/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":3.2105515457510146e-10,"min":-3.467395669411096e-8}},{"name":"conv256_1/conv1/scale/weights","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.043242172166412955,"min":5.28542947769165}},{"name":"conv256_1/conv1/scale/biases","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01643658619300992,"min":-1.3149268954407936}},{"name":"conv256_1/conv2/conv/filters","shape":[3,3,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0003289232651392619,"min":-0.041773254672686264}},{"name":"conv256_1/conv2/conv/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":9.13591691187321e-10,"min":-1.2333487831028833e-7}},{"name":"conv256_1/conv2/scale/weights","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0573908618852204,"min":4.360693454742432}},{"name":"conv256_1/conv2/scale/biases","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0164216583850337,"min":-1.3958409627278647}},{"name":"conv256_2/conv1/conv/filters","shape":[3,3,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00010476927912118389,"min":-0.015610622589056398}},{"name":"conv256_2/conv1/conv/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":2.418552539068639e-10,"min":-2.539480166022071e-8}},{"name":"conv256_2/conv1/scale/weights","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.06024209564807368,"min":6.598613739013672}},{"name":"conv256_2/conv1/scale/biases","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.01578534350675695,"min":-1.1049740454729864}},{"name":"conv256_2/conv2/conv/filters","shape":[3,3,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00005543030908002573,"min":-0.007427661416723448}},{"name":"conv256_2/conv2/conv/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":1.0822061852320308e-9,"min":-1.515088659324843e-7}},{"name":"conv256_2/conv2/scale/weights","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.04302893993901272,"min":2.2855491638183594}},{"name":"conv256_2/conv2/scale/biases","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006792667566561232,"min":-0.8083274404207865}},{"name":"conv256_down_out/conv1/conv/filters","shape":[3,3,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.000568966465253456,"min":-0.05632768006009214}},{"name":"conv256_down_out/conv1/conv/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":4.5347887884881677e-10,"min":-6.530095855422961e-8}},{"name":"conv256_down_out/conv1/scale/weights","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.017565592597512638,"min":4.594101905822754}},{"name":"conv256_down_out/conv1/scale/biases","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.04850864223405427,"min":-6.306123490427055}},{"name":"conv256_down_out/conv2/conv/filters","shape":[3,3,256,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0003739110687199761,"min":-0.06954745878191555}},{"name":"conv256_down_out/conv2/conv/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":1.2668428328152895e-9,"min":-2.2549802424112154e-7}},{"name":"conv256_down_out/conv2/scale/weights","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.04351314469879749,"min":4.31956672668457}},{"name":"conv256_down_out/conv2/scale/biases","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.021499746921015722,"min":-1.2039858275768804}},{"name":"fc","shape":[256,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.000357687911566566,"min":-0.04578405268052045}}],"paths":["z_face_recognition_model-shard1","z_face_recognition_model-shard2"]}]
// Arithmetic mean
let getMean = function (data) {
return data.reduce(function (a, b) {
return Number(a) + Number(b);
}) / data.length;
};
// Standard deviation
let getSD = function (data) {
let m = getMean(data);
return Math.sqrt(data.reduce(function (sq, n) {
return sq + Math.pow(n - m, 2);
}, 0) / (data.length - 1));
};
const LM_LEN = 68;
const LM_parts = ['chin', 'left_eyebrow', 'right_eyebrow',
'nose_bridge', 'nose_tip', 'left_eye', 'right_eye',
'top_lip', 'bottom_lip'];
const LM_names = [
'chin', 'chin', 'chin', 'chin', 'chin',
'chin', 'chin', 'chin', 'chin', 'chin',
'chin', 'chin', 'chin', 'chin', 'chin',
'chin', 'chin',
'left_eyebrow', 'left_eyebrow', 'left_eyebrow', 'left_eyebrow', 'left_eyebrow',
'right_eyebrow', 'right_eyebrow', 'right_eyebrow', 'right_eyebrow', 'right_eyebrow',
'nose_bridge', 'nose_bridge', 'nose_bridge', 'nose_bridge',
'nose_tip', 'nose_tip', 'nose_tip', 'nose_tip', 'nose_tip',
'left_eye', 'left_eye', 'left_eye', 'left_eye', 'left_eye', 'left_eye',
'right_eye', 'right_eye', 'right_eye', 'right_eye', 'right_eye', 'right_eye',
'lip', 'lip', 'lip', 'lip',
'lip', 'lip', 'lip', 'lip',
'lip', 'lip', 'lip', 'lip',
'lip', 'lip', 'lip', 'lip',
'lip', 'lip', 'lip', 'lip'
]
// https://github.com/ageitgey/face_recognition/blob/d34c622bf42e2c619505a4884017051ecf61ac77/face_recognition/api.py#L190
const top_lip_indices = [48, 49, 50, 51, 52, 53, 54, 64, 63, 62, 61, 60];
const bottom_lip_indices = [54, 55, 56, 57, 58, 59, 48, 60, 67, 66, 65, 64];
function get_landmarks(faceDescriptions) {
let landmarks = []
for(let i=0; i<faceDescriptions.length; i++) {
let curLM = {
'chin': [],
'left_eyebrow': [],
'right_eyebrow': [],
'nose_bridge': [],
'nose_tip': [],
'left_eye': [],
'right_eye': [],
'top_lip': [],
'bottom_lip': []
};
let lm = faceDescriptions[i].landmarks;
let lpts = lm.positions;
let x_points = [];
let y_points = [];
// print(lpts.length)
for(let j=0; j<LM_LEN; j++) {
x_points.push(lpts[j].x)
y_points.push(lpts[j].y)
}
let mean_x = getMean(x_points);
let mean_y = getMean(y_points);
for(let j=0; j<LM_LEN; j++) {
x_points[j] = x_points[j] - mean_x;
y_points[j] = y_points[j] - mean_y;
}
let sdev_x = getSD(x_points);
let sdev_y = getSD(y_points);
let sdev = sdev_x > sdev_y ? sdev_x : sdev_y;
// let p1 = lpts[27]
// let p2 = lpts[28]
// EYES VERSION
// let p1 = lpts[36];
// let p2 = lpts[42];
// EARS VERSION
let p1 = lpts[2];
let p2 = lpts[14];
let xd = p1.x - p2.x;
let yd = p1.y - p2.y;
let angle = Math.atan2(-yd, -xd);
let s_a = Math.sin(-angle);
let c_a = Math.cos(-angle);
let raw_points = []
for(let j=0; j<LM_LEN; j++) {
let pt = [0, 0]
pt[0] = lpts[j].x - mean_x;
pt[1] = lpts[j].y - mean_y;
pt[0] = pt[0] / sdev;
pt[1] = pt[1] / sdev;
let x_new = pt[0] * c_a - pt[1] * s_a;
let y_new = pt[0] * s_a + pt[1] * c_a;
pt[0] = x_new;
pt[1] = y_new;
raw_points.push(pt);
}
// put all raw points into landmarks objects
// first everything but the lips (which start at 48)
for(let j=0; j<48; j++) {
let key = LM_names[j];
curLM[key].push(raw_points[j]);
}
// now the lips, which have dupes
for(let j=0; j<top_lip_indices.length; j++) {
let cur_ix = top_lip_indices[j];
let cur_pt = raw_points[cur_ix];
let pt_copy = [cur_pt[0], cur_pt[1]];
curLM['top_lip'].push(pt_copy);
}
for(let j=0; j<bottom_lip_indices.length; j++) {
let cur_ix = bottom_lip_indices[j];
let cur_pt = raw_points[cur_ix];
let pt_copy = [cur_pt[0], cur_pt[1]];
curLM['bottom_lip'].push(pt_copy);
}
curLM['transform'] = {
'center': [mean_x, mean_y],
'scale': sdev,
'angle': angle
}
landmarks.push(curLM);
}
// print(JSON.stringify(landmarks));
return landmarks;
}
function get_latents(faceDescriptions) {
latents = [];
for(let i=0; i<faceDescriptions.length; i++) {
let lm = faceDescriptions[i].descriptor;
latents.push(lm);
// print(lm);
}
return latents;
}
function resetFocusedRandom() {
return Math.seedrandom(arguments);
}
function focusedRandom(min, max, focus, mean) {
// console.log("hello")
if(max === undefined) {
max = min;
min = 0;
}
if(focus === undefined) {
focus = 1.0;
}
if(mean === undefined) {
mean = (min + max) / 2.0;
}
if(focus == 0) {
return d3.randomUniform(min, max)();
}
else if(focus < 0) {
focus = -1 / focus;
}
let sigma = (max - min) / (2 * focus);
let val = d3.randomNormal(mean, sigma)();
if (val >= min && val < max) {
return val;
}
return d3.randomUniform(min, max)();
}
/**
* k-d Tree JavaScript - V 1.01
*
* https://github.com/ubilabs/kd-tree-javascript
*
* @author Mircea Pricop <pricop@ubilabs.net>, 2012
* @author Martin Kleppe <kleppe@ubilabs.net>, 2012
* @author Ubilabs http://ubilabs.net, 2012
* @license MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['exports'], factory);
} else if (typeof exports === 'object') {
factory(exports);
} else {
factory((root.commonJsStrict = {}));
}
}(this, function (exports) {
function Node(obj, dimension, parent) {
this.obj = obj;
this.left = null;
this.right = null;
this.parent = parent;
this.dimension = dimension;
}
function kdTree(points, metric, dimensions) {
var self = this;
function buildTree(points, depth, parent) {
var dim = depth % dimensions.length,
median,
node;
if (points.length === 0) {
return null;
}
if (points.length === 1) {
return new Node(points[0], dim, parent);
}
points.sort(function (a, b) {
return a[dimensions[dim]] - b[dimensions[dim]];
});
median = Math.floor(points.length / 2);
node = new Node(points[median], dim, parent);
node.left = buildTree(points.slice(0, median), depth + 1, node);
node.right = buildTree(points.slice(median + 1), depth + 1, node);
return node;
}
// Reloads a serialied tree
function loadTree (data) {
// Just need to restore the `parent` parameter
self.root = data;
function restoreParent (root) {
if (root.left) {
root.left.parent = root;
restoreParent(root.left);
}
if (root.right) {
root.right.parent = root;
restoreParent(root.right);
}
}
restoreParent(self.root);
}
// If points is not an array, assume we're loading a pre-built tree
if (!Array.isArray(points)) loadTree(points, metric, dimensions);
else this.root = buildTree(points, 0, null);
// Convert to a JSON serializable structure; this just requires removing
// the `parent` property
this.toJSON = function (src) {
if (!src) src = this.root;
var dest = new Node(src.obj, src.dimension, null);
if (src.left) dest.left = self.toJSON(src.left);
if (src.right) dest.right = self.toJSON(src.right);
return dest;
};
this.insert = function (point) {
function innerSearch(node, parent) {
if (node === null) {
return parent;
}
var dimension = dimensions[node.dimension];
if (point[dimension] < node.obj[dimension]) {
return innerSearch(node.left, node);
} else {
return innerSearch(node.right, node);
}
}
var insertPosition = innerSearch(this.root, null),
newNode,
dimension;
if (insertPosition === null) {
this.root = new Node(point, 0, null);
return;
}
newNode = new Node(point, (insertPosition.dimension + 1) % dimensions.length, insertPosition);
dimension = dimensions[insertPosition.dimension];
if (point[dimension] < insertPosition.obj[dimension]) {
insertPosition.left = newNode;
} else {
insertPosition.right = newNode;
}
};
this.remove = function (point) {
var node;
function nodeSearch(node) {
if (node === null) {
return null;
}
if (node.obj === point) {
return node;
}
var dimension = dimensions[node.dimension];
if (point[dimension] < node.obj[dimension]) {
return nodeSearch(node.left, node);
} else {
return nodeSearch(node.right, node);
}
}
function removeNode(node) {
var nextNode,
nextObj,
pDimension;
function findMin(node, dim) {
var dimension,
own,
left,
right,
min;
if (node === null) {
return null;
}
dimension = dimensions[dim];
if (node.dimension === dim) {
if (node.left !== null) {
return findMin(node.left, dim);
}
return node;
}
own = node.obj[dimension];
left = findMin(node.left, dim);
right = findMin(node.right, dim);
min = node;
if (left !== null && left.obj[dimension] < own) {
min = left;
}
if (right !== null && right.obj[dimension] < min.obj[dimension]) {
min = right;
}
return min;
}
if (node.left === null && node.right === null) {
if (node.parent === null) {
self.root = null;
return;
}
pDimension = dimensions[node.parent.dimension];
if (node.obj[pDimension] < node.parent.obj[pDimension]) {
node.parent.left = null;
} else {
node.parent.right = null;
}
return;
}
// If the right subtree is not empty, swap with the minimum element on the
// node's dimension. If it is empty, we swap the left and right subtrees and
// do the same.
if (node.right !== null) {
nextNode = findMin(node.right, node.dimension);
nextObj = nextNode.obj;
removeNode(nextNode);
node.obj = nextObj;
} else {
nextNode = findMin(node.left, node.dimension);
nextObj = nextNode.obj;
removeNode(nextNode);
node.right = node.left;
node.left = null;
node.obj = nextObj;
}
}
node = nodeSearch(self.root);
if (node === null) { return; }
removeNode(node);
};
this.nearest = function (point, maxNodes, maxDistance) {
var i,
result,
bestNodes;
bestNodes = new BinaryHeap(
function (e) { return -e[1]; }
);
function nearestSearch(node) {
var bestChild,
dimension = dimensions[node.dimension],
ownDistance = metric(point, node.obj),
linearPoint = {},
linearDistance,
otherChild,
i;
function saveNode(node, distance) {
bestNodes.push([node, distance]);
if (bestNodes.size() > maxNodes) {
bestNodes.pop();
}
}
for (i = 0; i < dimensions.length; i += 1) {
if (i === node.dimension) {
linearPoint[dimensions[i]] = point[dimensions[i]];
} else {
linearPoint[dimensions[i]] = node.obj[dimensions[i]];
}
}
linearDistance = metric(linearPoint, node.obj);
if (node.right === null && node.left === null) {
if (bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[1]) {
saveNode(node, ownDistance);
}
return;
}
if (node.right === null) {
bestChild = node.left;
} else if (node.left === null) {
bestChild = node.right;
} else {
if (point[dimension] < node.obj[dimension]) {
bestChild = node.left;
} else {
bestChild = node.right;
}
}
nearestSearch(bestChild);
if (bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[1]) {
saveNode(node, ownDistance);
}
if (bestNodes.size() < maxNodes || Math.abs(linearDistance) < bestNodes.peek()[1]) {
if (bestChild === node.left) {
otherChild = node.right;
} else {
otherChild = node.left;
}
if (otherChild !== null) {
nearestSearch(otherChild);
}
}
}
if (maxDistance) {
for (i = 0; i < maxNodes; i += 1) {
bestNodes.push([null, maxDistance]);
}
}
if(self.root)
nearestSearch(self.root);
result = [];
for (i = 0; i < Math.min(maxNodes, bestNodes.content.length); i += 1) {
if (bestNodes.content[i][0]) {
result.push([bestNodes.content[i][0].obj, bestNodes.content[i][1]]);
}
}
return result;
};
this.balanceFactor = function () {
function height(node) {
if (node === null) {
return 0;
}
return Math.max(height(node.left), height(node.right)) + 1;
}
function count(node) {
if (node === null) {
return 0;
}
return count(node.left) + count(node.right) + 1;
}
return height(self.root) / (Math.log(count(self.root)) / Math.log(2));
};
}
// Binary heap implementation from:
// http://eloquentjavascript.net/appendix2.html
function BinaryHeap(scoreFunction){
this.content = [];
this.scoreFunction = scoreFunction;
}
BinaryHeap.prototype = {
push: function(element) {
// Add the new element to the end of the array.
this.content.push(element);
// Allow it to bubble up.
this.bubbleUp(this.content.length - 1);
},
pop: function() {
// Store the first element so we can return it later.
var result = this.content[0];
// Get the element at the end of the array.
var end = this.content.pop();
// If there are any elements left, put the end element at the
// start, and let it sink down.
if (this.content.length > 0) {
this.content[0] = end;
this.sinkDown(0);
}
return result;
},
peek: function() {
return this.content[0];
},
remove: function(node) {
var len = this.content.length;
// To remove a value, we must search through the array to find
// it.
for (var i = 0; i < len; i++) {
if (this.content[i] == node) {
// When it is found, the process seen in 'pop' is repeated
// to fill up the hole.
var end = this.content.pop();
if (i != len - 1) {
this.content[i] = end;
if (this.scoreFunction(end) < this.scoreFunction(node))
this.bubbleUp(i);
else
this.sinkDown(i);
}
return;
}
}
throw new Error("Node not found.");
},
size: function() {
return this.content.length;
},
bubbleUp: function(n) {
// Fetch the element that has to be moved.
var element = this.content[n];
// When at 0, an element can not go up any further.
while (n > 0) {
// Compute the parent element's index, and fetch it.
var parentN = Math.floor((n + 1) / 2) - 1,
parent = this.content[parentN];
// Swap the elements if the parent is greater.
if (this.scoreFunction(element) < this.scoreFunction(parent)) {
this.content[parentN] = element;
this.content[n] = parent;
// Update 'n' to continue at the new position.
n = parentN;
}
// Found a parent that is less, no need to move it further.
else {
break;
}
}
},
sinkDown: function(n) {
// Look up the target element and its score.
var length = this.content.length,
element = this.content[n],
elemScore = this.scoreFunction(element);
while(true) {
// Compute the indices of the child elements.
var child2N = (n + 1) * 2, child1N = child2N - 1;
// This is used to store the new position of the element,
// if any.
var swap = null;
// If the first child exists (is inside the array)...
if (child1N < length) {
// Look it up and compute its score.
var child1 = this.content[child1N],
child1Score = this.scoreFunction(child1);
// If the score is less than our element's, we need to swap.
if (child1Score < elemScore)
swap = child1N;
}
// Do the same checks for the other child.
if (child2N < length) {
var child2 = this.content[child2N],
child2Score = this.scoreFunction(child2);
if (child2Score < (swap == null ? elemScore : child1Score)){
swap = child2N;
}
}
// If the element needs to be moved, swap it, and continue.
if (swap != null) {
this.content[n] = this.content[swap];
this.content[swap] = element;
n = swap;
}
// Otherwise, we are done.
else {
break;
}
}
}
};
this.kdTree = kdTree;
exports.kdTree = kdTree;
exports.BinaryHeap = BinaryHeap;
}));
// note: this file is poorly named - it can generally be ignored.
// helper functions below for supporting blocks/purview
function saveBlocksImages(doZoom) {
if(doZoom == null) {
doZoom = false;
}
// generate 960x500 preview.jpg of entire canvas
// TODO: should this be recycled?
var offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = 960;
offscreenCanvas.height = 500;
var context = offscreenCanvas.getContext('2d');
// background is flat white
context.fillStyle="#FFFFFF";
context.fillRect(0, 0, 960, 500);
context.drawImage(this.canvas, 0, 0, 960, 500);
// save to browser
var downloadMime = 'image/octet-stream';
var imageData = offscreenCanvas.toDataURL('image/jpeg');
imageData = imageData.replace('image/jpeg', downloadMime);
p5.prototype.downloadFile(imageData, 'preview.jpg', 'jpg');
// generate 230x120 thumbnail.png centered on mouse
offscreenCanvas.width = 230;
offscreenCanvas.height = 120;
// background is flat white
context = offscreenCanvas.getContext('2d');
context.fillStyle="#FFFFFF";
context.fillRect(0, 0, 230, 120);
if(doZoom) {
// pixelDensity does the right thing on retina displays
var pd = this._pixelDensity;
var sx = pd * mouseX - pd * 230/2;
var sy = pd * mouseY - pd * 120/2;
var sw = pd * 230;
var sh = pd * 120;
// bounds checking - just displace if necessary
if (sx < 0) {
sx = 0;
}
if (sx > this.canvas.width - sw) {
sx = this.canvas.width - sw;
}
if (sy < 0) {
sy = 0;
}
if (sy > this.canvas.height - sh) {
sy = this.canvas.height - sh;
}
// save to browser
context.drawImage(this.canvas, sx, sy, sw, sh, 0, 0, 230, 120);
}
else {
// now scaledown
var full_width = this.canvas.width;
var full_height = this.canvas.height;
context.drawImage(this.canvas, 0, 0, full_width, full_height, 0, 0, 230, 120);
}
imageData = offscreenCanvas.toDataURL('image/png');
imageData = imageData.replace('image/png', downloadMime);
// call this function after 1 second
setTimeout(function(){
p5.prototype.downloadFile(imageData, 'thumbnail.png', 'png');
}, 1000);
}