-
-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathscale-user.html
More file actions
154 lines (138 loc) · 7.21 KB
/
Copy pathscale-user.html
File metadata and controls
154 lines (138 loc) · 7.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Kinect2 Example</title>
<link rel="stylesheet" href="../assets/vendors/bootstrap-4.3.1-dist/css/bootstrap.css">
<link rel="stylesheet" href="../assets/vendors/bootstrap-4.3.1-dist/css/docs.min.css">
</head>
<body class="container-fluid py-3">
<div class="d-flex align-items-baseline justify-content-between">
<h1 class="bd-title">Scale User</h1>
<button onclick="require('electron').remote.getCurrentWebContents().openDevTools()">open dev tools</button>
</div>
<p>
This demo cuts out the closest person, and projects that person always at the same size and position, no matter the real life position from the Kinect.
</p>
<canvas id="outputCanvas" width="1920" height="1080" class="img-fluid"></canvas>
<script>
{
const Kinect2 = require('kinect2');
const kinect = new Kinect2();
const $outputCanvas = document.getElementById('outputCanvas'),
outputCtx = $outputCanvas.getContext('2d');
const $hiddenCanvas = document.createElement('canvas');
$hiddenCanvas.width = 1920;
$hiddenCanvas.height = 1080;
const hiddenCtx = $hiddenCanvas.getContext('2d');
const hiddenImageData = outputCtx.createImageData($hiddenCanvas.width, $hiddenCanvas.height);
let trackedBodyIndex = -1;
const emptyPixels = new Uint8Array(1920 * 1080 * 4);
const init = () => {
startKinect();
};
const startKinect = () => {
if (kinect.open()) {
kinect.on('multiSourceFrame', (frame) => {
const closestBodyIndex = getClosestBodyIndex(frame.body.bodies);
if(closestBodyIndex !== trackedBodyIndex) {
if(closestBodyIndex > -1) {
kinect.trackPixelsForBodyIndices([closestBodyIndex]);
} else {
kinect.trackPixelsForBodyIndices(false);
//clear canvas
renderColorFrame(outputCtx, outputImageData, emptyPixels.buffer);
}
}
else {
if(closestBodyIndex > -1) {
//get body ground position - when use jumps this point stays on the ground
if(frame.body.bodies[closestBodyIndex].joints[Kinect2.JointType.spineMid].floorColorY) {
//calculate the source rectangle
let leftJoint = frame.body.bodies[closestBodyIndex].joints[0],
topJoint = frame.body.bodies[closestBodyIndex].joints[0],
rightJoint = frame.body.bodies[closestBodyIndex].joints[0];
for(let i = 1; i < frame.body.bodies[closestBodyIndex].joints.length; i++) {
const joint = frame.body.bodies[closestBodyIndex].joints[i];
if(joint.colorX < leftJoint.colorX) {
leftJoint = joint;
}
if(joint.colorX > rightJoint.colorX) {
rightJoint = joint;
}
if(joint.colorY < topJoint.colorY) {
topJoint = joint;
}
}
const pixelWidth = calculatePixelWidth(frame.bodyIndexColor.horizontalFieldOfView, frame.body.bodies[closestBodyIndex].joints[Kinect2.JointType.spineMid].cameraZ * 1000);
scale = 0.3 * pixelWidth;
//head joint is in middle of head, add area (y-distance from neck to head joint) above
topJoint = {
colorX: topJoint.colorX,
colorY: Math.min(topJoint.colorY, frame.body.bodies[closestBodyIndex].joints[Kinect2.JointType.head].colorY - (frame.body.bodies[closestBodyIndex].joints[Kinect2.JointType.neck].colorY - frame.body.bodies[closestBodyIndex].joints[Kinect2.JointType.head].colorY))
};
const srcRect = {
x: leftJoint.colorX * $hiddenCanvas.width,
y: topJoint.colorY * $hiddenCanvas.height,
width: (rightJoint.colorX - leftJoint.colorX) * $hiddenCanvas.width,
height: (frame.body.bodies[closestBodyIndex].joints[Kinect2.JointType.spineMid].floorColorY - topJoint.colorY) * $hiddenCanvas.height
};
const dstRect = {
x: $outputCanvas.width * 0.5,
y: $outputCanvas.height - (srcRect.height * scale),
width: srcRect.width * scale,
height: srcRect.height * scale
};
//center the user horizontally - is not minus half width of image as user might reach to one side or the other
//do minus the space on the left size of the spine
const spaceLeft = frame.body.bodies[closestBodyIndex].joints[Kinect2.JointType.spineMid].colorX - leftJoint.colorX;
dstRect.x -= (spaceLeft * $hiddenCanvas.width * scale);
// render the full image to the hidden canvas
renderColorFrame(hiddenCtx, hiddenImageData, frame.bodyIndexColor.bodies[closestBodyIndex].buffer);
// render the cutout to the displayed canvas
outputCtx.clearRect(0, 0, $outputCanvas.width, $outputCanvas.height);
outputCtx.drawImage($hiddenCanvas, srcRect.x, srcRect.y, srcRect.width, srcRect.height, dstRect.x, dstRect.y, dstRect.width, dstRect.height);
}
}
}
trackedBodyIndex = closestBodyIndex;
});
kinect.openMultiSourceReader({
frameTypes: Kinect2.FrameType.bodyIndexColor | Kinect2.FrameType.body,
includeJointFloorData: true
});
}
};
const getClosestBodyIndex = (bodies) => {
let closestZ = Number.MAX_VALUE;
let closestBodyIndex = -1;
for(let i = 0; i < bodies.length; i++) {
if(bodies[i].tracked && bodies[i].joints[Kinect2.JointType.spineMid].cameraZ < closestZ) {
closestZ = bodies[i].joints[Kinect2.JointType.spineMid].cameraZ;
closestBodyIndex = i;
}
}
return closestBodyIndex;
};
const calculatePixelWidth = (horizontalFieldOfView, depth) => {
// measure the size of the pixel
const hFov = horizontalFieldOfView / 2;
const numPixels = $hiddenCanvas.width / 2;
const T = Math.tan((Math.PI * 180) / hFov);
const pixelWidth = T * depth;
return pixelWidth / numPixels;
};
const renderColorFrame = (ctx, canvasImageData, newPixelData) => {
const pixelArray = canvasImageData.data;
for (let i = 0; i < canvasImageData.data.length; i++) {
pixelArray[i] = newPixelData[i];
}
ctx.putImageData(canvasImageData, 0, 0);
};
// expose the kinect instance to the window object in this demo app to allow the parent window to close it between sessions
window.kinect = kinect;
init();
}
</script>
</body>
</html>