nl-knd_client 0.0.0.pre.usegit

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,212 @@
1
+ /*
2
+ * Non-inline definitions and functions for Kinect data pack/unpack code.
3
+ * (C)2011 Mike Bourgeous
4
+ */
5
+ #include <string.h>
6
+ #include <math.h>
7
+
8
+ #include <nlutils/nlutils.h>
9
+
10
+ #define UNPACK_INLINE
11
+ #include "unpack.h"
12
+
13
+ // TODO: Put ku_xworld, ku_yworld, lut into a library of addons, or submit as patches
14
+ // to libfreenect.
15
+
16
+ // Depth look-up table (translates depth sample into world-space millimeters).
17
+ int ku_depth_lut[2048];
18
+
19
+ // Converts x in pixels and z in world millimeters to x in world millimeters.
20
+ static int ku_xworld(int x, int zw)
21
+ {
22
+ // tan 28 ~= .53171 (1089 ~= .53171 * 2048)
23
+ // 0xcccd is the ~reciprocal of 10 (factor of W/2=320)
24
+ // Add 2**34 (0x400000000) for rounding before shift
25
+ // Shift right by 35:
26
+ // 11 bits for tangent (* 2048 above)
27
+ // 19 bits for reciprocal multiplication by 1/10 (factor of W/2=320)
28
+ // 5 bits for division by 32 (other factor of W/2=320)
29
+ //
30
+ // In total, with an overly generous maximum range of +/-16384mm (15
31
+ // bits), and an overhead of 35 bits due to arithmetic, 50 bits are
32
+ // needed for the calculation.
33
+ return (((int64_t)zw * (320 - x) * 1089 * 0xcccd) + 0x400000000) >> 35;
34
+ }
35
+
36
+ // Converts y in pixels and z in world millimeters to y in world millimeters.
37
+ static int ku_yworld(int y, int zw)
38
+ {
39
+ return ku_xworld(y + (640 - 480) / 2, zw);
40
+ }
41
+
42
+ // Initializes the depth look-up table.
43
+ // Copied from the knd daemon code, based on:
44
+ // http://groups.google.com/group/openkinect/browse_thread/thread/31351846fd33c78/e98a94ac605b9f21#e98a94ac605b9f21
45
+ void ku_init_lut()
46
+ {
47
+ int i;
48
+
49
+ for(i = 0; i < 2047; i++) {
50
+ ku_depth_lut[i] = (int)(0.1236f * tanf(i / 2842.5f + 1.1863f) * 1000.0f);
51
+ }
52
+ ku_depth_lut[2047] = 1048576;
53
+ }
54
+
55
+ // Finds the closest entry in the depth look-up table to the given world-space
56
+ // depth value in millimeters without going over. Uses a binary search.
57
+ int ku_reverse_lut(int zw)
58
+ {
59
+ int idx = PXZMAX / 2;
60
+ int off = PXZMAX / 4;
61
+
62
+ while(off > 0 && ku_depth_lut[idx] != zw) {
63
+ if(ku_depth_lut[idx] > zw) {
64
+ idx -= off;
65
+ } else if(ku_depth_lut[idx] < zw) {
66
+ idx += off;
67
+ }
68
+
69
+ off >>= 1;
70
+ }
71
+
72
+ // Binary search isn't perfect due to truncation, so find the optimum value
73
+ while(ku_depth_lut[idx] > zw && idx > 0) {
74
+ idx--;
75
+ }
76
+ while(ku_depth_lut[idx + 1] < zw && idx <= PXZMAX) {
77
+ idx++;
78
+ }
79
+
80
+ return idx;
81
+ }
82
+
83
+ // Plots a linear depth version of the given perspective image on the 8-bit
84
+ // output surface, which must be 640x480 bytes.
85
+ void plot_linear(const uint16_t *in, uint8_t *out)
86
+ {
87
+ int x, y, pix;
88
+
89
+ for(pix = 0, y = 0; y < 640; y++) {
90
+ for(x = 0; x < 480; x++, pix++) {
91
+ out[pix] = 255 - CLAMP(0, 255, ((int32_t)ku_depth_lut[(65535 - in[pix]) >> 5] - 400) * 255 / ZMAX);
92
+ }
93
+ }
94
+ }
95
+
96
+ // Turns overhead view coordinates into a pixel index.
97
+ #define OVPX(xw, zw) (((zw) * ZPIX / ZMAX) * XPIX + ((xw) * XPIX / XMAX + XPIX / 2))
98
+
99
+ // Plots an overhead view on the given raw linear 8-bit grayscale image
100
+ // surface, which must be XPIX bytes wide by ZPIX bytes tall.
101
+ void plot_overhead(const uint16_t *in, uint8_t *out)
102
+ {
103
+ int y, x, pix, val;
104
+ int xw, zw, opx;
105
+ int c;
106
+
107
+ memset(out, 0, XPIX * ZPIX);
108
+
109
+ // TODO: Draw borders
110
+
111
+ for(pix = 0, y = 0; y < 480; y++) {
112
+ for(x = 0; x < 640; x++, pix++) {
113
+ val = (65535 - in[pix]) >> 5;
114
+ zw = ku_depth_lut[val];
115
+ if(val >= 2047 || zw >= ZMAX) {
116
+ continue;
117
+ }
118
+ xw = ku_xworld(x, zw);
119
+
120
+ opx = OVPX(xw, zw);
121
+ if(opx < 0 || opx >= XPIX * ZPIX) {
122
+ continue;
123
+ }
124
+ c = out[opx];
125
+ c += 2;
126
+ if(c > 255) {
127
+ c = 255;
128
+ }
129
+ out[opx] = c;
130
+ }
131
+ }
132
+ }
133
+
134
+ // Turns side view coordinates into a pixel index.
135
+ #define SVPX(zw, yw) (((-yw) * YPIX / YMAX + YPIX / 2) * ZPIX + ((zw) * ZPIX / ZMAX))
136
+
137
+ // Plots a side view on the given raw linear 8-bit grayscale image surface,
138
+ // which must be ZPIX bytes wide by YPIX bytes tall.
139
+ void plot_side(const uint16_t *in, uint8_t *out)
140
+ {
141
+ int y, x, pix, val;
142
+ int yw, zw, opx;
143
+ int c;
144
+
145
+ memset(out, 0, ZPIX * YPIX);
146
+
147
+ // TODO: Draw borders
148
+ // TODO: Allow skipping for speed
149
+
150
+ for(pix = 0, y = 0; y < 480; y++) {
151
+ for(x = 0; x < 640; x++, pix++) {
152
+ val = (65535 - in[pix]) >> 5;
153
+ zw = ku_depth_lut[val];
154
+ if(val >= 2047 || zw >= ZMAX) {
155
+ continue;
156
+ }
157
+ yw = ku_yworld(y, zw);
158
+
159
+ opx = SVPX(zw, yw);
160
+ if(opx < 0 || opx >= ZPIX * YPIX) {
161
+ continue;
162
+ }
163
+ c = out[opx];
164
+ c += 2;
165
+ if(c > 255) {
166
+ c = 255;
167
+ }
168
+ out[opx] = c;
169
+ }
170
+ }
171
+ }
172
+
173
+ // Turns front view coordinates into a pixel index.
174
+ #define FVPX(xw, yw) (((-yw) * YPIX / YMAX + YPIX / 2) * XPIX + ((-xw) * XPIX / XMAX + XPIX / 2))
175
+
176
+ // Plots a front view on the given raw linear 8-bit grayscale image surface,
177
+ // which must be XPIX bytes wide by YPIX bytes tall.
178
+ void plot_front(const uint16_t *in, uint8_t *out)
179
+ {
180
+ int y, x, pix, val;
181
+ int xw, yw, zw, opx;
182
+ int c;
183
+
184
+ memset(out, 0, XPIX * YPIX);
185
+
186
+ // TODO: Draw borders
187
+ // TODO: Allow skipping for speed
188
+
189
+ for(pix = 0, y = 0; y < 480; y++) {
190
+ for(x = 0; x < 640; x++, pix++) {
191
+ val = (65535 - in[pix]) >> 5;
192
+ zw = ku_depth_lut[val];
193
+ if(val >= 2047 || zw >= ZMAX) {
194
+ continue;
195
+ }
196
+ xw = ku_xworld(x, zw);
197
+ yw = ku_yworld(y, zw);
198
+
199
+ opx = FVPX(xw, yw);
200
+ if(opx < 0 || opx >= XPIX * YPIX) {
201
+ continue;
202
+ }
203
+ c = out[opx];
204
+ c += 1 + (zw - 512) / 256; // TODO: Scale intensity by surface area
205
+ if(c > 255) {
206
+ c = 255;
207
+ }
208
+ out[opx] = c;
209
+ }
210
+ }
211
+ }
212
+
@@ -0,0 +1,108 @@
1
+ /*
2
+ * Definitions for Kinect data pack/unpack code.
3
+ * (C)2011 Mike Bourgeous
4
+ */
5
+ #ifndef UNPACK_H_
6
+ #define UNPACK_H_
7
+
8
+ #include <stdint.h>
9
+
10
+ #ifndef UNPACK_INLINE
11
+ #define UNPACK_INLINE inline
12
+ #endif /* UNPACK_INLINE */
13
+
14
+ // assuming xmax~=3.797 and ymax~=2.848 when z ~= 7
15
+ // calculated as x=5*tan(28)/tan(35) and y=x*3/4
16
+ #define XPIX 500
17
+ #define YPIX 500
18
+ #define ZPIX 500
19
+ #define XMAX 7594 // Actually 2*xmax
20
+ #define YMAX 5696 // Actually 2*ymax
21
+ #define ZMAX 7000
22
+ #define PXZMAX 1092
23
+
24
+
25
+ // Depth look-up table (translates depth sample into world-space millimeters).
26
+ extern int ku_depth_lut[2048];
27
+
28
+ // Unpacks and inverts 8 11-bit pixels (11 bytes) from in and stores them as
29
+ // MSB-aligned 16-bit values in out (16 bytes)
30
+ UNPACK_INLINE void unpack11_to_16(const uint8_t *in, uint16_t *out)
31
+ {
32
+ out[0] = 65535 - (((in[0] << 3) | (in[1] >> 5)) << 5);
33
+ out[1] = 65535 - ((((in[1] & 0x1f) << 6) | (in[2] >> 2)) << 5);
34
+ out[2] = 65535 - ((((in[2] & 0x03) << 9) | (in[3] << 1) | (in[4] >> 7)) << 5);
35
+ out[3] = 65535 - ((((in[4] & 0x7f) << 4) | (in[5] >> 4)) << 5);
36
+ out[4] = 65535 - ((((in[5] & 0x0f) << 7) | (in[6] >> 1)) << 5);
37
+ out[5] = 65535 - ((((in[6] & 0x01) << 10) | (in[7] << 2) | (in[8] >> 6)) << 5);
38
+ out[6] = 65535 - ((((in[8] & 0x3f) << 5) | (in[9] >> 3)) << 5);
39
+ out[7] = 65535 - ((((in[9] & 0x07) << 8) | in[10]) << 5);
40
+ }
41
+
42
+ // Packs 8 LSB-aligned 11-in-16-bit pixels (16 bytes) into 11 output bytes
43
+ UNPACK_INLINE void pack16_to_11(const uint16_t *in, uint8_t *out)
44
+ {
45
+ out[0] = in[0] >> 3;
46
+ out[1] = ((in[0] & 0x07) << 5) | (in[1] >> 6);
47
+ out[2] = ((in[1] & 0x3f) << 2) | (in[2] >> 9);
48
+ out[3] = (in[2] & 0x1fe) >> 1;
49
+ out[4] = ((in[2] & 0x01) << 7) | (in[3] >> 4);
50
+ out[5] = ((in[3] & 0x0f) << 4) | (in[4] >> 7);
51
+ out[6] = ((in[4] & 0x7f) << 1) | (in[5] >> 10);
52
+ out[7] = (in[5] & 0x3fc) >> 2;
53
+ out[8] = ((in[5] & 0x03) << 6) | (in[6] >> 5);
54
+ out[9] = ((in[6] & 0x1f) << 3) | (in[7] >> 8);
55
+ out[10] = in[7] & 0xff;
56
+ }
57
+
58
+ // Unpacks 8 11-bit pixels (11 bytes) into 8 output bytes
59
+ UNPACK_INLINE void unpack11_to_8(const uint8_t *in, uint8_t *out)
60
+ {
61
+ uint16_t buf16[8];
62
+ int i;
63
+
64
+ unpack11_to_16(in, buf16);
65
+ for(i = 0; i < 8; i++) {
66
+ out[i] = buf16[i] >> 3;
67
+ }
68
+ }
69
+
70
+ // Unpacks a single pixel into a right-aligned 16-bit value
71
+ UNPACK_INLINE int pxval_11(uint8_t *buf, int pixel)
72
+ {
73
+ uint32_t byteindex = (pixel * 11) >> 3;
74
+ uint32_t shiftbits = ((7 + pixel * 5) & 0x7) + 14;
75
+ uint32_t base;
76
+
77
+ buf = buf + byteindex;
78
+ base = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
79
+
80
+ return (base >> shiftbits) & 0x7ff;
81
+ }
82
+
83
+ // Initializes the depth look-up table.
84
+ // Copied from the knd daemon code, based on:
85
+ // http://groups.google.com/group/openkinect/browse_thread/thread/31351846fd33c78/e98a94ac605b9f21#e98a94ac605b9f21
86
+ void ku_init_lut();
87
+
88
+ // Finds the closest entry in the depth look-up table to the given world-space
89
+ // depth value in millimeters without going over. Uses a binary search.
90
+ int ku_reverse_lut(int zw);
91
+
92
+ // Plots a linear depth version of the given perspective image on the 8-bit
93
+ // output surface, which must be 640x480 bytes.
94
+ void plot_linear(const uint16_t *in, uint8_t *out);
95
+
96
+ // Plots an overhead view on the given raw linear 8-bit grayscale image
97
+ // surface, which must be XPIX bytes wide by ZPIX bytes tall.
98
+ void plot_overhead(const uint16_t *in, uint8_t *out);
99
+
100
+ // Plots a side view on the given raw linear 8-bit grayscale image surface,
101
+ // which must be ZPIX bytes wide by YPIX bytes tall.
102
+ void plot_side(const uint16_t *in, uint8_t *out);
103
+
104
+ // Plots a front view on the given raw linear 8-bit grayscale image surface,
105
+ // which must be XPIX bytes wide by YPIX bytes tall.
106
+ void plot_front(const uint16_t *in, uint8_t *out);
107
+
108
+ #endif /* UNPACK_H_ */
@@ -0,0 +1,26 @@
1
+ /*
2
+ * Experimental Kinect depth image unpacking code.
3
+ * (C)2011 Mike Bourgeous
4
+ */
5
+ #include <stdio.h>
6
+ #include <stdint.h>
7
+
8
+ #include "unpack.h"
9
+
10
+ int main()
11
+ {
12
+ uint16_t in[640 * 480];
13
+ uint8_t out[XPIX * ZPIX];
14
+
15
+ if(fread(in, 2, 640 * 480, stdin) != 640 * 480) {
16
+ fprintf(stderr, "Must provide %d bytes of unpacked depth data to stdin.\n", 640 * 480 * 2);
17
+ }
18
+
19
+ ku_init_lut();
20
+ plot_overhead(in, out);
21
+
22
+ fwrite(out, 1, XPIX * ZPIX, stdout);
23
+
24
+ return 0;
25
+ }
26
+
@@ -0,0 +1,42 @@
1
+ /*
2
+ * Code to render a basic grid for the overhead view, for later manipulation.
3
+ * The final grid will be created from this program's output using the GIMP.
4
+ * (C)2012 Mike Bourgeous
5
+ */
6
+ #include <stdio.h>
7
+ #include <stdint.h>
8
+ #include <string.h>
9
+
10
+ #include "unpack.h"
11
+
12
+ void draw_grid(uint8_t *grid, uint8_t color, int spacing)
13
+ {
14
+ int x, z;
15
+
16
+ // Loop through x in world space, z in pixels
17
+ for(x = 0; x < XMAX / 2; x += spacing) {
18
+ for(z = 0; z < ZPIX; z++) {
19
+ grid[x * XPIX / XMAX + XPIX / 2 + z * XPIX] = color;
20
+ grid[XPIX / 2 - (x * XPIX / XMAX) + z * XPIX] = color;
21
+ }
22
+ }
23
+
24
+ // Loop through z in world space, x in pixels
25
+ for(z = 0; z < ZMAX; z += spacing) {
26
+ for(x = 0; x < XPIX; x++) {
27
+ grid[x + z * ZPIX / ZMAX * XPIX] = color;
28
+ }
29
+ }
30
+ }
31
+
32
+ int main()
33
+ {
34
+ uint8_t out[XPIX * ZPIX];
35
+
36
+ memset(out, 0, sizeof(out));
37
+ draw_grid(out, 128, 500);
38
+ draw_grid(out, 255, 1000);
39
+ fwrite(out, 1, sizeof(out), stdout);
40
+
41
+ return 0;
42
+ }
@@ -0,0 +1,26 @@
1
+ /*
2
+ * Experimental Kinect depth image unpacking code.
3
+ * (C)2011 Mike Bourgeous
4
+ */
5
+ #include <stdio.h>
6
+ #include <stdint.h>
7
+
8
+ #include "unpack.h"
9
+
10
+ int main()
11
+ {
12
+ uint16_t in[640 * 480];
13
+ uint8_t out[ZPIX * YPIX];
14
+
15
+ if(fread(in, 2, 640 * 480, stdin) != 640 * 480) {
16
+ fprintf(stderr, "Must provide %d bytes of unpacked depth data to stdin.\n", 640 * 480 * 2);
17
+ }
18
+
19
+ ku_init_lut();
20
+ plot_side(in, out);
21
+
22
+ fwrite(out, 1, sizeof(out), stdout);
23
+
24
+ return 0;
25
+ }
26
+
@@ -0,0 +1,42 @@
1
+ /*
2
+ * Code to render a basic grid for the side view, for later manipulation.
3
+ * The final grid will be created from this program's output using the GIMP.
4
+ * (C)2012 Mike Bourgeous
5
+ */
6
+ #include <stdio.h>
7
+ #include <stdint.h>
8
+ #include <string.h>
9
+
10
+ #include "unpack.h"
11
+
12
+ void draw_grid(uint8_t *grid, uint8_t color, int spacing)
13
+ {
14
+ int y, z;
15
+
16
+ // Loop through y in world space, z in piyels
17
+ for(y = 0; y < YMAX / 2; y += spacing) {
18
+ for(z = 0; z < ZPIX; z++) {
19
+ grid[y * YPIX / YMAX * ZPIX + YPIX / 2 * ZPIX + z] = color;
20
+ grid[YPIX / 2 * ZPIX - (y * YPIX / YMAX * ZPIX) + z] = color;
21
+ }
22
+ }
23
+
24
+ // Loop through z in world space, y in piyels
25
+ for(z = 0; z < ZMAX; z += spacing) {
26
+ for(y = 0; y < YPIX; y++) {
27
+ grid[y * ZPIX + z * ZPIX / ZMAX] = color;
28
+ }
29
+ }
30
+ }
31
+
32
+ int main()
33
+ {
34
+ uint8_t out[YPIX * ZPIX];
35
+
36
+ memset(out, 0, sizeof(out));
37
+ draw_grid(out, 128, 500);
38
+ draw_grid(out, 255, 1000);
39
+ fwrite(out, 1, sizeof(out), stdout);
40
+
41
+ return 0;
42
+ }