00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef TRICLOPS_CLOUD_H
00017 #define TRICLOPS_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 "cvBumblebee.h"
00027 #include <boost/filesystem.hpp>
00028
00029 #ifdef HAVE_TRICLOPS
00030
00036 class triclops_cloud : public cloud3
00037 {
00038 public:
00058 triclops_cloud (const options &opts, const calibration &_calib)
00059 : cloud3 (opts, _calib),
00060 cvb (opts.bumblebee_configuration ()),
00061 left_image_template (opts.left_image_template ()),
00062 right_image_template (opts.right_image_template ())
00063 {
00064 const CvSize depth_size = cvb.get_depth_size ();
00065 bg_disp = cvCreateImage (depth_size, IPL_DEPTH_16U, 1);
00066 mask = cvCreateImage (depth_size, IPL_DEPTH_8U, 1);
00067
00068 init ();
00069 }
00070
00071 virtual bool read_background (const std::string &depth_background)
00072 {
00073
00074 const CvSize depth_size = cvb.get_depth_size ();
00075 IplImage *accum = cvCreateImage (depth_size, IPL_DEPTH_32S, 1);
00076 IplImage *count = cvCreateImage (depth_size, IPL_DEPTH_8U, 1);
00077 cvZero (accum);
00078 cvZero (count);
00079
00080
00081 const char *input_template = "%s/%s%.6d.png";
00082 point_vector P;
00083 const int num_frames = 5;
00084 for (int bg_frame = 15; bg_frame < 15+num_frames; bg_frame++)
00085 {
00086 char left_file [100], right_file [100];
00087 sprintf (left_file, input_template, depth_background.c_str (), "left", bg_frame);
00088 sprintf (right_file, input_template, depth_background.c_str (), "right", bg_frame);
00089
00090 IplImage *left = cvLoadImage (left_file);
00091 IplImage *right = cvLoadImage (right_file);
00092
00093 if (left && right)
00094 {
00095
00096 cvSmooth (left, left, CV_GAUSSIAN, 3);
00097 cvSmooth (right, right, CV_GAUSSIAN, 3);
00098
00099 cvb.set_images (left, right);
00100 IplImage *disp = cvb.get_disparity ();
00101
00102
00103 for (int x = 0; x < depth_size.width; x++)
00104 for (int y = 0; y < depth_size.height; y++)
00105 if (!invalid_disparity (GRAY16 (disp, x, y)))
00106 {
00107 GRAY32 (accum, x, y) += (int) GRAY16 (disp, x, y);
00108 GRAY (count, x, y) ++;
00109 }
00110
00111 cvReleaseImage (&left);
00112 cvReleaseImage (&right);
00113 cvReleaseImage (&disp);
00114 }
00115 }
00116
00117 P.reserve (depth_size.width * depth_size.height);
00118 for (int x = 0; x < depth_size.width; x++)
00119 for (int y = 0; y < depth_size.height; y++)
00120 if (GRAY (count, x, y) > 0)
00121 {
00122 GRAY16 (bg_disp, x, y) = (double)GRAY32 (accum, x, y) / (double)GRAY (count, x, y);
00123 bool valid;
00124 const vector3 xyz = cvb.get_xyz (GRAY16 (bg_disp, x, y), x, y, valid);
00125 P.push_back (calib.camera_to_world (xyz));
00126 }
00127 else
00128 GRAY16 (bg_disp, x, y) = NO_DISPARITY;
00129
00130 cvReleaseImage (&accum);
00131 cvReleaseImage (&count);
00132
00133 if (P.size () > 0)
00134 bg_nearest_cloud.refresh (P);
00135
00136 return (P.size () > 0);
00137 }
00138
00153 bool refresh (bool goto_next = true)
00154 {
00155
00156 char left_file [100], right_file [100];
00157 sprintf (left_file, left_image_template.c_str (), frame);
00158 sprintf (right_file, right_image_template.c_str (), frame);
00159 if (goto_next) frame ++;
00160
00161 IplImage *left = cvLoadImage (left_file);
00162 IplImage *right = cvLoadImage (right_file);
00163
00164 const bool found = (left && right);
00165 if (!found)
00166 {
00167 std::cerr << "triclops_cloud::refresh: could not open '"
00168 << left_file << "' / '" << right_file << "' for reading" << std::endl;
00169 }
00170 else
00171 {
00172
00173 cvSmooth (left, left, CV_GAUSSIAN, 3);
00174 cvSmooth (right, right, CV_GAUSSIAN, 3);
00175
00176 cvb.set_images (left, right);
00177 IplImage *disp = cvb.get_disparity ();
00178
00179 depth_bgsub (disp, bg_disp, mask, 250);
00180
00181
00182 const CvSize size = cvGetSize (disp);
00183 const CvSize imsize = cvGetSize (left);
00184 const size_t num_points = size.width * size.height;
00185 points.clear ();
00186 points.reserve (num_points / downsample);
00187 colours.clear ();
00188 colours.reserve (num_points / downsample);
00189
00190
00191 const double sample_scale = (double)imsize.width / (double)size.width;
00192 int count = 0;
00193 for (int x = 0; x < size.width; x++)
00194 {
00195 for (int y = 0; y < size.height; y++)
00196 {
00197 if (GRAY (mask, x, y) == 0 || count++ % downsample != 0)
00198 continue;
00199
00200 bool valid;
00201 const vector3 xyz = cvb.get_xyz (x, y, valid);
00202
00203 if (valid)
00204 {
00205 const vector3 p = calib.camera_to_world (xyz);
00206
00207 const int xx = sample_scale*x, yy = sample_scale*y;
00208 const float red = ((float)RED (right, xx, yy)) / 255.0f;
00209 const float green = ((float)GREEN (right, xx, yy)) / 255.0f;
00210 const float blue = ((float)BLUE (right, xx, yy)) / 255.0f;
00211 const vector3 rgb (red, green, blue);
00212
00213 points.push_back (p);
00214 colours.push_back (rgb);
00215 }
00216 }
00217 }
00218
00219
00220
00221
00222
00223
00224 nearest_cloud.refresh (points);
00225
00226
00227 cvReleaseImage (&left);
00228 cvReleaseImage (&right);
00229 cvReleaseImage (&disp);
00230 }
00231
00232 return found;
00233 }
00234
00246 vector3 bg_normal (const size_t i) const
00247 {
00248 return vector3 (0, 0, 0);
00249 }
00250
00266 void depth_bgsub (IplImage *im, IplImage *bg, IplImage *dest, int threshold)
00267 {
00268 cvZero (dest);
00269
00270 const CvSize size = cvGetSize (im);
00271 for (int x = 0; x < size.width; x++)
00272 {
00273 for (int y = 0; y < size.height; y++)
00274 {
00275 unsigned short vim = GRAY16 (im, x, y);
00276 unsigned short vbg = GRAY16 (bg, x, y);
00277
00278 unsigned char result;
00279 if (invalid_disparity (vbg) && !invalid_disparity (vim))
00280 result = 255;
00281 else if (invalid_disparity (vbg))
00282 result = 0;
00283 else if (!invalid_disparity (vbg) && !invalid_disparity (vim) && abs (vbg - vim) > threshold)
00284 result = 255;
00285 else
00286 result = 0;
00287
00288 GRAY (dest, x, y) = result;
00289 }
00290 }
00291
00292 cvErode (dest, dest, NULL, 3);
00293 cvDilate (dest, dest, NULL, 3);
00294
00295
00296
00297
00298 }
00299
00300 protected:
00301 cvBumblebee cvb;
00302 const std::string left_image_template, right_image_template;
00303 IplImage *bg_disp, *mask;
00304 };
00305
00306 #else // HAVE_TRICLOPS
00307
00308
00309 class triclops_cloud : public cloud3
00310 {
00311 public:
00312 triclops_cloud (const options &opts, const calibration &_calib)
00313 : cloud3 (opts, _calib)
00314 {
00315 std::cerr << "Program was not linked with TriClops" << std::endl;
00316 exit (-1);
00317 init ();
00318 }
00319
00320 virtual bool read_background (const std::string &depth_background)
00321 {
00322 return false;
00323 }
00324
00325 bool refresh (bool goto_next = true)
00326 {
00327 std::cerr << "Program was not linked with TriClops" << std::endl;
00328 exit (-1);
00329 return false;
00330 }
00331
00332 vector3 bg_normal (const size_t i) const
00333 {
00334 return vector3 (0, 0, 0);
00335 }
00336 };
00337
00338 #endif // HAVE_TRICLOPS
00339 #endif // TRICLOPS_CLOUD_H