Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef KINECT_CLOUD_H
00017 #define KINECT_CLOUD_H
00018
00019 #include <string>
00020 #include <vector>
00021
00022 #include "cloud.h"
00023 #include "options.h"
00024 #include "math_types.h"
00025
00026 #include "ntk/camera/rgbd_processor.h"
00027 #include "ntk/camera/calibration.h"
00028 #include "ntk/mesh/mesh_generator.h"
00029 #include <boost/filesystem.hpp>
00030
00035 class kinect_cloud : public cloud3
00036 {
00037 public:
00057 kinect_cloud (const options &opts, const calibration &_calib)
00058 : cloud3 (opts, _calib),
00059 input_template (opts.data_template ())
00060 {
00061 mesh.setUseColor(true);
00062
00063 const std::string calib_file = opts.kinect_calibration ();
00064 kinect_calibration.loadFromFile (calib_file.c_str ());
00065
00066
00067 processor.setFilterFlag (ntk::RGBDProcessor::ComputeKinectDepthBaseline, true);
00068 processor.setFilterFlag (ntk::RGBDProcessor::FilterMedian, true);
00069 processor.setFilterFlag (ntk::RGBDProcessor::ComputeNormals, true);
00070 processor.setFilterFlag (ntk::RGBDProcessor::SmoothDepth, true);
00071
00072 init ();
00073 }
00074
00075 virtual bool read_background (const std::string &depth_background)
00076 {
00077 point_vector P;
00078 const int num_frames = 5;
00079 P.reserve (num_frames * 640 * 480);
00080 bg_normals.reserve (num_frames * 640 * 480);
00081 for (int bg_frame = 15; bg_frame < 15+num_frames; bg_frame++)
00082 {
00083 const char *format = "%s/view%.4d";
00084 char buffer [100];
00085 sprintf (buffer, format, depth_background.c_str (), bg_frame);
00086
00087 if (boost::filesystem::is_directory (buffer))
00088 {
00089 current_frame.loadFromDir (buffer, &kinect_calibration);
00090 processor.processImage (current_frame);
00091 mesh.generate (current_frame);
00092 const cv::Mat3f &mesh_normals = current_frame.normal ();
00093
00094
00095 const size_t num_points = mesh.mesh ().vertices.size ();
00096 for (size_t k = 0; k < num_points; k++)
00097 {
00098 const cv::Point3f xyz = mesh.mesh ().vertices [k];
00099
00100 const double s = 1000.0;
00101 const vector3 point = calib.camera_to_world (s*vector3 (xyz.x, xyz.y, -xyz.z));
00102 P.push_back (point);
00103
00104 const int row = k / mesh_normals.cols, col = k - row * mesh_normals.cols;
00105 const cv::Vec3f normal = mesh_normals (row, col);
00106
00107 const vector3 tmp = calib.camera_to_world (s*vector3 (normal [0] + xyz.x, normal [1] + xyz.y, -normal [2] - xyz.z)) - point;
00108 bg_normals.push_back (unit (tmp));
00109 }
00110 }
00111 else
00112 break;
00113 }
00114
00115 if (P.size () > 0)
00116 bg_nearest_cloud.refresh (P);
00117
00118 return (P.size () > 0);
00119 }
00120
00121
00136 bool refresh (bool goto_next = true)
00137 {
00138
00139 char dirname [100];
00140 sprintf (dirname, "%s/view%.4d", input_template.c_str (), frame);
00141 if (goto_next) frame ++;
00142
00143 const bool found = boost::filesystem::is_directory (dirname);
00144 if (!found)
00145 {
00146 std::cerr << "kinect_cloud::refresh: could not open '"
00147 << dirname << "' for reading" << std::endl;
00148 }
00149 else
00150 {
00151
00152 const std::string sdirname (dirname);
00153 current_frame.loadFromDir (sdirname, &kinect_calibration);
00154 processor.processImage (current_frame);
00155 mesh.generate (current_frame);
00156
00157
00158 const size_t num_points = mesh.mesh ().vertices.size ();
00159 points.reserve (num_points / downsample);
00160 normals.reserve (num_points / downsample);
00161 colours.reserve (num_points / downsample);
00162
00163
00164 const std::vector<cv::Point3f> &vertices = mesh.mesh ().vertices;
00165 const cv::Mat3f &mesh_normals = current_frame.normal ();
00166 const std::vector<cv::Vec3b> &colors = mesh.mesh ().colors;
00167 for (size_t k = 0; k < num_points; k += downsample)
00168 {
00169 const cv::Point3f xyz = vertices [k];
00170 const int row = k / mesh_normals.cols, col = k - row * mesh_normals.cols;
00171 const cv::Vec3f normal = mesh_normals (row, col);
00172 const cv::Vec3b rgb = colors [k];
00173
00174 const double s = 1000.0;
00175 const vector3 point = calib.camera_to_world (s*vector3 (xyz.x, xyz.y, -xyz.z));
00176
00177 if (!use_background_subtraction || (point (1) > 1.75 && bg_nearest_cloud.nearest_distance (point) > depth_threshold && norm2 (point) < 200.0))
00178 {
00179 points.push_back (point);
00180 const vector3 tmp = calib.camera_to_world (s*vector3 (normal [0] + xyz.x, normal [1] + xyz.y, -normal [2] - xyz.z)) - point;
00181 normals.push_back (unit (tmp));
00182 colours.push_back (vector3 (rgb [0], rgb [1], rgb [2]) / 255.0);
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191 nearest_cloud.refresh (points);
00192 }
00193
00194 return found;
00195 }
00196
00206 vector3 normal (const size_t i) const
00207 {
00208 if (i < normals.size ())
00209 return normals [i];
00210 else
00211 return vector3 (0, 0, 0);
00212 };
00213
00223 vector3 bg_normal (const size_t i) const
00224 {
00225 if (i < bg_normals.size ())
00226 return bg_normals [i];
00227 else
00228 return vector3 (0, 0, 0);
00229 }
00230
00234 void show () const
00235 {
00236 cloud3::show ();
00237
00238 glDisable (GL_LIGHTING);
00239 glBegin (GL_LINES);
00240 glColor3f (0.2, 0.2, 0.8);
00241 for (size_t k = 0; k < points.size (); k+=20)
00242 {
00243 const vector3 p = points [k];
00244 const vector3 normal = p + normals [k];
00245 glVertex3f (p [0], p [1], p [2]);
00246 glVertex3f (normal [0], normal [1], normal [2]);
00247 }
00248 glEnd ();
00249 glEnable (GL_LIGHTING);
00250 }
00251
00252 protected:
00253 const std::string input_template;
00254 ntk::RGBDCalibration kinect_calibration;
00255 ntk::NiteProcessor processor;
00256 ntk::RGBDImage current_frame;
00257 ntk::MeshGenerator mesh;
00258 point_vector normals, bg_normals;
00259 };
00260
00261 #endif // KINECT_CLOUD_H