human/demo/draw.js

200 lines
7.4 KiB
JavaScript
Raw Normal View History

2020-11-04 16:18:22 +01:00
async function drawGesture(result, canvas, ui) {
if (!result) return;
const ctx = canvas.getContext('2d');
ctx.font = ui.baseFont;
ctx.fillStyle = ui.baseLabel;
let i = 1;
for (const [key, val] of Object.entries(result)) {
if (val.length > 0) {
const label = `${key}: ${val.join(', ')}`;
ctx.fillText(label, 6, i * (ui.baseLineHeight + 24));
i += 1;
}
}
}
2020-10-17 13:34:45 +02:00
async function drawFace(result, canvas, ui, triangulation) {
if (!result) return;
const ctx = canvas.getContext('2d');
for (const face of result) {
ctx.font = ui.baseFont;
ctx.strokeStyle = ui.baseColor;
ctx.fillStyle = ui.baseColor;
ctx.lineWidth = ui.baseLineWidth;
ctx.beginPath();
if (ui.drawBoxes) {
ctx.rect(face.box[0], face.box[1], face.box[2], face.box[3]);
}
// silly hack since fillText does not suport new line
const labels = [];
2020-11-06 19:50:16 +01:00
// labels.push(`${Math.trunc(100 * face.confidence)}% face`);
2020-11-06 17:39:39 +01:00
if (face.genderConfidence) labels.push(`${Math.trunc(100 * face.genderConfidence)}% ${face.gender || ''}`);
2020-10-18 20:14:05 +02:00
if (face.age) labels.push(`age: ${face.age || ''}`);
2020-10-17 13:34:45 +02:00
if (face.iris) labels.push(`iris: ${face.iris}`);
2020-11-05 21:38:09 +01:00
if (face.emotion && face.emotion.length > 0) {
const emotion = face.emotion.map((a) => `${Math.trunc(100 * a.score)}% ${a.emotion}`);
labels.push(emotion.join(' '));
}
2020-10-17 13:34:45 +02:00
ctx.fillStyle = ui.baseLabel;
2020-11-04 16:18:22 +01:00
for (const i in labels) ctx.fillText(labels[i], face.box[0] + 8, face.box[1] + 24 + ((i + 1) * ui.baseLineHeight));
2020-10-17 13:34:45 +02:00
ctx.stroke();
ctx.lineWidth = 1;
if (face.mesh) {
if (ui.drawPoints) {
for (const point of face.mesh) {
ctx.fillStyle = ui.useDepth ? `rgba(${127.5 + (2 * point[2])}, ${127.5 - (2 * point[2])}, 255, 0.5)` : ui.baseColor;
ctx.beginPath();
ctx.arc(point[0], point[1], 2, 0, 2 * Math.PI);
ctx.fill();
}
}
if (ui.drawPolygons) {
for (let i = 0; i < triangulation.length / 3; i++) {
const points = [
triangulation[i * 3 + 0],
triangulation[i * 3 + 1],
triangulation[i * 3 + 2],
].map((index) => face.mesh[index]);
const path = new Path2D();
path.moveTo(points[0][0], points[0][1]);
for (const point of points) {
path.lineTo(point[0], point[1]);
}
path.closePath();
ctx.strokeStyle = ui.useDepth ? `rgba(${127.5 + (2 * points[0][2])}, ${127.5 - (2 * points[0][2])}, 255, 0.3)` : ui.baseColor;
ctx.stroke(path);
if (ui.fillPolygons) {
ctx.fillStyle = ui.useDepth ? `rgba(${127.5 + (2 * points[0][2])}, ${127.5 - (2 * points[0][2])}, 255, 0.3)` : ui.baseColor;
ctx.fill(path);
}
}
}
}
}
}
async function drawBody(result, canvas, ui) {
if (!result) return;
const ctx = canvas.getContext('2d');
2020-10-30 12:32:35 +01:00
ctx.lineJoin = 'round';
2020-10-17 13:34:45 +02:00
for (const pose of result) {
ctx.fillStyle = ui.baseColor;
ctx.strokeStyle = ui.baseColor;
ctx.font = ui.baseFont;
ctx.lineWidth = ui.baseLineWidth;
if (ui.drawPoints) {
for (const point of pose.keypoints) {
ctx.beginPath();
ctx.arc(point.position.x, point.position.y, 2, 0, 2 * Math.PI);
ctx.fill();
}
}
if (ui.drawPolygons) {
const path = new Path2D();
let part;
// torso
part = pose.keypoints.find((a) => a.part === 'leftShoulder');
path.moveTo(part.position.x, part.position.y);
part = pose.keypoints.find((a) => a.part === 'rightShoulder');
path.lineTo(part.position.x, part.position.y);
part = pose.keypoints.find((a) => a.part === 'rightHip');
path.lineTo(part.position.x, part.position.y);
part = pose.keypoints.find((a) => a.part === 'leftHip');
path.lineTo(part.position.x, part.position.y);
part = pose.keypoints.find((a) => a.part === 'leftShoulder');
path.lineTo(part.position.x, part.position.y);
// legs
part = pose.keypoints.find((a) => a.part === 'leftHip');
path.moveTo(part.position.x, part.position.y);
part = pose.keypoints.find((a) => a.part === 'leftKnee');
path.lineTo(part.position.x, part.position.y);
part = pose.keypoints.find((a) => a.part === 'leftAnkle');
path.lineTo(part.position.x, part.position.y);
part = pose.keypoints.find((a) => a.part === 'rightHip');
path.moveTo(part.position.x, part.position.y);
part = pose.keypoints.find((a) => a.part === 'rightKnee');
path.lineTo(part.position.x, part.position.y);
part = pose.keypoints.find((a) => a.part === 'rightAnkle');
path.lineTo(part.position.x, part.position.y);
// arms
2020-10-30 12:32:35 +01:00
part = pose.keypoints.find((a) => a.part === 'rightShoulder');
2020-10-17 13:34:45 +02:00
path.moveTo(part.position.x, part.position.y);
2020-10-30 12:32:35 +01:00
part = pose.keypoints.find((a) => a.part === 'leftShoulder');
path.lineTo(part.position.x, part.position.y);
2020-10-17 13:34:45 +02:00
part = pose.keypoints.find((a) => a.part === 'leftElbow');
path.lineTo(part.position.x, part.position.y);
part = pose.keypoints.find((a) => a.part === 'leftWrist');
path.lineTo(part.position.x, part.position.y);
// arms
2020-10-30 12:32:35 +01:00
part = pose.keypoints.find((a) => a.part === 'leftShoulder');
2020-10-17 13:34:45 +02:00
path.moveTo(part.position.x, part.position.y);
2020-10-30 12:32:35 +01:00
part = pose.keypoints.find((a) => a.part === 'rightShoulder');
path.lineTo(part.position.x, part.position.y);
2020-10-17 13:34:45 +02:00
part = pose.keypoints.find((a) => a.part === 'rightElbow');
path.lineTo(part.position.x, part.position.y);
part = pose.keypoints.find((a) => a.part === 'rightWrist');
path.lineTo(part.position.x, part.position.y);
// draw all
ctx.stroke(path);
}
}
}
async function drawHand(result, canvas, ui) {
if (!result) return;
const ctx = canvas.getContext('2d');
2020-10-30 12:32:35 +01:00
ctx.lineJoin = 'round';
2020-10-17 13:34:45 +02:00
for (const hand of result) {
ctx.font = ui.baseFont;
ctx.lineWidth = ui.baseLineWidth;
if (ui.drawBoxes) {
ctx.lineWidth = ui.baseLineWidth;
ctx.beginPath();
ctx.strokeStyle = ui.baseColor;
ctx.fillStyle = ui.baseColor;
ctx.rect(hand.box[0], hand.box[1], hand.box[2], hand.box[3]);
ctx.fillStyle = ui.baseLabel;
ctx.fillText('hand', hand.box[0] + 2, hand.box[1] + 22, hand.box[2]);
ctx.stroke();
}
if (ui.drawPoints) {
2020-11-04 20:59:30 +01:00
if (hand.landmarks && hand.landmarks.length > 0) {
for (const point of hand.landmarks) {
ctx.fillStyle = ui.useDepth ? `rgba(${127.5 + (2 * point[2])}, ${127.5 - (2 * point[2])}, 255, 0.5)` : ui.baseColor;
ctx.beginPath();
ctx.arc(point[0], point[1], 2, 0, 2 * Math.PI);
ctx.fill();
}
2020-10-17 13:34:45 +02:00
}
}
if (ui.drawPolygons) {
const addPart = (part) => {
2020-11-04 20:59:30 +01:00
if (!part) return;
2020-10-30 12:32:35 +01:00
for (let i = 0; i < part.length; i++) {
2020-10-17 13:34:45 +02:00
ctx.lineWidth = ui.baseLineWidth;
ctx.beginPath();
ctx.strokeStyle = ui.useDepth ? `rgba(${127.5 + (2 * part[i][2])}, ${127.5 - (2 * part[i][2])}, 255, 0.5)` : ui.baseColor;
2020-10-30 12:32:35 +01:00
ctx.moveTo(part[i > 0 ? i - 1 : 0][0], part[i > 0 ? i - 1 : 0][1]);
2020-10-17 13:34:45 +02:00
ctx.lineTo(part[i][0], part[i][1]);
ctx.stroke();
}
};
addPart(hand.annotations.indexFinger);
addPart(hand.annotations.middleFinger);
addPart(hand.annotations.ringFinger);
addPart(hand.annotations.pinky);
addPart(hand.annotations.thumb);
2020-10-30 12:32:35 +01:00
// addPart(hand.annotations.palmBase);
2020-10-17 13:34:45 +02:00
}
}
}
const draw = {
face: drawFace,
body: drawBody,
hand: drawHand,
2020-11-04 16:18:22 +01:00
gesture: drawGesture,
2020-10-17 13:34:45 +02:00
};
export default draw;