-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathparallax.cpp
More file actions
278 lines (243 loc) · 10.6 KB
/
parallax.cpp
File metadata and controls
278 lines (243 loc) · 10.6 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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
#include <librealsense/rs.hpp>
#include <cstdio>
#define GLFW_INCLUDE_GLU
#include <GLFW/glfw3.h>
double yaw, pitch, lastX, lastY; int ml, mode;
double ipd, vshift,dshift;
static void on_mouse_button(GLFWwindow * win, int button, int action, int mods)
{
if(button == GLFW_MOUSE_BUTTON_LEFT) ml = action == GLFW_PRESS;
if(button == GLFW_MOUSE_BUTTON_RIGHT){pitch=0;yaw=0;}
}
static double clamp(double val, double lo, double hi) { return val < lo ? lo : val > hi ? hi : val; }
static void on_cursor_pos(GLFWwindow * win, double x, double y)
{
if(ml)
{
yaw = clamp(yaw - (x - lastX), -120, 120);
pitch = clamp(pitch + (y - lastY), -80, 80);
}
lastX = x;
lastY = y;
}
static void on_keypress(GLFWwindow * win, int key,int scancode,int action, int mods){
if(action==GLFW_PRESS)
switch(key){
case(GLFW_KEY_RIGHT):
ipd+=0.01;
break;
case(GLFW_KEY_LEFT):
ipd-=0.01;
break;
case(GLFW_KEY_UP):
vshift-=0.01;
break;
case(GLFW_KEY_DOWN):
vshift+=0.01;
break;
case(GLFW_KEY_SPACE):
pitch=0.0;
yaw=0.0;
mode+=1;
break;
case(GLFW_KEY_ESCAPE):
glfwDestroyWindow(win);
break;
default:
break;
}
}
int main() try
{
// Turn on logging. We can separately enable logging to console or to file, and use different severity filters for each.
rs::log_to_console(rs::log_severity::warn);
//rs::log_to_file(rs::log_severity::debug, "librealsense.log");
// Create a context object. This object owns the handles to all connected realsense devices.
rs::context ctx;
printf("There are %d connected RealSense devices.\n", ctx.get_device_count());
if(ctx.get_device_count() == 0) return EXIT_FAILURE;
// This tutorial will access only a single device, but it is trivial to extend to multiple devices
rs::device * dev = ctx.get_device(0);
printf("\nUsing device 0, an %s\n", dev->get_name());
printf(" Serial number: %s\n", dev->get_serial());
printf(" Firmware version: %s\n", dev->get_firmware_version());
// Configure depth and color to run with the device's preferred settings
//dev->enable_stream(rs::stream::depth, rs::preset::best_quality);
//dev->enable_stream(rs::stream::color, rs::preset::best_quality);
dev->enable_stream(rs::stream::depth, 640, 480, rs::format::z16, 60);
dev->enable_stream(rs::stream::color, 640, 480, rs::format::rgb8, 60);
//dev->enable_stream(rs::stream::color, 640, 480, rs::format::yuyv, 60);
dev->enable_stream(rs::stream::infrared, 640, 480, rs::format::y8, 60);
dev->enable_stream(rs::stream::infrared2, 640, 480, rs::format::y8, 60);
dev->start();
GLuint tex;
glGenTextures(1, &tex);
// Open a GLFW window to display our output
glfwInit();
//GLFWwindow * win = glfwCreateWindow(1280, 960, "librealsense tutorial #3", nullptr, nullptr);
int n_monitors;
GLFWmonitor** monitors = glfwGetMonitors(&n_monitors);
GLFWwindow * win = glfwCreateWindow(1920, 1080, "Yeah dude, I rock on a different monitor!", 1 ? monitors[n_monitors - 1] : nullptr, nullptr);
glfwSetCursorPosCallback(win, on_cursor_pos);
glfwSetMouseButtonCallback(win, on_mouse_button);
glfwSetKeyCallback(win,on_keypress);
glfwMakeContextCurrent(win);
while(!glfwWindowShouldClose(win))
{
// Wait for new frame data
glfwPollEvents();
dev->wait_for_frames();
// Retrieve our images
const uint16_t * depth_image = (const uint16_t *)dev->get_frame_data(rs::stream::depth);
const uint8_t * color_image = (const uint8_t *)dev->get_frame_data(rs::stream::color);
/* How can we fix the depth?
* Idea:
* - create a columnar store for each of x,y,chroma1,chroma2,lumosity_color,lumosity_ir1,lumosity_ir2
* - put all pixels with known depth in there
* - make a copy table of argsorts
* - for each of the unknown depths
* - find location of each element in sorted lists
* - define an expanding window of size n on both sides of each position in argsort list
* - take the intersection of all windows
* - increase n until m are in the intersection
* - assign the average value to the unknown
* */
// Retrieve camera parameters for mapping between depth and color
rs::intrinsics depth_intrin = dev->get_stream_intrinsics(rs::stream::depth);
rs::extrinsics depth_to_color = dev->get_extrinsics(rs::stream::depth, rs::stream::color);
rs::intrinsics color_intrin = dev->get_stream_intrinsics(rs::stream::color);
float scale = dev->get_depth_scale();
// Set up a perspective transform in a space that we can rotate by clicking and dragging the mouse
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
auto make_pointcloud = [&](double vx=0.0,double vy=0.0,double vz=0.0){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, (float)960/1080, 0.01f, 20.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(vx,vy,vz, vx,vy,1, 0,-1,0);
glTranslatef(0,0,+0.5f);
glRotated(pitch, 1, 0, 0);
glRotated(yaw, 0, 1, 0);
glTranslatef(0,0,-0.5f);
// We will render our depth data as a set of points in 3D space
glPointSize(2);
glEnable(GL_DEPTH_TEST);
glBegin(GL_POINTS);
float last_depth=0.0;
float last_line[depth_intrin.width];
for(int dy=0; dy<depth_intrin.height; ++dy)
{
for(int dx=0; dx<depth_intrin.width; ++dx)
{
// Retrieve the 16-bit depth value and map it into a depth in meters
uint16_t depth_value = depth_image[dy * depth_intrin.width + dx];
float depth_in_meters = depth_value * scale;
// Skip over pixels with a depth value of zero, which is used to indicate no data
if(depth_value == 0)
continue;//
//depth_in_meters=(last_depth+last_line[dx])/2;
else
last_depth = depth_in_meters;
last_line[dx]=depth_in_meters;
// Map from pixel coordinates in the depth image to pixel coordinates in the color image
rs::float2 depth_pixel = {(float)dx, (float)dy};
rs::float3 depth_point = depth_intrin.deproject(depth_pixel, depth_in_meters);
rs::float3 color_point = depth_to_color.transform(depth_point);
rs::float2 color_pixel = color_intrin.project(color_point);
// Use the color from the nearest color pixel, or pure white if this point falls outside the color image
const int cx = (int)std::round(color_pixel.x), cy = (int)std::round(color_pixel.y);
if(cx < 0 || cy < 0 || cx >= color_intrin.width || cy >= color_intrin.height)
{
//glColor3ub(255, 255, 255);
continue;
}
else
{
glColor3ubv(color_image + (cy * color_intrin.width + cx) * 3);
}
// Emit a vertex at the 3D location of this depth pixel
glVertex3f(depth_point.x, depth_point.y, depth_point.z);
}
}
glEnd();
};
auto make_infrared = [&](){
glViewport(0,0,1920,1080);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//glOrtho(0,1920,0,1080,-1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPixelZoom(1.5, -1.5);
glRasterPos2f(-1, .667);
glDrawPixels(640, 480, GL_LUMINANCE, GL_UNSIGNED_BYTE, dev->get_frame_data(rs::stream::infrared));
glRasterPos2f(0, .667);
glDrawPixels(640, 480, GL_LUMINANCE, GL_UNSIGNED_BYTE, dev->get_frame_data(rs::stream::infrared2));
};
auto make_color = [&](){
glViewport(0,0,1920,1080);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//glOrtho(0,1920,0,1080,-1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPixelZoom(1.5, -1.5);
glRasterPos2f(-1, .667);
glDrawPixels(640, 480, GL_RGB, GL_UNSIGNED_BYTE, dev->get_frame_data(rs::stream::color));
glRasterPos2f(0, .667);
glDrawPixels(640, 480, GL_RGB, GL_UNSIGNED_BYTE, dev->get_frame_data(rs::stream::color));
};
auto make_color3 = [&](){
// my bad attempt at background image
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1,1,-1,1,-1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,tex);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,640,480,0,GL_RGB,GL_UNSIGNED_BYTE,dev->get_frame_data(rs::stream::color));
glBegin(GL_QUADS);
glTexCoord2d(0,1);glVertex2d(-1,-1);
glTexCoord2d(1,1);glVertex2d(1,-1);
glTexCoord2d(1,0);glVertex2d(1,1);
glTexCoord2d(0,0);glVertex2d(-1,1);
glEnd();
// enf background image
};
switch(mode % 3){
case(0):
glViewport(0,0,960,1080);
make_pointcloud(-ipd,vshift,-0.05);
glViewport(960,0,960,1080);
make_pointcloud(ipd,vshift,-0.05);
break;
case(1):
make_infrared();
break;
case(2):
make_color();
break;
case(3): //should never get here
glViewport(0,0,960,1080);
make_color3();
glViewport(960,0,960,1080);
make_color3();
break;
default:
break;
}
glfwSwapBuffers(win);
}
return EXIT_SUCCESS;
}
catch(const rs::error & e)
{
// Method calls against librealsense objects may throw exceptions of type rs::error
printf("rs::error was thrown when calling %s(%s):\n", e.get_failed_function().c_str(), e.get_failed_args().c_str());
printf(" %s\n", e.what());
return EXIT_FAILURE;
}