-
Notifications
You must be signed in to change notification settings - Fork 134
/
demo.cu
executable file
·214 lines (176 loc) · 9.87 KB
/
demo.cu
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
// ---------------------------------------------------------
// Author: Andy Zeng, Princeton University, 2016
// ---------------------------------------------------------
#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <string>
#include "utils.hpp"
// CUDA kernel function to integrate a TSDF voxel volume given depth images
__global__
void Integrate(float * cam_K, float * cam2base, float * depth_im,
int im_height, int im_width, int voxel_grid_dim_x, int voxel_grid_dim_y, int voxel_grid_dim_z,
float voxel_grid_origin_x, float voxel_grid_origin_y, float voxel_grid_origin_z, float voxel_size, float trunc_margin,
float * voxel_grid_TSDF, float * voxel_grid_weight) {
int pt_grid_z = blockIdx.x;
int pt_grid_y = threadIdx.x;
for (int pt_grid_x = 0; pt_grid_x < voxel_grid_dim_x; ++pt_grid_x) {
// Convert voxel center from grid coordinates to base frame camera coordinates
float pt_base_x = voxel_grid_origin_x + pt_grid_x * voxel_size;
float pt_base_y = voxel_grid_origin_y + pt_grid_y * voxel_size;
float pt_base_z = voxel_grid_origin_z + pt_grid_z * voxel_size;
// Convert from base frame camera coordinates to current frame camera coordinates
float tmp_pt[3] = {0};
tmp_pt[0] = pt_base_x - cam2base[0 * 4 + 3];
tmp_pt[1] = pt_base_y - cam2base[1 * 4 + 3];
tmp_pt[2] = pt_base_z - cam2base[2 * 4 + 3];
float pt_cam_x = cam2base[0 * 4 + 0] * tmp_pt[0] + cam2base[1 * 4 + 0] * tmp_pt[1] + cam2base[2 * 4 + 0] * tmp_pt[2];
float pt_cam_y = cam2base[0 * 4 + 1] * tmp_pt[0] + cam2base[1 * 4 + 1] * tmp_pt[1] + cam2base[2 * 4 + 1] * tmp_pt[2];
float pt_cam_z = cam2base[0 * 4 + 2] * tmp_pt[0] + cam2base[1 * 4 + 2] * tmp_pt[1] + cam2base[2 * 4 + 2] * tmp_pt[2];
if (pt_cam_z <= 0)
continue;
int pt_pix_x = roundf(cam_K[0 * 3 + 0] * (pt_cam_x / pt_cam_z) + cam_K[0 * 3 + 2]);
int pt_pix_y = roundf(cam_K[1 * 3 + 1] * (pt_cam_y / pt_cam_z) + cam_K[1 * 3 + 2]);
if (pt_pix_x < 0 || pt_pix_x >= im_width || pt_pix_y < 0 || pt_pix_y >= im_height)
continue;
float depth_val = depth_im[pt_pix_y * im_width + pt_pix_x];
if (depth_val <= 0 || depth_val > 6)
continue;
float diff = depth_val - pt_cam_z;
if (diff <= -trunc_margin)
continue;
// Integrate
int volume_idx = pt_grid_z * voxel_grid_dim_y * voxel_grid_dim_x + pt_grid_y * voxel_grid_dim_x + pt_grid_x;
float dist = fmin(1.0f, diff / trunc_margin);
float weight_old = voxel_grid_weight[volume_idx];
float weight_new = weight_old + 1.0f;
voxel_grid_weight[volume_idx] = weight_new;
voxel_grid_TSDF[volume_idx] = (voxel_grid_TSDF[volume_idx] * weight_old + dist) / weight_new;
}
}
// Loads a binary file with depth data and generates a TSDF voxel volume (5m x 5m x 5m at 1cm resolution)
// Volume is aligned with respect to the camera coordinates of the first frame (a.k.a. base frame)
int main(int argc, char * argv[]) {
// Location of camera intrinsic file
std::string cam_K_file = "data/camera-intrinsics.txt";
// Location of folder containing RGB-D frames and camera pose files
std::string data_path = "data/rgbd-frames";
int base_frame_idx = 150;
int first_frame_idx = 150;
float num_frames = 50;
float cam_K[3 * 3];
float base2world[4 * 4];
float cam2base[4 * 4];
float cam2world[4 * 4];
int im_width = 640;
int im_height = 480;
float depth_im[im_height * im_width];
// Voxel grid parameters (change these to change voxel grid resolution, etc.)
float voxel_grid_origin_x = -1.5f; // Location of voxel grid origin in base frame camera coordinates
float voxel_grid_origin_y = -1.5f;
float voxel_grid_origin_z = 0.5f;
float voxel_size = 0.006f;
float trunc_margin = voxel_size * 5;
int voxel_grid_dim_x = 500;
int voxel_grid_dim_y = 500;
int voxel_grid_dim_z = 500;
// Manual parameters
if (argc > 1) {
cam_K_file = argv[1];
data_path = argv[2];
base_frame_idx = atoi(argv[3]);
first_frame_idx = atoi(argv[4]);
num_frames = atof(argv[5]);
voxel_grid_origin_x = atof(argv[6]);
voxel_grid_origin_y = atof(argv[7]);
voxel_grid_origin_z = atof(argv[8]);
voxel_size = atof(argv[9]);
trunc_margin = atof(argv[10]);
}
// Read camera intrinsics
std::vector<float> cam_K_vec = LoadMatrixFromFile(cam_K_file, 3, 3);
std::copy(cam_K_vec.begin(), cam_K_vec.end(), cam_K);
// Read base frame camera pose
std::ostringstream base_frame_prefix;
base_frame_prefix << std::setw(6) << std::setfill('0') << base_frame_idx;
std::string base2world_file = data_path + "/frame-" + base_frame_prefix.str() + ".pose.txt";
std::vector<float> base2world_vec = LoadMatrixFromFile(base2world_file, 4, 4);
std::copy(base2world_vec.begin(), base2world_vec.end(), base2world);
// Invert base frame camera pose to get world-to-base frame transform
float base2world_inv[16] = {0};
invert_matrix(base2world, base2world_inv);
// Initialize voxel grid
float * voxel_grid_TSDF = new float[voxel_grid_dim_x * voxel_grid_dim_y * voxel_grid_dim_z];
float * voxel_grid_weight = new float[voxel_grid_dim_x * voxel_grid_dim_y * voxel_grid_dim_z];
for (int i = 0; i < voxel_grid_dim_x * voxel_grid_dim_y * voxel_grid_dim_z; ++i)
voxel_grid_TSDF[i] = 1.0f;
memset(voxel_grid_weight, 0, sizeof(float) * voxel_grid_dim_x * voxel_grid_dim_y * voxel_grid_dim_z);
// Load variables to GPU memory
float * gpu_voxel_grid_TSDF;
float * gpu_voxel_grid_weight;
cudaMalloc(&gpu_voxel_grid_TSDF, voxel_grid_dim_x * voxel_grid_dim_y * voxel_grid_dim_z * sizeof(float));
cudaMalloc(&gpu_voxel_grid_weight, voxel_grid_dim_x * voxel_grid_dim_y * voxel_grid_dim_z * sizeof(float));
checkCUDA(__LINE__, cudaGetLastError());
cudaMemcpy(gpu_voxel_grid_TSDF, voxel_grid_TSDF, voxel_grid_dim_x * voxel_grid_dim_y * voxel_grid_dim_z * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(gpu_voxel_grid_weight, voxel_grid_weight, voxel_grid_dim_x * voxel_grid_dim_y * voxel_grid_dim_z * sizeof(float), cudaMemcpyHostToDevice);
checkCUDA(__LINE__, cudaGetLastError());
float * gpu_cam_K;
float * gpu_cam2base;
float * gpu_depth_im;
cudaMalloc(&gpu_cam_K, 3 * 3 * sizeof(float));
cudaMemcpy(gpu_cam_K, cam_K, 3 * 3 * sizeof(float), cudaMemcpyHostToDevice);
cudaMalloc(&gpu_cam2base, 4 * 4 * sizeof(float));
cudaMalloc(&gpu_depth_im, im_height * im_width * sizeof(float));
checkCUDA(__LINE__, cudaGetLastError());
// Loop through each depth frame and integrate TSDF voxel grid
for (int frame_idx = first_frame_idx; frame_idx < first_frame_idx + (int)num_frames; ++frame_idx) {
std::ostringstream curr_frame_prefix;
curr_frame_prefix << std::setw(6) << std::setfill('0') << frame_idx;
// // Read current frame depth
std::string depth_im_file = data_path + "/frame-" + curr_frame_prefix.str() + ".depth.png";
ReadDepth(depth_im_file, im_height, im_width, depth_im);
// Read base frame camera pose
std::string cam2world_file = data_path + "/frame-" + curr_frame_prefix.str() + ".pose.txt";
std::vector<float> cam2world_vec = LoadMatrixFromFile(cam2world_file, 4, 4);
std::copy(cam2world_vec.begin(), cam2world_vec.end(), cam2world);
// Compute relative camera pose (camera-to-base frame)
multiply_matrix(base2world_inv, cam2world, cam2base);
cudaMemcpy(gpu_cam2base, cam2base, 4 * 4 * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(gpu_depth_im, depth_im, im_height * im_width * sizeof(float), cudaMemcpyHostToDevice);
checkCUDA(__LINE__, cudaGetLastError());
std::cout << "Fusing: " << depth_im_file << std::endl;
Integrate <<< voxel_grid_dim_z, voxel_grid_dim_y >>>(gpu_cam_K, gpu_cam2base, gpu_depth_im,
im_height, im_width, voxel_grid_dim_x, voxel_grid_dim_y, voxel_grid_dim_z,
voxel_grid_origin_x, voxel_grid_origin_y, voxel_grid_origin_z, voxel_size, trunc_margin,
gpu_voxel_grid_TSDF, gpu_voxel_grid_weight);
}
// Load TSDF voxel grid from GPU to CPU memory
cudaMemcpy(voxel_grid_TSDF, gpu_voxel_grid_TSDF, voxel_grid_dim_x * voxel_grid_dim_y * voxel_grid_dim_z * sizeof(float), cudaMemcpyDeviceToHost);
cudaMemcpy(voxel_grid_weight, gpu_voxel_grid_weight, voxel_grid_dim_x * voxel_grid_dim_y * voxel_grid_dim_z * sizeof(float), cudaMemcpyDeviceToHost);
checkCUDA(__LINE__, cudaGetLastError());
// Compute surface points from TSDF voxel grid and save to point cloud .ply file
std::cout << "Saving surface point cloud (tsdf.ply)..." << std::endl;
SaveVoxelGrid2SurfacePointCloud("tsdf.ply", voxel_grid_dim_x, voxel_grid_dim_y, voxel_grid_dim_z,
voxel_size, voxel_grid_origin_x, voxel_grid_origin_y, voxel_grid_origin_z,
voxel_grid_TSDF, voxel_grid_weight, 0.2f, 0.0f);
// Save TSDF voxel grid and its parameters to disk as binary file (float array)
std::cout << "Saving TSDF voxel grid values to disk (tsdf.bin)..." << std::endl;
std::string voxel_grid_saveto_path = "tsdf.bin";
std::ofstream outFile(voxel_grid_saveto_path, std::ios::binary | std::ios::out);
float voxel_grid_dim_xf = (float) voxel_grid_dim_x;
float voxel_grid_dim_yf = (float) voxel_grid_dim_y;
float voxel_grid_dim_zf = (float) voxel_grid_dim_z;
outFile.write((char*)&voxel_grid_dim_xf, sizeof(float));
outFile.write((char*)&voxel_grid_dim_yf, sizeof(float));
outFile.write((char*)&voxel_grid_dim_zf, sizeof(float));
outFile.write((char*)&voxel_grid_origin_x, sizeof(float));
outFile.write((char*)&voxel_grid_origin_y, sizeof(float));
outFile.write((char*)&voxel_grid_origin_z, sizeof(float));
outFile.write((char*)&voxel_size, sizeof(float));
outFile.write((char*)&trunc_margin, sizeof(float));
for (int i = 0; i < voxel_grid_dim_x * voxel_grid_dim_y * voxel_grid_dim_z; ++i)
outFile.write((char*)&voxel_grid_TSDF[i], sizeof(float));
outFile.close();
return 0;
}