added experimental face.rotation.gaze

pull/134/head
Vladimir Mandic 2021-05-28 15:53:51 -04:00
parent 82c93191ac
commit 8c9fb63b01
19 changed files with 388 additions and 203 deletions

View File

@ -9,7 +9,10 @@ Repository: **<git+https://github.com/vladmandic/human.git>**
## Changelog
### **HEAD -> main** 2021/05/27 mandic00@live.com
### **HEAD -> main** 2021/05/28 mandic00@live.com
### **origin/main** 2021/05/27 mandic00@live.com
### **1.9.4** 2021/05/27 mandic00@live.com

View File

@ -17,8 +17,8 @@ let human;
const userConfig = {
warmup: 'none',
backend: 'webgl',
async: false,
cacheSensitivity: 0,
// async: false,
// cacheSensitivity: 0,
filter: {
enabled: false,
flip: false,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

8
dist/human.esm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

10
dist/human.js vendored

File diff suppressed because one or more lines are too long

View File

@ -4324,8 +4324,23 @@ async function predict3(image13, config3, idx, count2) {
}
// src/face.ts
var calculateFaceAngle = (face5, image_size) => {
const degrees = (theta) => theta * 180 / Math.PI;
var calculateGaze = (mesh) => {
const radians = (pt1, pt2) => Math.atan2(pt1[1] - pt2[1], pt1[0] - pt2[0]);
const offsetIris = [0, 0];
const eyeRatio = 5;
const left = mesh[33][2] > mesh[263][2];
const irisCenter = left ? mesh[473] : mesh[468];
const eyeCenter = left ? [(mesh[133][0] + mesh[33][0]) / 2, (mesh[133][1] + mesh[33][1]) / 2] : [(mesh[263][0] + mesh[362][0]) / 2, (mesh[263][1] + mesh[362][1]) / 2];
const eyeSize = left ? [mesh[133][0] - mesh[33][0], mesh[23][1] - mesh[27][1]] : [mesh[263][0] - mesh[362][0], mesh[253][1] - mesh[257][1]];
const eyeDiff = [
(eyeCenter[0] - irisCenter[0]) / eyeSize[0] - offsetIris[0],
eyeRatio * (irisCenter[1] - eyeCenter[1]) / eyeSize[1] - offsetIris[1]
];
const vectorLength = Math.sqrt(eyeDiff[0] ** 2 + eyeDiff[1] ** 2);
const vectorAngle = radians([0, 0], eyeDiff);
return { angle: vectorAngle, strength: vectorLength };
};
var calculateFaceAngle = (face5, imageSize) => {
const normalize = (v) => {
const length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] /= length;
@ -4378,11 +4393,11 @@ var calculateFaceAngle = (face5, image_size) => {
};
const mesh = face5.meshRaw;
if (!mesh || mesh.length < 300)
return { angle: { pitch: 0, yaw: 0, roll: 0 }, matrix: [1, 0, 0, 0, 1, 0, 0, 0, 1] };
const size = Math.max(face5.boxRaw[2] * image_size[0], face5.boxRaw[3] * image_size[1]) / 1.5;
return { angle: { pitch: 0, yaw: 0, roll: 0 }, matrix: [1, 0, 0, 0, 1, 0, 0, 0, 1], gaze: { angle: 0, strength: 0 } };
const size = Math.max(face5.boxRaw[2] * imageSize[0], face5.boxRaw[3] * imageSize[1]) / 1.5;
const pts = [mesh[10], mesh[152], mesh[234], mesh[454]].map((pt) => [
pt[0] * image_size[0] / size,
pt[1] * image_size[1] / size,
pt[0] * imageSize[0] / size,
pt[1] * imageSize[1] / size,
pt[2]
]);
const y_axis = normalize(subVectors(pts[1], pts[0]));
@ -4401,7 +4416,8 @@ var calculateFaceAngle = (face5, image_size) => {
z_axis[2]
];
const angle = rotationMatrixToEulerAngle(matrix);
return { angle, matrix };
const gaze = mesh.length === 478 ? calculateGaze(mesh) : { angle: 0, strength: 0 };
return { angle, matrix, gaze };
};
var detectFace = async (parent, input) => {
var _a, _b, _c, _d, _e, _f, _g, _h;
@ -17535,15 +17551,14 @@ var iris = (res) => {
gestures.push({ iris: i, gesture: "looking left" });
const rightIrisCenterY = Math.abs(res[i].mesh[145][1] - res[i].annotations.rightEyeIris[0][1]) / res[i].box[3];
const leftIrisCenterY = Math.abs(res[i].mesh[374][1] - res[i].annotations.leftEyeIris[0][1]) / res[i].box[3];
if (leftIrisCenterY < 0.01 || rightIrisCenterY < 0.01 || leftIrisCenterY > 0.025 || rightIrisCenterY > 0.025)
if (leftIrisCenterY < 0.01 || rightIrisCenterY < 0.01 || leftIrisCenterY > 0.022 || rightIrisCenterY > 0.022)
center = false;
if (leftIrisCenterY < 0.01 || rightIrisCenterY < 0.01)
gestures.push({ iris: i, gesture: "looking down" });
if (leftIrisCenterY > 0.025 || rightIrisCenterY > 0.025)
if (leftIrisCenterY > 0.022 || rightIrisCenterY > 0.022)
gestures.push({ iris: i, gesture: "looking up" });
if (center)
gestures.push({ iris: i, gesture: "looking center" });
console.log(leftIrisCenterX, rightIrisCenterX, leftIrisCenterY, rightIrisCenterY, gestures);
}
return gestures;
};
@ -18538,6 +18553,7 @@ async function gesture(inCanvas2, result, drawOptions) {
}
}
async function face2(inCanvas2, result, drawOptions) {
var _a, _b, _c, _d;
const localOptions = mergeDeep(options, drawOptions);
if (!result || !inCanvas2)
return;
@ -18619,6 +18635,26 @@ async function face2(inCanvas2, result, drawOptions) {
ctx.fill();
}
}
if (((_b = (_a = f.rotation) == null ? void 0 : _a.gaze) == null ? void 0 : _b.strength) && ((_d = (_c = f.rotation) == null ? void 0 : _c.gaze) == null ? void 0 : _d.angle)) {
const leftGaze = [
f.annotations["leftEyeIris"][0][0] + Math.cos(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[2],
f.annotations["leftEyeIris"][0][1] - Math.sin(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[3]
];
ctx.beginPath();
ctx.moveTo(f.annotations["leftEyeIris"][0][0], f.annotations["leftEyeIris"][0][1]);
ctx.strokeStyle = "pink";
ctx.lineTo(leftGaze[0], leftGaze[1]);
ctx.stroke();
const rightGaze = [
f.annotations["rightEyeIris"][0][0] + Math.cos(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[2],
f.annotations["rightEyeIris"][0][1] - Math.sin(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[3]
];
ctx.beginPath();
ctx.moveTo(f.annotations["rightEyeIris"][0][0], f.annotations["rightEyeIris"][0][1]);
ctx.strokeStyle = "pink";
ctx.lineTo(rightGaze[0], rightGaze[1]);
ctx.stroke();
}
}
}
}

View File

@ -4325,8 +4325,23 @@ async function predict3(image13, config3, idx, count2) {
}
// src/face.ts
var calculateFaceAngle = (face5, image_size) => {
const degrees = (theta) => theta * 180 / Math.PI;
var calculateGaze = (mesh) => {
const radians = (pt1, pt2) => Math.atan2(pt1[1] - pt2[1], pt1[0] - pt2[0]);
const offsetIris = [0, 0];
const eyeRatio = 5;
const left = mesh[33][2] > mesh[263][2];
const irisCenter = left ? mesh[473] : mesh[468];
const eyeCenter = left ? [(mesh[133][0] + mesh[33][0]) / 2, (mesh[133][1] + mesh[33][1]) / 2] : [(mesh[263][0] + mesh[362][0]) / 2, (mesh[263][1] + mesh[362][1]) / 2];
const eyeSize = left ? [mesh[133][0] - mesh[33][0], mesh[23][1] - mesh[27][1]] : [mesh[263][0] - mesh[362][0], mesh[253][1] - mesh[257][1]];
const eyeDiff = [
(eyeCenter[0] - irisCenter[0]) / eyeSize[0] - offsetIris[0],
eyeRatio * (irisCenter[1] - eyeCenter[1]) / eyeSize[1] - offsetIris[1]
];
const vectorLength = Math.sqrt(eyeDiff[0] ** 2 + eyeDiff[1] ** 2);
const vectorAngle = radians([0, 0], eyeDiff);
return { angle: vectorAngle, strength: vectorLength };
};
var calculateFaceAngle = (face5, imageSize) => {
const normalize = (v) => {
const length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] /= length;
@ -4379,11 +4394,11 @@ var calculateFaceAngle = (face5, image_size) => {
};
const mesh = face5.meshRaw;
if (!mesh || mesh.length < 300)
return { angle: { pitch: 0, yaw: 0, roll: 0 }, matrix: [1, 0, 0, 0, 1, 0, 0, 0, 1] };
const size = Math.max(face5.boxRaw[2] * image_size[0], face5.boxRaw[3] * image_size[1]) / 1.5;
return { angle: { pitch: 0, yaw: 0, roll: 0 }, matrix: [1, 0, 0, 0, 1, 0, 0, 0, 1], gaze: { angle: 0, strength: 0 } };
const size = Math.max(face5.boxRaw[2] * imageSize[0], face5.boxRaw[3] * imageSize[1]) / 1.5;
const pts = [mesh[10], mesh[152], mesh[234], mesh[454]].map((pt) => [
pt[0] * image_size[0] / size,
pt[1] * image_size[1] / size,
pt[0] * imageSize[0] / size,
pt[1] * imageSize[1] / size,
pt[2]
]);
const y_axis = normalize(subVectors(pts[1], pts[0]));
@ -4402,7 +4417,8 @@ var calculateFaceAngle = (face5, image_size) => {
z_axis[2]
];
const angle = rotationMatrixToEulerAngle(matrix);
return { angle, matrix };
const gaze = mesh.length === 478 ? calculateGaze(mesh) : { angle: 0, strength: 0 };
return { angle, matrix, gaze };
};
var detectFace = async (parent, input) => {
var _a, _b, _c, _d, _e, _f, _g, _h;
@ -17536,15 +17552,14 @@ var iris = (res) => {
gestures.push({ iris: i, gesture: "looking left" });
const rightIrisCenterY = Math.abs(res[i].mesh[145][1] - res[i].annotations.rightEyeIris[0][1]) / res[i].box[3];
const leftIrisCenterY = Math.abs(res[i].mesh[374][1] - res[i].annotations.leftEyeIris[0][1]) / res[i].box[3];
if (leftIrisCenterY < 0.01 || rightIrisCenterY < 0.01 || leftIrisCenterY > 0.025 || rightIrisCenterY > 0.025)
if (leftIrisCenterY < 0.01 || rightIrisCenterY < 0.01 || leftIrisCenterY > 0.022 || rightIrisCenterY > 0.022)
center = false;
if (leftIrisCenterY < 0.01 || rightIrisCenterY < 0.01)
gestures.push({ iris: i, gesture: "looking down" });
if (leftIrisCenterY > 0.025 || rightIrisCenterY > 0.025)
if (leftIrisCenterY > 0.022 || rightIrisCenterY > 0.022)
gestures.push({ iris: i, gesture: "looking up" });
if (center)
gestures.push({ iris: i, gesture: "looking center" });
console.log(leftIrisCenterX, rightIrisCenterX, leftIrisCenterY, rightIrisCenterY, gestures);
}
return gestures;
};
@ -18539,6 +18554,7 @@ async function gesture(inCanvas2, result, drawOptions) {
}
}
async function face2(inCanvas2, result, drawOptions) {
var _a, _b, _c, _d;
const localOptions = mergeDeep(options, drawOptions);
if (!result || !inCanvas2)
return;
@ -18620,6 +18636,26 @@ async function face2(inCanvas2, result, drawOptions) {
ctx.fill();
}
}
if (((_b = (_a = f.rotation) == null ? void 0 : _a.gaze) == null ? void 0 : _b.strength) && ((_d = (_c = f.rotation) == null ? void 0 : _c.gaze) == null ? void 0 : _d.angle)) {
const leftGaze = [
f.annotations["leftEyeIris"][0][0] + Math.cos(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[2],
f.annotations["leftEyeIris"][0][1] - Math.sin(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[3]
];
ctx.beginPath();
ctx.moveTo(f.annotations["leftEyeIris"][0][0], f.annotations["leftEyeIris"][0][1]);
ctx.strokeStyle = "pink";
ctx.lineTo(leftGaze[0], leftGaze[1]);
ctx.stroke();
const rightGaze = [
f.annotations["rightEyeIris"][0][0] + Math.cos(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[2],
f.annotations["rightEyeIris"][0][1] - Math.sin(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[3]
];
ctx.beginPath();
ctx.moveTo(f.annotations["rightEyeIris"][0][0], f.annotations["rightEyeIris"][0][1]);
ctx.strokeStyle = "pink";
ctx.lineTo(rightGaze[0], rightGaze[1]);
ctx.stroke();
}
}
}
}

56
dist/human.node.js vendored
View File

@ -4324,8 +4324,23 @@ async function predict3(image13, config3, idx, count2) {
}
// src/face.ts
var calculateFaceAngle = (face5, image_size) => {
const degrees = (theta) => theta * 180 / Math.PI;
var calculateGaze = (mesh) => {
const radians = (pt1, pt2) => Math.atan2(pt1[1] - pt2[1], pt1[0] - pt2[0]);
const offsetIris = [0, 0];
const eyeRatio = 5;
const left = mesh[33][2] > mesh[263][2];
const irisCenter = left ? mesh[473] : mesh[468];
const eyeCenter = left ? [(mesh[133][0] + mesh[33][0]) / 2, (mesh[133][1] + mesh[33][1]) / 2] : [(mesh[263][0] + mesh[362][0]) / 2, (mesh[263][1] + mesh[362][1]) / 2];
const eyeSize = left ? [mesh[133][0] - mesh[33][0], mesh[23][1] - mesh[27][1]] : [mesh[263][0] - mesh[362][0], mesh[253][1] - mesh[257][1]];
const eyeDiff = [
(eyeCenter[0] - irisCenter[0]) / eyeSize[0] - offsetIris[0],
eyeRatio * (irisCenter[1] - eyeCenter[1]) / eyeSize[1] - offsetIris[1]
];
const vectorLength = Math.sqrt(eyeDiff[0] ** 2 + eyeDiff[1] ** 2);
const vectorAngle = radians([0, 0], eyeDiff);
return { angle: vectorAngle, strength: vectorLength };
};
var calculateFaceAngle = (face5, imageSize) => {
const normalize = (v) => {
const length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] /= length;
@ -4378,11 +4393,11 @@ var calculateFaceAngle = (face5, image_size) => {
};
const mesh = face5.meshRaw;
if (!mesh || mesh.length < 300)
return { angle: { pitch: 0, yaw: 0, roll: 0 }, matrix: [1, 0, 0, 0, 1, 0, 0, 0, 1] };
const size = Math.max(face5.boxRaw[2] * image_size[0], face5.boxRaw[3] * image_size[1]) / 1.5;
return { angle: { pitch: 0, yaw: 0, roll: 0 }, matrix: [1, 0, 0, 0, 1, 0, 0, 0, 1], gaze: { angle: 0, strength: 0 } };
const size = Math.max(face5.boxRaw[2] * imageSize[0], face5.boxRaw[3] * imageSize[1]) / 1.5;
const pts = [mesh[10], mesh[152], mesh[234], mesh[454]].map((pt) => [
pt[0] * image_size[0] / size,
pt[1] * image_size[1] / size,
pt[0] * imageSize[0] / size,
pt[1] * imageSize[1] / size,
pt[2]
]);
const y_axis = normalize(subVectors(pts[1], pts[0]));
@ -4401,7 +4416,8 @@ var calculateFaceAngle = (face5, image_size) => {
z_axis[2]
];
const angle = rotationMatrixToEulerAngle(matrix);
return { angle, matrix };
const gaze = mesh.length === 478 ? calculateGaze(mesh) : { angle: 0, strength: 0 };
return { angle, matrix, gaze };
};
var detectFace = async (parent, input) => {
var _a, _b, _c, _d, _e, _f, _g, _h;
@ -17535,15 +17551,14 @@ var iris = (res) => {
gestures.push({ iris: i, gesture: "looking left" });
const rightIrisCenterY = Math.abs(res[i].mesh[145][1] - res[i].annotations.rightEyeIris[0][1]) / res[i].box[3];
const leftIrisCenterY = Math.abs(res[i].mesh[374][1] - res[i].annotations.leftEyeIris[0][1]) / res[i].box[3];
if (leftIrisCenterY < 0.01 || rightIrisCenterY < 0.01 || leftIrisCenterY > 0.025 || rightIrisCenterY > 0.025)
if (leftIrisCenterY < 0.01 || rightIrisCenterY < 0.01 || leftIrisCenterY > 0.022 || rightIrisCenterY > 0.022)
center = false;
if (leftIrisCenterY < 0.01 || rightIrisCenterY < 0.01)
gestures.push({ iris: i, gesture: "looking down" });
if (leftIrisCenterY > 0.025 || rightIrisCenterY > 0.025)
if (leftIrisCenterY > 0.022 || rightIrisCenterY > 0.022)
gestures.push({ iris: i, gesture: "looking up" });
if (center)
gestures.push({ iris: i, gesture: "looking center" });
console.log(leftIrisCenterX, rightIrisCenterX, leftIrisCenterY, rightIrisCenterY, gestures);
}
return gestures;
};
@ -18538,6 +18553,7 @@ async function gesture(inCanvas2, result, drawOptions) {
}
}
async function face2(inCanvas2, result, drawOptions) {
var _a, _b, _c, _d;
const localOptions = mergeDeep(options, drawOptions);
if (!result || !inCanvas2)
return;
@ -18619,6 +18635,26 @@ async function face2(inCanvas2, result, drawOptions) {
ctx.fill();
}
}
if (((_b = (_a = f.rotation) == null ? void 0 : _a.gaze) == null ? void 0 : _b.strength) && ((_d = (_c = f.rotation) == null ? void 0 : _c.gaze) == null ? void 0 : _d.angle)) {
const leftGaze = [
f.annotations["leftEyeIris"][0][0] + Math.cos(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[2],
f.annotations["leftEyeIris"][0][1] - Math.sin(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[3]
];
ctx.beginPath();
ctx.moveTo(f.annotations["leftEyeIris"][0][0], f.annotations["leftEyeIris"][0][1]);
ctx.strokeStyle = "pink";
ctx.lineTo(leftGaze[0], leftGaze[1]);
ctx.stroke();
const rightGaze = [
f.annotations["rightEyeIris"][0][0] + Math.cos(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[2],
f.annotations["rightEyeIris"][0][1] - Math.sin(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[3]
];
ctx.beginPath();
ctx.moveTo(f.annotations["rightEyeIris"][0][0], f.annotations["rightEyeIris"][0][1]);
ctx.strokeStyle = "pink";
ctx.lineTo(rightGaze[0], rightGaze[1]);
ctx.stroke();
}
}
}
}

View File

@ -1,17 +1,17 @@
2021-05-28 10:43:13 INFO:  @vladmandic/human version 1.9.4
2021-05-28 10:43:13 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-05-28 10:43:13 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-05-28 10:43:13 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":102,"outputBytes":1292,"outputFiles":"dist/tfjs.esm.js"}
2021-05-28 10:43:13 STATE: Build for: node type: node: {"imports":37,"importBytes":431046,"outputBytes":385548,"outputFiles":"dist/human.node.js"}
2021-05-28 10:43:13 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":110,"outputBytes":1300,"outputFiles":"dist/tfjs.esm.js"}
2021-05-28 10:43:13 STATE: Build for: nodeGPU type: node: {"imports":37,"importBytes":431054,"outputBytes":385552,"outputFiles":"dist/human.node-gpu.js"}
2021-05-28 10:43:13 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":149,"outputBytes":1367,"outputFiles":"dist/tfjs.esm.js"}
2021-05-28 10:43:13 STATE: Build for: nodeWASM type: node: {"imports":37,"importBytes":431121,"outputBytes":385624,"outputFiles":"dist/human.node-wasm.js"}
2021-05-28 10:43:13 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2478,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-05-28 10:43:13 STATE: Build for: browserNoBundle type: esm: {"imports":37,"importBytes":431148,"outputBytes":236193,"outputFiles":"dist/human.esm-nobundle.js"}
2021-05-28 10:43:14 STATE: Build for: browserBundle type: tfjs: {"modules":1274,"moduleBytes":4114813,"imports":7,"importBytes":2478,"outputBytes":1111414,"outputFiles":"dist/tfjs.esm.js"}
2021-05-28 10:43:14 STATE: Build for: browserBundle type: iife: {"imports":37,"importBytes":1541168,"outputBytes":1344079,"outputFiles":"dist/human.js"}
2021-05-28 10:43:15 STATE: Build for: browserBundle type: esm: {"imports":37,"importBytes":1541168,"outputBytes":1344071,"outputFiles":"dist/human.esm.js"}
2021-05-28 10:43:15 INFO:  Generate types: ["src/human.ts"]
2021-05-28 10:43:20 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-05-28 10:43:20 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-05-28 15:51:39 INFO:  @vladmandic/human version 1.9.4
2021-05-28 15:51:39 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-05-28 15:51:39 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-05-28 15:51:39 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":102,"outputBytes":1292,"outputFiles":"dist/tfjs.esm.js"}
2021-05-28 15:51:39 STATE: Build for: node type: node: {"imports":37,"importBytes":434116,"outputBytes":387673,"outputFiles":"dist/human.node.js"}
2021-05-28 15:51:39 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":110,"outputBytes":1300,"outputFiles":"dist/tfjs.esm.js"}
2021-05-28 15:51:39 STATE: Build for: nodeGPU type: node: {"imports":37,"importBytes":434124,"outputBytes":387677,"outputFiles":"dist/human.node-gpu.js"}
2021-05-28 15:51:39 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":149,"outputBytes":1367,"outputFiles":"dist/tfjs.esm.js"}
2021-05-28 15:51:39 STATE: Build for: nodeWASM type: node: {"imports":37,"importBytes":434191,"outputBytes":387749,"outputFiles":"dist/human.node-wasm.js"}
2021-05-28 15:51:40 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2478,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-05-28 15:51:40 STATE: Build for: browserNoBundle type: esm: {"imports":37,"importBytes":434218,"outputBytes":237474,"outputFiles":"dist/human.esm-nobundle.js"}
2021-05-28 15:51:40 STATE: Build for: browserBundle type: tfjs: {"modules":1274,"moduleBytes":4114813,"imports":7,"importBytes":2478,"outputBytes":1111414,"outputFiles":"dist/tfjs.esm.js"}
2021-05-28 15:51:41 STATE: Build for: browserBundle type: iife: {"imports":37,"importBytes":1544238,"outputBytes":1345362,"outputFiles":"dist/human.js"}
2021-05-28 15:51:41 STATE: Build for: browserBundle type: esm: {"imports":37,"importBytes":1544238,"outputBytes":1345354,"outputFiles":"dist/human.esm.js"}
2021-05-28 15:51:41 INFO:  Generate types: ["src/human.ts"]
2021-05-28 15:51:46 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-05-28 15:51:46 INFO:  Generate TypeDocs: ["src/human.ts"]

View File

@ -238,6 +238,27 @@ export async function face(inCanvas: HTMLCanvasElement, result: Array<Face>, dra
ctx.fill();
}
}
if (f.rotation?.gaze?.strength && f.rotation?.gaze?.angle) {
const leftGaze = [
f.annotations['leftEyeIris'][0][0] + (Math.cos(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[2]),
f.annotations['leftEyeIris'][0][1] - (Math.sin(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[3]),
];
ctx.beginPath();
ctx.moveTo(f.annotations['leftEyeIris'][0][0], f.annotations['leftEyeIris'][0][1]);
ctx.strokeStyle = 'pink';
ctx.lineTo(leftGaze[0], leftGaze[1]);
ctx.stroke();
const rightGaze = [
f.annotations['rightEyeIris'][0][0] + (Math.cos(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[2]),
f.annotations['rightEyeIris'][0][1] - (Math.sin(f.rotation.gaze.angle) * f.rotation.gaze.strength * f.box[3]),
];
ctx.beginPath();
ctx.moveTo(f.annotations['rightEyeIris'][0][0], f.annotations['rightEyeIris'][0][1]);
ctx.strokeStyle = 'pink';
ctx.lineTo(rightGaze[0], rightGaze[1]);
ctx.stroke();
}
}
}
}

View File

@ -9,9 +9,40 @@ import * as emotion from './emotion/emotion';
import * as faceres from './faceres/faceres';
import { Face } from './result';
const calculateFaceAngle = (face, image_size): { angle: { pitch: number, yaw: number, roll: number }, matrix: [number, number, number, number, number, number, number, number, number] } => {
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
const degrees = (theta) => (theta * 180) / Math.PI;
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
const rad2deg = (theta) => (theta * 180) / Math.PI;
const calculateGaze = (mesh): { angle: number, strength: number } => {
const radians = (pt1, pt2) => Math.atan2(pt1[1] - pt2[1], pt1[0] - pt2[0]); // function to calculate angle between any two points
const offsetIris = [0, 0]; // tbd: iris center may not align with average of eye extremes
const eyeRatio = 5; // factor to normalize changes x vs y
const left = mesh[33][2] > mesh[263][2]; // pick left or right eye depending which one is closer bazed on outsize point z axis
const irisCenter = left ? mesh[473] : mesh[468];
const eyeCenter = left // eye center is average of extreme points on x axis for both x and y, ignoring y extreme points as eyelids naturally open/close more when gazing up/down so relative point is less precise
? [(mesh[133][0] + mesh[33][0]) / 2, (mesh[133][1] + mesh[33][1]) / 2]
: [(mesh[263][0] + mesh[362][0]) / 2, (mesh[263][1] + mesh[362][1]) / 2];
const eyeSize = left // eye size is difference between extreme points for both x and y, used to normalize & squarify eye dimensions
? [mesh[133][0] - mesh[33][0], mesh[23][1] - mesh[27][1]]
: [mesh[263][0] - mesh[362][0], mesh[253][1] - mesh[257][1]];
const eyeDiff = [ // x distance between extreme point and center point normalized with eye size
(eyeCenter[0] - irisCenter[0]) / eyeSize[0] - offsetIris[0],
eyeRatio * (irisCenter[1] - eyeCenter[1]) / eyeSize[1] - offsetIris[1],
];
const vectorLength = Math.sqrt((eyeDiff[0] ** 2) + (eyeDiff[1] ** 2)); // vector length is a diagonal between two differences
const vectorAngle = radians([0, 0], eyeDiff); // using eyeDiff instead eyeCenter/irisCenter combo due to manual adjustments
// vectorAngle right=0*pi, up=1*pi/2, left=1*pi, down=3*pi/2
return { angle: vectorAngle, strength: vectorLength };
};
const calculateFaceAngle = (face, imageSize): {
angle: { pitch: number, yaw: number, roll: number },
matrix: [number, number, number, number, number, number, number, number, number],
gaze: { angle: number, strength: number },
} => {
// const degrees = (theta) => Math.abs(((theta * 180) / Math.PI) % 360);
const normalize = (v) => { // normalize vector
const length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
@ -71,15 +102,16 @@ const calculateFaceAngle = (face, image_size): { angle: { pitch: number, yaw: nu
return angle;
};
// initialize gaze and mesh
const mesh = face.meshRaw;
if (!mesh || mesh.length < 300) return { angle: { pitch: 0, yaw: 0, roll: 0 }, matrix: [1, 0, 0, 0, 1, 0, 0, 0, 1] };
if (!mesh || mesh.length < 300) return { angle: { pitch: 0, yaw: 0, roll: 0 }, matrix: [1, 0, 0, 0, 1, 0, 0, 0, 1], gaze: { angle: 0, strength: 0 } };
const size = Math.max(face.boxRaw[2] * image_size[0], face.boxRaw[3] * image_size[1]) / 1.5;
const size = Math.max(face.boxRaw[2] * imageSize[0], face.boxRaw[3] * imageSize[1]) / 1.5;
// top, bottom, left, right
const pts = [mesh[10], mesh[152], mesh[234], mesh[454]].map((pt) => [
// make the xyz coordinates proportional, independent of the image/box size
pt[0] * image_size[0] / size,
pt[1] * image_size[1] / size,
pt[0] * imageSize[0] / size,
pt[1] * imageSize[1] / size,
pt[2],
]);
@ -98,7 +130,11 @@ const calculateFaceAngle = (face, image_size): { angle: { pitch: number, yaw: nu
];
const angle = rotationMatrixToEulerAngle(matrix);
// const angle = meshToEulerAngle(mesh);
return { angle, matrix };
// we have iris keypoints so we can calculate gaze direction
const gaze = mesh.length === 478 ? calculateGaze(mesh) : { angle: 0, strength: 0 };
return { angle, matrix, gaze };
};
export const detectFace = async (parent, input): Promise<Face[]> => {

View File

@ -73,14 +73,12 @@ export const iris = (res): Gesture[] => {
const rightIrisCenterY = Math.abs(res[i].mesh[145][1] - res[i].annotations.rightEyeIris[0][1]) / res[i].box[3];
const leftIrisCenterY = Math.abs(res[i].mesh[374][1] - res[i].annotations.leftEyeIris[0][1]) / res[i].box[3];
if (leftIrisCenterY < 0.01 || rightIrisCenterY < 0.01 || leftIrisCenterY > 0.025 || rightIrisCenterY > 0.025) center = false;
if (leftIrisCenterY < 0.01 || rightIrisCenterY < 0.01 || leftIrisCenterY > 0.022 || rightIrisCenterY > 0.022) center = false;
if (leftIrisCenterY < 0.01 || rightIrisCenterY < 0.01) gestures.push({ iris: i, gesture: 'looking down' });
if (leftIrisCenterY > 0.025 || rightIrisCenterY > 0.025) gestures.push({ iris: i, gesture: 'looking up' });
if (leftIrisCenterY > 0.022 || rightIrisCenterY > 0.022) gestures.push({ iris: i, gesture: 'looking up' });
// still center;
if (center) gestures.push({ iris: i, gesture: 'looking center' });
console.log(leftIrisCenterX, rightIrisCenterX, leftIrisCenterY, rightIrisCenterY, gestures);
}
return gestures;
};

View File

@ -28,6 +28,7 @@ import { Tensor } from '../dist/tfjs.esm.js';
* - rotation: face rotiation that contains both angles and matrix used for 3d transformations
* - angle: face angle as object with values for roll, yaw and pitch angles
* - matrix: 3d transofrmation matrix as array of numeric values
* - gaze: gaze direction as object with values for agngle in radians and strengthss
* - tensor: face tensor as Tensor object which contains detected face
*/
export interface Face {
@ -49,6 +50,7 @@ export interface Face {
rotation: {
angle: { roll: number, yaw: number, pitch: number },
matrix: [number, number, number, number, number, number, number, number, number],
gaze: { angle: number, strength: number },
}
tensor: typeof Tensor,
}

View File

@ -1,120 +1,120 @@
2021-05-25 08:46:04 INFO:  @vladmandic/human version 1.9.3
2021-05-25 08:46:04 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-05-25 08:46:04 INFO:  tests: ["test-node.js","test-node-gpu.js","test-node-wasm.js"]
2021-05-25 08:46:04 INFO:  test-node.js start
2021-05-25 08:46:05 STATE: test-node.js passed: create human
2021-05-25 08:46:05 INFO:  test-node.js human version: 1.9.3
2021-05-25 08:46:05 INFO:  test-node.js platform: linux x64 agent: NodeJS v16.0.0
2021-05-25 08:46:05 INFO:  test-node.js tfjs version: 3.6.0
2021-05-25 08:46:05 STATE: test-node.js passed: set backend: tensorflow
2021-05-25 08:46:05 STATE: test-node.js passed: load models
2021-05-25 08:46:05 STATE: test-node.js result: defined models: 13 loaded models: 6
2021-05-25 08:46:05 STATE: test-node.js passed: warmup: none default
2021-05-25 08:46:07 STATE: test-node.js passed: warmup: face default
2021-05-25 08:46:07 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 5 object: 1 person: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.8246909379959106,"class":"person"} {"score":0.96,"keypoints":5}
2021-05-25 08:46:07 DATA:  test-node.js result: performance: load: 346 total: 1673
2021-05-25 08:46:09 STATE: test-node.js passed: warmup: body default
2021-05-25 08:46:09 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":29.5,"gender":"female"} {"score":0.7261000871658325,"class":"person"} {"score":0.92,"keypoints":17}
2021-05-25 08:46:09 DATA:  test-node.js result: performance: load: 346 total: 1665
2021-05-25 08:46:09 INFO:  test-node.js test body variants
2021-05-25 08:46:10 STATE: test-node.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-25 08:46:11 STATE: test-node.js passed: detect: assets/human-sample-body.jpg posenet
2021-05-25 08:46:11 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1} {"score":0.7261000871658325,"class":"person"} {"score":0.91,"keypoints":17}
2021-05-25 08:46:11 DATA:  test-node.js result: performance: load: 346 total: 1017
2021-05-25 08:46:12 STATE: test-node.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-25 08:46:12 STATE: test-node.js passed: detect: assets/human-sample-body.jpg blazepose
2021-05-25 08:46:12 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1} {"score":0.7261000871658325,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:12 DATA:  test-node.js result: performance: load: 346 total: 418
2021-05-25 08:46:13 STATE: test-node.js passed: detect: random default
2021-05-25 08:46:13 DATA:  test-node.js result: face: 0 body: 1 hand: 0 gesture: 1 object: 0 person: 0 {} {} {"score":1,"keypoints":39}
2021-05-25 08:46:13 DATA:  test-node.js result: performance: load: 346 total: 888
2021-05-25 08:46:13 INFO:  test-node.js test: first instance
2021-05-25 08:46:13 STATE: test-node.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-05-25 08:46:15 STATE: test-node.js passed: detect: assets/sample-me.jpg default
2021-05-25 08:46:15 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 2 person: 1 {"confidence":1,"age":39.2,"gender":"male"} {"score":0.6820425987243652,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:15 DATA:  test-node.js result: performance: load: 346 total: 1761
2021-05-25 08:46:15 INFO:  test-node.js test: second instance
2021-05-25 08:46:16 STATE: test-node.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-05-25 08:46:17 STATE: test-node.js passed: detect: assets/sample-me.jpg default
2021-05-25 08:46:17 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 2 person: 1 {"confidence":1,"age":39.2,"gender":"male"} {"score":0.6820425987243652,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:17 DATA:  test-node.js result: performance: load: 4 total: 1670
2021-05-25 08:46:17 INFO:  test-node.js test: concurrent
2021-05-25 08:46:17 STATE: test-node.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-05-25 08:46:17 STATE: test-node.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-05-25 08:46:18 STATE: test-node.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-25 08:46:19 STATE: test-node.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-25 08:46:25 STATE: test-node.js passed: detect: assets/human-sample-face.jpg default
2021-05-25 08:46:25 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 1 person: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.8257162570953369,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:25 DATA:  test-node.js result: performance: load: 346 total: 5919
2021-05-25 08:46:25 STATE: test-node.js passed: detect: assets/human-sample-face.jpg default
2021-05-25 08:46:25 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 1 person: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.8257162570953369,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:25 DATA:  test-node.js result: performance: load: 4 total: 5919
2021-05-25 08:46:25 STATE: test-node.js passed: detect: assets/human-sample-body.jpg default
2021-05-25 08:46:25 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.7273815870285034,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:25 DATA:  test-node.js result: performance: load: 346 total: 5919
2021-05-25 08:46:25 STATE: test-node.js passed: detect: assets/human-sample-body.jpg default
2021-05-25 08:46:25 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.7273815870285034,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:25 DATA:  test-node.js result: performance: load: 4 total: 5919
2021-05-25 08:46:25 INFO:  test-node.js test complete: 20499 ms
2021-05-25 08:46:25 INFO:  test-node-gpu.js start
2021-05-25 08:46:26 WARN:  test-node-gpu.js stderr: 2021-05-25 08:46:26.515096: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory
2021-05-25 08:46:26 WARN:  test-node-gpu.js stderr: 2021-05-25 08:46:26.635286: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library 'libcuda.so.1'; dlerror: libcuda.so.1: cannot open shared object file: No such file or directory
2021-05-25 08:46:26 WARN:  test-node-gpu.js stderr: 2021-05-25 08:46:26.635353: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (wyse): /proc/driver/nvidia/version does not exist
2021-05-25 08:46:26 STATE: test-node-gpu.js passed: create human
2021-05-25 08:46:26 INFO:  test-node-gpu.js human version: 1.9.3
2021-05-25 08:46:26 INFO:  test-node-gpu.js platform: linux x64 agent: NodeJS v16.0.0
2021-05-25 08:46:26 INFO:  test-node-gpu.js tfjs version: 3.6.0
2021-05-25 08:46:27 STATE: test-node-gpu.js passed: set backend: tensorflow
2021-05-25 08:46:27 STATE: test-node-gpu.js passed: load models
2021-05-25 08:46:27 STATE: test-node-gpu.js result: defined models: 13 loaded models: 6
2021-05-25 08:46:27 STATE: test-node-gpu.js passed: warmup: none default
2021-05-25 08:46:28 STATE: test-node-gpu.js passed: warmup: face default
2021-05-25 08:46:28 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 5 object: 1 person: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.8246909379959106,"class":"person"} {"score":0.96,"keypoints":5}
2021-05-25 08:46:28 DATA:  test-node-gpu.js result: performance: load: 326 total: 1742
2021-05-25 08:46:30 STATE: test-node-gpu.js passed: warmup: body default
2021-05-25 08:46:30 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":29.5,"gender":"female"} {"score":0.7261000871658325,"class":"person"} {"score":0.92,"keypoints":17}
2021-05-25 08:46:30 DATA:  test-node-gpu.js result: performance: load: 326 total: 1599
2021-05-25 08:46:30 INFO:  test-node-gpu.js test body variants
2021-05-25 08:46:31 STATE: test-node-gpu.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-25 08:46:32 STATE: test-node-gpu.js passed: detect: assets/human-sample-body.jpg posenet
2021-05-25 08:46:32 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1} {"score":0.7261000871658325,"class":"person"} {"score":0.91,"keypoints":17}
2021-05-25 08:46:32 DATA:  test-node-gpu.js result: performance: load: 326 total: 1448
2021-05-25 08:46:34 STATE: test-node-gpu.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-25 08:46:34 STATE: test-node-gpu.js passed: detect: assets/human-sample-body.jpg blazepose
2021-05-25 08:46:34 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1} {"score":0.7261000871658325,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:34 DATA:  test-node-gpu.js result: performance: load: 326 total: 627
2021-05-25 08:46:35 STATE: test-node-gpu.js passed: detect: random default
2021-05-25 08:46:35 DATA:  test-node-gpu.js result: face: 0 body: 1 hand: 0 gesture: 1 object: 1 person: 0 {} {"score":0.7261000871658325,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:35 DATA:  test-node-gpu.js result: performance: load: 326 total: 258
2021-05-25 08:46:35 INFO:  test-node-gpu.js test: first instance
2021-05-25 08:46:35 STATE: test-node-gpu.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-05-25 08:46:35 STATE: test-node-gpu.js passed: detect: assets/sample-me.jpg default
2021-05-25 08:46:35 DATA:  test-node-gpu.js result: face: 0 body: 1 hand: 0 gesture: 1 object: 1 person: 0 {} {"score":0.7261000871658325,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:35 DATA:  test-node-gpu.js result: performance: load: 326 total: 234
2021-05-25 08:46:35 INFO:  test-node-gpu.js test: second instance
2021-05-25 08:46:36 STATE: test-node-gpu.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-05-25 08:46:38 STATE: test-node-gpu.js passed: detect: assets/sample-me.jpg default
2021-05-25 08:46:38 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 2 person: 1 {"confidence":1,"age":39.2,"gender":"male"} {"score":0.6820425987243652,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:38 DATA:  test-node-gpu.js result: performance: load: 4 total: 2409
2021-05-25 08:46:38 INFO:  test-node-gpu.js test: concurrent
2021-05-25 08:46:38 STATE: test-node-gpu.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-05-25 08:46:38 STATE: test-node-gpu.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-05-25 08:46:39 STATE: test-node-gpu.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-25 08:46:40 STATE: test-node-gpu.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-25 08:46:50 STATE: test-node-gpu.js passed: detect: assets/human-sample-face.jpg default
2021-05-25 08:46:50 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 1 person: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.8257162570953369,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:50 DATA:  test-node-gpu.js result: performance: load: 326 total: 9194
2021-05-25 08:46:50 STATE: test-node-gpu.js passed: detect: assets/human-sample-face.jpg default
2021-05-25 08:46:50 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 1 person: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.8257162570953369,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:50 DATA:  test-node-gpu.js result: performance: load: 4 total: 9194
2021-05-25 08:46:50 STATE: test-node-gpu.js passed: detect: assets/human-sample-body.jpg default
2021-05-25 08:46:50 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.7273815870285034,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:50 DATA:  test-node-gpu.js result: performance: load: 326 total: 9194
2021-05-25 08:46:50 STATE: test-node-gpu.js passed: detect: assets/human-sample-body.jpg default
2021-05-25 08:46:50 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.7273815870285034,"class":"person"} {"score":1,"keypoints":39}
2021-05-25 08:46:50 DATA:  test-node-gpu.js result: performance: load: 4 total: 9194
2021-05-25 08:46:50 INFO:  test-node-gpu.js test complete: 23315 ms
2021-05-25 08:46:50 INFO:  test-node-wasm.js start
2021-05-25 08:46:50 ERROR: test-node-wasm.js failed: model server: request to http://localhost:10030/models/ failed, reason: connect ECONNREFUSED 127.0.0.1:10030
2021-05-25 08:46:50 ERROR: test-node-wasm.js aborting test
2021-05-25 08:46:50 INFO:  status: {"passed":46,"failed":1}
2021-05-28 15:52:57 INFO:  @vladmandic/human version 1.9.4
2021-05-28 15:52:57 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-05-28 15:52:57 INFO:  tests: ["test-node.js","test-node-gpu.js","test-node-wasm.js"]
2021-05-28 15:52:57 INFO:  test-node.js start
2021-05-28 15:52:59 STATE: test-node.js passed: create human
2021-05-28 15:52:59 INFO:  test-node.js human version: 1.9.4
2021-05-28 15:52:59 INFO:  test-node.js platform: linux x64 agent: NodeJS v16.0.0
2021-05-28 15:52:59 INFO:  test-node.js tfjs version: 3.6.0
2021-05-28 15:52:59 STATE: test-node.js passed: set backend: tensorflow
2021-05-28 15:52:59 STATE: test-node.js passed: load models
2021-05-28 15:52:59 STATE: test-node.js result: defined models: 13 loaded models: 6
2021-05-28 15:52:59 STATE: test-node.js passed: warmup: none default
2021-05-28 15:53:01 STATE: test-node.js passed: warmup: face default
2021-05-28 15:53:01 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.8246909379959106,"class":"person"} {"score":0.96,"keypoints":5}
2021-05-28 15:53:01 DATA:  test-node.js result: performance: load: 397 total: 1679
2021-05-28 15:53:02 STATE: test-node.js passed: warmup: body default
2021-05-28 15:53:02 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":29.5,"gender":"female"} {"score":0.7261000871658325,"class":"person"} {"score":0.92,"keypoints":17}
2021-05-28 15:53:02 DATA:  test-node.js result: performance: load: 397 total: 1462
2021-05-28 15:53:02 INFO:  test-node.js test body variants
2021-05-28 15:53:03 STATE: test-node.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-28 15:53:04 STATE: test-node.js passed: detect: assets/human-sample-body.jpg posenet
2021-05-28 15:53:04 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1} {"score":0.7261000871658325,"class":"person"} {"score":0.91,"keypoints":17}
2021-05-28 15:53:04 DATA:  test-node.js result: performance: load: 397 total: 957
2021-05-28 15:53:05 STATE: test-node.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-28 15:53:06 STATE: test-node.js passed: detect: assets/human-sample-body.jpg blazepose
2021-05-28 15:53:06 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1} {"score":0.7261000871658325,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:06 DATA:  test-node.js result: performance: load: 397 total: 523
2021-05-28 15:53:07 STATE: test-node.js passed: detect: random default
2021-05-28 15:53:07 DATA:  test-node.js result: face: 0 body: 1 hand: 0 gesture: 1 object: 0 person: 0 {} {} {"score":1,"keypoints":39}
2021-05-28 15:53:07 DATA:  test-node.js result: performance: load: 397 total: 970
2021-05-28 15:53:07 INFO:  test-node.js test: first instance
2021-05-28 15:53:07 STATE: test-node.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-05-28 15:53:09 STATE: test-node.js passed: detect: assets/sample-me.jpg default
2021-05-28 15:53:09 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 4 object: 2 person: 1 {"confidence":1,"age":39.2,"gender":"male"} {"score":0.6820425987243652,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:09 DATA:  test-node.js result: performance: load: 397 total: 1591
2021-05-28 15:53:09 INFO:  test-node.js test: second instance
2021-05-28 15:53:09 STATE: test-node.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-05-28 15:53:11 STATE: test-node.js passed: detect: assets/sample-me.jpg default
2021-05-28 15:53:11 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 4 object: 2 person: 1 {"confidence":1,"age":39.2,"gender":"male"} {"score":0.6820425987243652,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:11 DATA:  test-node.js result: performance: load: 4 total: 1475
2021-05-28 15:53:11 INFO:  test-node.js test: concurrent
2021-05-28 15:53:11 STATE: test-node.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-05-28 15:53:11 STATE: test-node.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-05-28 15:53:12 STATE: test-node.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-28 15:53:13 STATE: test-node.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-28 15:53:18 STATE: test-node.js passed: detect: assets/human-sample-face.jpg default
2021-05-28 15:53:18 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 4 object: 1 person: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.8257162570953369,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:18 DATA:  test-node.js result: performance: load: 397 total: 5615
2021-05-28 15:53:18 STATE: test-node.js passed: detect: assets/human-sample-face.jpg default
2021-05-28 15:53:18 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 4 object: 1 person: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.8257162570953369,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:18 DATA:  test-node.js result: performance: load: 4 total: 5615
2021-05-28 15:53:18 STATE: test-node.js passed: detect: assets/human-sample-body.jpg default
2021-05-28 15:53:18 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.7273815870285034,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:18 DATA:  test-node.js result: performance: load: 397 total: 5615
2021-05-28 15:53:18 STATE: test-node.js passed: detect: assets/human-sample-body.jpg default
2021-05-28 15:53:18 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.7273815870285034,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:18 DATA:  test-node.js result: performance: load: 4 total: 5615
2021-05-28 15:53:18 INFO:  test-node.js test complete: 19711 ms
2021-05-28 15:53:18 INFO:  test-node-gpu.js start
2021-05-28 15:53:20 WARN:  test-node-gpu.js stderr: 2021-05-28 15:53:20.148509: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory
2021-05-28 15:53:20 WARN:  test-node-gpu.js stderr: 2021-05-28 15:53:20.400714: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library 'libcuda.so.1'; dlerror: libcuda.so.1: cannot open shared object file: No such file or directory
2021-05-28 15:53:20 WARN:  test-node-gpu.js stderr: 2021-05-28 15:53:20.400783: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (wyse): /proc/driver/nvidia/version does not exist
2021-05-28 15:53:20 STATE: test-node-gpu.js passed: create human
2021-05-28 15:53:20 INFO:  test-node-gpu.js human version: 1.9.4
2021-05-28 15:53:20 INFO:  test-node-gpu.js platform: linux x64 agent: NodeJS v16.0.0
2021-05-28 15:53:20 INFO:  test-node-gpu.js tfjs version: 3.6.0
2021-05-28 15:53:20 STATE: test-node-gpu.js passed: set backend: tensorflow
2021-05-28 15:53:20 STATE: test-node-gpu.js passed: load models
2021-05-28 15:53:20 STATE: test-node-gpu.js result: defined models: 13 loaded models: 6
2021-05-28 15:53:20 STATE: test-node-gpu.js passed: warmup: none default
2021-05-28 15:53:22 STATE: test-node-gpu.js passed: warmup: face default
2021-05-28 15:53:22 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.8246909379959106,"class":"person"} {"score":0.96,"keypoints":5}
2021-05-28 15:53:22 DATA:  test-node-gpu.js result: performance: load: 310 total: 1956
2021-05-28 15:53:24 STATE: test-node-gpu.js passed: warmup: body default
2021-05-28 15:53:24 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":29.5,"gender":"female"} {"score":0.7261000871658325,"class":"person"} {"score":0.92,"keypoints":17}
2021-05-28 15:53:24 DATA:  test-node-gpu.js result: performance: load: 310 total: 1601
2021-05-28 15:53:24 INFO:  test-node-gpu.js test body variants
2021-05-28 15:53:25 STATE: test-node-gpu.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-28 15:53:26 STATE: test-node-gpu.js passed: detect: assets/human-sample-body.jpg posenet
2021-05-28 15:53:26 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1} {"score":0.7261000871658325,"class":"person"} {"score":0.91,"keypoints":17}
2021-05-28 15:53:26 DATA:  test-node-gpu.js result: performance: load: 310 total: 1047
2021-05-28 15:53:27 STATE: test-node-gpu.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-28 15:53:27 STATE: test-node-gpu.js passed: detect: assets/human-sample-body.jpg blazepose
2021-05-28 15:53:27 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1} {"score":0.7261000871658325,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:27 DATA:  test-node-gpu.js result: performance: load: 310 total: 436
2021-05-28 15:53:28 STATE: test-node-gpu.js passed: detect: random default
2021-05-28 15:53:28 DATA:  test-node-gpu.js result: face: 0 body: 1 hand: 0 gesture: 1 object: 1 person: 0 {} {"score":0.7261000871658325,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:28 DATA:  test-node-gpu.js result: performance: load: 310 total: 209
2021-05-28 15:53:28 INFO:  test-node-gpu.js test: first instance
2021-05-28 15:53:28 STATE: test-node-gpu.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-05-28 15:53:28 STATE: test-node-gpu.js passed: detect: assets/sample-me.jpg default
2021-05-28 15:53:28 DATA:  test-node-gpu.js result: face: 0 body: 1 hand: 0 gesture: 1 object: 1 person: 0 {} {"score":0.7261000871658325,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:28 DATA:  test-node-gpu.js result: performance: load: 310 total: 184
2021-05-28 15:53:28 INFO:  test-node-gpu.js test: second instance
2021-05-28 15:53:29 STATE: test-node-gpu.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-05-28 15:53:30 STATE: test-node-gpu.js passed: detect: assets/sample-me.jpg default
2021-05-28 15:53:30 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 4 object: 2 person: 1 {"confidence":1,"age":39.2,"gender":"male"} {"score":0.6820425987243652,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:30 DATA:  test-node-gpu.js result: performance: load: 2 total: 1487
2021-05-28 15:53:30 INFO:  test-node-gpu.js test: concurrent
2021-05-28 15:53:30 STATE: test-node-gpu.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-05-28 15:53:30 STATE: test-node-gpu.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-05-28 15:53:31 STATE: test-node-gpu.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-28 15:53:32 STATE: test-node-gpu.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-05-28 15:53:38 STATE: test-node-gpu.js passed: detect: assets/human-sample-face.jpg default
2021-05-28 15:53:38 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 4 object: 1 person: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.8257162570953369,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:38 DATA:  test-node-gpu.js result: performance: load: 310 total: 5528
2021-05-28 15:53:38 STATE: test-node-gpu.js passed: detect: assets/human-sample-face.jpg default
2021-05-28 15:53:38 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 4 object: 1 person: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.8257162570953369,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:38 DATA:  test-node-gpu.js result: performance: load: 2 total: 5528
2021-05-28 15:53:38 STATE: test-node-gpu.js passed: detect: assets/human-sample-body.jpg default
2021-05-28 15:53:38 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.7273815870285034,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:38 DATA:  test-node-gpu.js result: performance: load: 310 total: 5528
2021-05-28 15:53:38 STATE: test-node-gpu.js passed: detect: assets/human-sample-body.jpg default
2021-05-28 15:53:38 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 1 person: 1 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.7273815870285034,"class":"person"} {"score":1,"keypoints":39}
2021-05-28 15:53:38 DATA:  test-node-gpu.js result: performance: load: 2 total: 5528
2021-05-28 15:53:38 INFO:  test-node-gpu.js test complete: 17887 ms
2021-05-28 15:53:38 INFO:  test-node-wasm.js start
2021-05-28 15:53:38 ERROR: test-node-wasm.js failed: model server: request to http://localhost:10030/models/ failed, reason: connect ECONNREFUSED 127.0.0.1:10030
2021-05-28 15:53:38 ERROR: test-node-wasm.js aborting test
2021-05-28 15:53:38 INFO:  status: {"passed":46,"failed":1}

File diff suppressed because one or more lines are too long

View File

@ -91,6 +91,7 @@
<li>rotation: face rotiation that contains both angles and matrix used for 3d transformations</li>
<li>angle: face angle as object with values for roll, yaw and pitch angles</li>
<li>matrix: 3d transofrmation matrix as array of numeric values</li>
<li>gaze: gaze direction as object with values for agngle in radians and strengthss</li>
<li>tensor: face tensor as Tensor object which contains detected face</li>
</ul>
</div>
@ -242,7 +243,7 @@
<section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface">
<a name="rotation" class="tsd-anchor"></a>
<h3>rotation</h3>
<div class="tsd-signature tsd-kind-icon">rotation<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">{ </span>angle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>pitch<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">; </span>roll<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">; </span>yaw<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">; </span>matrix<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">[</span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">]</span><span class="tsd-signature-symbol"> }</span></div>
<div class="tsd-signature tsd-kind-icon">rotation<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">{ </span>angle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>pitch<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">; </span>roll<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">; </span>yaw<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">; </span>gaze<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>angle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">; </span>strength<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">; </span>matrix<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">[</span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">]</span><span class="tsd-signature-symbol"> }</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-type-declaration">
@ -262,6 +263,17 @@
</li>
</ul>
</li>
<li class="tsd-parameter">
<h5>gaze<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>angle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">; </span>strength<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> }</span></h5>
<ul class="tsd-parameters">
<li class="tsd-parameter">
<h5>angle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></h5>
</li>
<li class="tsd-parameter">
<h5>strength<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></h5>
</li>
</ul>
</li>
<li class="tsd-parameter">
<h5>matrix<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">[</span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">, </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">]</span></h5>
</li>

5
types/result.d.ts vendored
View File

@ -26,6 +26,7 @@ import { Tensor } from '../dist/tfjs.esm.js';
* - rotation: face rotiation that contains both angles and matrix used for 3d transformations
* - angle: face angle as object with values for roll, yaw and pitch angles
* - matrix: 3d transofrmation matrix as array of numeric values
* - gaze: gaze direction as object with values for agngle in radians and strengthss
* - tensor: face tensor as Tensor object which contains detected face
*/
export interface Face {
@ -57,6 +58,10 @@ export interface Face {
pitch: number;
};
matrix: [number, number, number, number, number, number, number, number, number];
gaze: {
angle: number;
strength: number;
};
};
tensor: typeof Tensor;
}