image_grabber.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2012-, Open Perception, Inc.
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of the copyright holder(s) nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  */
00037 // Looking for PCL_BUILT_WITH_VTK
00038 #include <pcl/pcl_config.h>
00039 #include <pcl/io/image_grabber.h>
00040 #include <pcl/point_cloud.h>
00041 #include <pcl/point_types.h>
00042 #include <pcl/io/pcd_io.h>
00043 #include <pcl/for_each_type.h>
00044 #include <pcl/io/lzf_image_io.h>
00045 #include <pcl/console/time.h>
00046 
00047 #ifdef PCL_BUILT_WITH_VTK
00048   #include <vtkImageReader2.h>
00049   #include <vtkImageReader2Factory.h>
00050   #include <vtkImageData.h>
00051   #include <vtkSmartPointer.h>
00052   #include <vtkTIFFReader.h>
00053   #include <vtkPNGReader.h>
00054   #include <vtkJPEGReader.h>
00055   #include <vtkPNMReader.h>
00056 #endif
00057 
00060 struct pcl::ImageGrabberBase::ImageGrabberImpl
00061 {
00063   ImageGrabberImpl (pcl::ImageGrabberBase& grabber, 
00064                     const std::string& dir, 
00065                     float frames_per_second, 
00066                     bool repeat, 
00067                     bool pclzf_mode=false);
00069   ImageGrabberImpl (pcl::ImageGrabberBase& grabber, 
00070                     const std::string& rgb_dir, 
00071                     const std::string& depth_dir, 
00072                     float frames_per_second, 
00073                     bool repeat);
00074   ImageGrabberImpl (pcl::ImageGrabberBase& grabber, 
00075                     const std::vector<std::string>& depth_image_files, 
00076                     float frames_per_second, 
00077                     bool repeat);
00078   
00079   void 
00080   trigger ();
00082   void 
00083   loadNextCloud ();
00084   
00086   bool
00087   getCloudAt (size_t idx, pcl::PCLPointCloud2 &blob, Eigen::Vector4f &origin, Eigen::Quaternionf &orientation,
00088               double &fx, double &fy, double &cx, double &cy) const;
00089   
00091   bool
00092   getCloudVTK (size_t idx, pcl::PCLPointCloud2 &blob, Eigen::Vector4f &origin, Eigen::Quaternionf &orientation) const;
00094   bool
00095   getCloudPCLZF (size_t idx, pcl::PCLPointCloud2 &blob, Eigen::Vector4f &origin, Eigen::Quaternionf &orientation,
00096                  double &fx, double &fy, double &cx, double &cy) const;
00097 
00100   void
00101   loadDepthAndRGBFiles (const std::string &dir);
00104   void
00105   loadDepthAndRGBFiles (const std::string &depth_dir, const std::string &rgb_dir);
00107   //  our list accordingly
00108   void
00109   loadPCLZFFiles (const std::string &dir);
00110 
00112   bool
00113   isValidExtension (const std::string &extension);
00114 
00116   void
00117   rewindOnce ();
00118 
00121   bool
00122   getTimestampFromFilepath (const std::string &filepath, uint64_t &timestamp) const;
00123 
00124   size_t
00125   numFrames () const;
00126 
00127   
00128 #ifdef PCL_BUILT_WITH_VTK
00129 
00130   bool
00131   getVtkImage (const std::string &filename, vtkSmartPointer<vtkImageData> &image) const;
00132 #endif//PCL_BUILT_WITH_VTK
00133   
00134   pcl::ImageGrabberBase& grabber_;
00135   float frames_per_second_;
00136   bool repeat_;
00137   bool running_;
00138   // VTK
00139   std::vector<std::string> depth_image_files_;
00140   std::vector<std::string> rgb_image_files_;
00141   // PCLZF
00142   std::vector<std::string> depth_pclzf_files_;
00143   std::vector<std::string> rgb_pclzf_files_;
00144   std::vector<std::string> xml_files_;
00145 
00146   size_t cur_frame_;
00147 
00148   TimeTrigger time_trigger_;
00149 
00150   pcl::PCLPointCloud2 next_cloud_;
00152   pcl::PointCloud<pcl::PointXYZ> next_cloud_depth_;
00153   pcl::PointCloud<pcl::PointXYZRGBA> next_cloud_color_;
00154   Eigen::Vector4f origin_;
00155   Eigen::Quaternionf orientation_;
00156   EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00157   bool valid_;
00159   //  (so we don't attempt to adjust for QVGA, QQVGA, etc).
00160   bool pclzf_mode_;
00161 
00162   float depth_image_units_;
00163 
00164   bool manual_intrinsics_;
00165   double focal_length_x_;
00166   double focal_length_y_;
00167   double principal_point_x_;
00168   double principal_point_y_;
00169 
00170   unsigned int num_threads_;
00171 };
00172 
00174 pcl::ImageGrabberBase::ImageGrabberImpl::ImageGrabberImpl (pcl::ImageGrabberBase& grabber, 
00175                                                            const std::string& dir, 
00176                                                            float frames_per_second, 
00177                                                            bool repeat, 
00178                                                            bool pclzf_mode)
00179   : grabber_ (grabber)
00180   , frames_per_second_ (frames_per_second)
00181   , repeat_ (repeat)
00182   , running_ (false)
00183   , depth_image_files_ ()
00184   , rgb_image_files_ ()
00185   , time_trigger_ (1.0 / static_cast<double> (std::max (frames_per_second, 0.001f)), boost::bind (&ImageGrabberImpl::trigger, this))
00186   , next_cloud_ ()
00187   , origin_ ()
00188   , orientation_ ()
00189   , valid_ (false)
00190   , pclzf_mode_(pclzf_mode)
00191   , depth_image_units_ (1E-3f)
00192   , manual_intrinsics_ (false)
00193   , focal_length_x_ (525.)
00194   , focal_length_y_ (525.)
00195   , principal_point_x_ (319.5)
00196   , principal_point_y_ (239.5)
00197   , num_threads_ (1)
00198 {
00199   if(pclzf_mode_)
00200   {
00201     loadPCLZFFiles(dir);
00202   }
00203   else
00204   {
00205     loadDepthAndRGBFiles (dir);
00206   }
00207   cur_frame_ = 0;
00208 }
00209 
00211 pcl::ImageGrabberBase::ImageGrabberImpl::ImageGrabberImpl (pcl::ImageGrabberBase& grabber, 
00212                                                            const std::string& depth_dir, 
00213                                                            const std::string& rgb_dir, 
00214                                                            float frames_per_second, 
00215                                                            bool repeat)
00216   : grabber_ (grabber)
00217   , frames_per_second_ (frames_per_second)
00218   , repeat_ (repeat)
00219   , running_ (false)
00220   , depth_image_files_ ()
00221   , rgb_image_files_ ()
00222   , time_trigger_ (1.0 / static_cast<double> (std::max (frames_per_second, 0.001f)), boost::bind (&ImageGrabberImpl::trigger, this))
00223   , next_cloud_ ()
00224   , origin_ ()
00225   , orientation_ ()
00226   , valid_ (false)
00227   , pclzf_mode_ (false)
00228   , depth_image_units_ (1E-3f)
00229   , manual_intrinsics_ (false)
00230   , focal_length_x_ (525.)
00231   , focal_length_y_ (525.)
00232   , principal_point_x_ (319.5)
00233   , principal_point_y_ (239.5)
00234   , num_threads_ (1)
00235 {
00236   loadDepthAndRGBFiles (depth_dir, rgb_dir);
00237   cur_frame_ = 0;
00238 }
00239 
00241 pcl::ImageGrabberBase::ImageGrabberImpl::ImageGrabberImpl (pcl::ImageGrabberBase& grabber, 
00242                                                            const std::vector<std::string>& depth_image_files, 
00243                                                            float frames_per_second, 
00244                                                            bool repeat)
00245   : grabber_ (grabber)
00246   , frames_per_second_ (frames_per_second)
00247   , repeat_ (repeat)
00248   , running_ (false)
00249   , depth_image_files_ ()
00250   , rgb_image_files_ ()
00251   , time_trigger_ (1.0 / static_cast<double> (std::max (frames_per_second, 0.001f)), boost::bind (&ImageGrabberImpl::trigger, this))
00252   , next_cloud_ ()
00253   , origin_ ()
00254   , orientation_ ()
00255   , valid_ (false)
00256   , pclzf_mode_ (false)
00257   , depth_image_units_ (1E-3f)
00258   , manual_intrinsics_ (false)
00259   , focal_length_x_ (525.)
00260   , focal_length_y_ (525.)
00261   , principal_point_x_ (319.5)
00262   , principal_point_y_ (239.5)
00263   , num_threads_ (1)
00264 {
00265   depth_image_files_ = depth_image_files;
00266   cur_frame_ = 0;
00267 }
00268 
00270 void 
00271 pcl::ImageGrabberBase::ImageGrabberImpl::loadNextCloud ()
00272 {
00273   if (cur_frame_ >= numFrames ())
00274   {
00275     if (repeat_)
00276       cur_frame_ = 0;
00277     else
00278     {
00279       valid_ = false;
00280       return;
00281     }
00282   }
00283   valid_ = getCloudAt (cur_frame_, next_cloud_, origin_, orientation_, 
00284       focal_length_x_, focal_length_y_, principal_point_x_, principal_point_y_);
00285   cur_frame_++;
00286 }
00287 
00289 void 
00290 pcl::ImageGrabberBase::ImageGrabberImpl::trigger ()
00291 {
00292   if (valid_)
00293   {
00294     grabber_.publish (next_cloud_,origin_,orientation_);
00295   }
00296   // Preload the next cloud
00297   loadNextCloud ();
00298 }
00299 
00301 void
00302 pcl::ImageGrabberBase::ImageGrabberImpl::loadDepthAndRGBFiles (const std::string &dir)
00303 {
00304   if (!boost::filesystem::exists (dir) || !boost::filesystem::is_directory (dir))
00305   {
00306     PCL_ERROR ("[pcl::ImageGrabber::loadDepthAndRGBFiles] Error: attempted to instantiate a pcl::ImageGrabber from a path which"
00307                " is not a directory: %s", dir.c_str ());
00308     return;
00309   }
00310   std::string pathname;
00311   std::string extension;
00312   std::string basename;
00313   boost::filesystem::directory_iterator end_itr;
00314   for (boost::filesystem::directory_iterator itr (dir); itr != end_itr; ++itr)
00315   {
00316 #if BOOST_FILESYSTEM_VERSION == 3
00317     extension = boost::algorithm::to_upper_copy (boost::filesystem::extension (itr->path ()));
00318     pathname = itr->path ().string ();
00319     basename = boost::filesystem::basename (itr->path ());
00320 #else
00321     extension = boost::algorithm::to_upper_copy (boost::filesystem::extension (itr->leaf ()));
00322     pathname = itr->path ().filename ();
00323     basename = boost::filesystem::basename (itr->leaf ());
00324 #endif
00325     if (!boost::filesystem::is_directory (itr->status ()) 
00326         && isValidExtension (extension))
00327     {
00328       if (basename.find ("rgb") < basename.npos)
00329       {
00330         rgb_image_files_.push_back (pathname);
00331       }
00332       else if (basename.find ("depth") < basename.npos)
00333       {
00334         depth_image_files_.push_back (pathname);
00335       }
00336     }
00337   }
00338   sort (depth_image_files_.begin (), depth_image_files_.end ());
00339   if (rgb_image_files_.size () > 0)
00340     sort (rgb_image_files_.begin (), rgb_image_files_.end ());
00341 }
00342 
00343 void
00344 pcl::ImageGrabberBase::ImageGrabberImpl::loadDepthAndRGBFiles (const std::string &depth_dir, const std::string &rgb_dir)
00345 {
00346   if (!boost::filesystem::exists (depth_dir) || !boost::filesystem::is_directory (depth_dir))
00347   {
00348     PCL_ERROR ("[pcl::ImageGrabber::loadDepthAndRGBFiles] Error: attempted to instantiate a pcl::ImageGrabber from a path which"
00349                " is not a directory: %s", depth_dir.c_str ());
00350     return;
00351   }
00352   if (!boost::filesystem::exists (rgb_dir) || !boost::filesystem::is_directory (rgb_dir))
00353   {
00354     PCL_ERROR ("[pcl::ImageGrabber::loadDepthAndRGBFiles] Error: attempted to instantiate a pcl::ImageGrabber from a path which"
00355                " is not a directory: %s", rgb_dir.c_str ());
00356     return;
00357   }
00358   std::string pathname;
00359   std::string extension;
00360   std::string basename;
00361   boost::filesystem::directory_iterator end_itr;
00362   // First iterate over depth images
00363   for (boost::filesystem::directory_iterator itr (depth_dir); itr != end_itr; ++itr)
00364   {
00365 #if BOOST_FILESYSTEM_VERSION == 3
00366     extension = boost::algorithm::to_upper_copy (boost::filesystem::extension (itr->path ()));
00367     pathname = itr->path ().string ();
00368     basename = boost::filesystem::basename (itr->path ());
00369 #else
00370     extension = boost::algorithm::to_upper_copy (boost::filesystem::extension (itr->leaf ()));
00371     pathname = itr->path ().filename ();
00372     basename = boost::filesystem::basename (itr->leaf ());
00373 #endif
00374     if (!boost::filesystem::is_directory (itr->status ())
00375         && isValidExtension (extension))
00376     {
00377       if (basename.find ("depth") < basename.npos)
00378       {
00379         depth_image_files_.push_back (pathname);
00380       }
00381     }
00382   }
00383   // Then iterate over RGB images
00384   for (boost::filesystem::directory_iterator itr (rgb_dir); itr != end_itr; ++itr)
00385   {
00386 #if BOOST_FILESYSTEM_VERSION == 3
00387     extension = boost::algorithm::to_upper_copy (boost::filesystem::extension (itr->path ()));
00388     pathname = itr->path ().string ();
00389     basename = boost::filesystem::basename (itr->path ());
00390 #else
00391     extension = boost::algorithm::to_upper_copy (boost::filesystem::extension (itr->leaf ()));
00392     pathname = itr->path ().filename ();
00393     basename = boost::filesystem::basename (itr->leaf ());
00394 #endif
00395     if (!boost::filesystem::is_directory (itr->status ())
00396         && isValidExtension (extension))
00397     {
00398       if (basename.find ("rgb") < basename.npos)
00399       {
00400         rgb_image_files_.push_back (pathname);
00401       }
00402     }
00403   }
00404   if (depth_image_files_.size () != rgb_image_files_.size () )
00405     PCL_WARN ("[pcl::ImageGrabberBase::ImageGrabberImpl::loadDepthAndRGBFiles] : Watch out not same amount of depth and rgb images");
00406   if (depth_image_files_.size () > 0)
00407     sort (depth_image_files_.begin (), depth_image_files_.end ());
00408   else
00409     PCL_ERROR ("[pcl::ImageGrabberBase::ImageGrabberImpl::loadDepthAndRGBFiles] : no depth images added");
00410   if (rgb_image_files_.size () > 0)
00411     sort (rgb_image_files_.begin (), rgb_image_files_.end ());
00412   else
00413     PCL_ERROR ("[pcl::ImageGrabberBase::ImageGrabberImpl::loadDepthAndRGBFiles] : no rgb images added");
00414 }
00415 
00416 
00418 void
00419 pcl::ImageGrabberBase::ImageGrabberImpl::loadPCLZFFiles (const std::string &dir)
00420 {
00421   if (!boost::filesystem::exists (dir) || !boost::filesystem::is_directory (dir))
00422   {
00423     PCL_ERROR ("[pcl::ImageGrabber::loadPCLZFFiles] Error: attempted to instantiate a pcl::ImageGrabber from a path which"
00424                " is not a directory: %s", dir.c_str ());
00425     return;
00426   }
00427   std::string pathname;
00428   std::string extension;
00429   std::string basename;
00430   boost::filesystem::directory_iterator end_itr;
00431   for (boost::filesystem::directory_iterator itr (dir); itr != end_itr; ++itr)
00432   {
00433 #if BOOST_FILESYSTEM_VERSION == 3
00434     extension = boost::algorithm::to_upper_copy (boost::filesystem::extension (itr->path ()));
00435     pathname = itr->path ().string ();
00436     basename = boost::filesystem::basename (itr->path ());
00437 #else
00438     extension = boost::algorithm::to_upper_copy (boost::filesystem::extension (itr->leaf ()));
00439     pathname = itr->path ().filename ();
00440     basename = boost::filesystem::basename (itr->leaf ());
00441 #endif
00442     if (!boost::filesystem::is_directory (itr->status ()) 
00443         && isValidExtension (extension))
00444     {
00445       if (basename.find ("rgb") < basename.npos)
00446         rgb_pclzf_files_.push_back (pathname);
00447       else if (basename.find ("depth") < basename.npos)
00448         depth_pclzf_files_.push_back (pathname);
00449       else
00450         xml_files_.push_back (pathname);
00451 
00452     }
00453   }
00454   sort (depth_pclzf_files_.begin (), depth_pclzf_files_.end ());
00455   if (rgb_pclzf_files_.size () > 0)
00456     sort (rgb_pclzf_files_.begin (), rgb_pclzf_files_.end ());
00457   sort (xml_files_.begin(), xml_files_.end());
00458   if (depth_pclzf_files_.size() != xml_files_.size())
00459   {
00460     PCL_ERROR("[pcl::ImageGrabber::loadPCLZFFiles] # depth clouds != # xml files\n");
00461     return;
00462   }
00463   if (depth_pclzf_files_.size() != rgb_pclzf_files_.size() && rgb_pclzf_files_.size() > 0)
00464   {
00465     PCL_ERROR("[pcl::ImageGrabber::loadPCLZFFiles] # depth clouds != # rgb clouds\n");
00466     return;
00467   }
00468 }
00470 bool
00471 pcl::ImageGrabberBase::ImageGrabberImpl::isValidExtension (const std::string &extension)
00472 {
00473   bool valid;
00474   if(pclzf_mode_)
00475   {
00476     valid = extension == ".PCLZF" || extension == ".XML";
00477   }
00478   else
00479   {
00480     valid = extension == ".TIFF" || extension == ".PNG" 
00481          || extension == ".JPG" || extension == ".JPEG"
00482          || extension == ".PPM";
00483   }
00484   return (valid);
00485 }
00486   
00487 void
00488 pcl::ImageGrabberBase::ImageGrabberImpl::rewindOnce ()
00489 {
00490   if (cur_frame_ > 0)
00491     cur_frame_--;
00492 }
00493   
00495 bool
00496 pcl::ImageGrabberBase::ImageGrabberImpl::getTimestampFromFilepath (
00497     const std::string &filepath, 
00498     uint64_t &timestamp) const
00499 {
00500   // For now, we assume the file is of the form frame_[22-char POSIX timestamp]_*
00501   char timestamp_str[256];
00502   int result = std::sscanf (boost::filesystem::basename (filepath).c_str (), 
00503                             "frame_%22s_%*s",
00504                             timestamp_str);
00505   if (result > 0)
00506   {
00507     // Convert to uint64_t, microseconds since 1970-01-01
00508     boost::posix_time::ptime cur_date = boost::posix_time::from_iso_string (timestamp_str);
00509     boost::posix_time::ptime zero_date (
00510         boost::gregorian::date (1970,boost::gregorian::Jan,1));
00511     timestamp = (cur_date - zero_date).total_microseconds ();
00512     return (true);
00513   }
00514   return (false);
00515 }
00516   
00518 bool
00519 pcl::ImageGrabberBase::ImageGrabberImpl::getCloudAt (size_t idx, 
00520                                                      pcl::PCLPointCloud2 &blob,
00521                                                      Eigen::Vector4f &origin, 
00522                                                      Eigen::Quaternionf &orientation, 
00523                                                      double &fx, 
00524                                                      double &fy, 
00525                                                      double &cx, 
00526                                                      double &cy) const
00527 {
00528   if (depth_image_files_.size () > 0)
00529   {
00530     fx = focal_length_x_;
00531     fy = focal_length_y_;
00532     cx = principal_point_x_;
00533     cy = principal_point_y_;
00534     return (getCloudVTK (idx, blob, origin, orientation) );
00535   }
00536   else if (depth_pclzf_files_.size () > 0)
00537     return (getCloudPCLZF (idx, blob, origin, orientation, fx, fy, cx, cy) );
00538   else
00539   {
00540     PCL_ERROR ("[pcl::ImageGrabber::getCloudAt] Could not find VTK or PCLZF files.\n");
00541     return (false);
00542   }
00543 }  
00544 
00545 bool
00546 pcl::ImageGrabberBase::ImageGrabberImpl::getCloudVTK (size_t idx, 
00547                                                       pcl::PCLPointCloud2 &blob,
00548                                                       Eigen::Vector4f &origin, 
00549                                                       Eigen::Quaternionf &orientation) const
00550 {
00551 #ifdef PCL_BUILT_WITH_VTK
00552   if (idx > depth_image_files_.size ())
00553   {
00554     return (false);
00555   }
00556   unsigned short* depth_pixel;
00557   unsigned char* color_pixel;
00558   vtkSmartPointer<vtkImageData> depth_image;
00559   vtkSmartPointer<vtkImageData> rgb_image;
00560   const std::string &depth_image_file = depth_image_files_[idx];
00561   // If there are RGB files, load an rgb image
00562   if (rgb_image_files_.size () != 0)
00563   {
00564     const std::string &rgb_image_file = rgb_image_files_[idx];
00565     // If we were unable to pull a Vtk image, throw an error
00566     if (!getVtkImage (rgb_image_file, rgb_image) )
00567     {
00568       return (false);
00569     }
00570   }
00571   if (!getVtkImage (depth_image_file, depth_image) )
00572   {
00573     return (false);
00574   }
00575   int* dims = depth_image->GetDimensions ();
00576 
00577   // Fill in image data
00578   depth_pixel = static_cast<unsigned short*>(depth_image->GetScalarPointer ());
00579   
00580   // Set up intrinsics
00581   float scaleFactorX, scaleFactorY;
00582   float centerX, centerY;
00583   if (manual_intrinsics_)
00584   {
00585     scaleFactorX = 1.f / static_cast<float> (focal_length_x_);
00586     scaleFactorY = 1.f / static_cast<float> (focal_length_y_);
00587     centerX = static_cast<float> (principal_point_x_);
00588     centerY = static_cast<float> (principal_point_y_);
00589   }
00590   else
00591   {
00592     // The 525 factor default is only true for VGA. If not, we should scale
00593     scaleFactorX = scaleFactorY = 1/525.f * 640.f / static_cast<float> (dims[0]);
00594     centerX = ((float)dims[0] - 1.f)/2.f;
00595     centerY = ((float)dims[1] - 1.f)/2.f;
00596   }
00597 
00598   if(rgb_image_files_.size() > 0)
00599   {
00600     pcl::PointCloud<pcl::PointXYZRGBA> cloud_color;
00601     cloud_color.width = dims[0];
00602     cloud_color.height = dims[1];
00603     cloud_color.is_dense = false;
00604     cloud_color.points.resize (depth_image->GetNumberOfPoints ());
00605 
00606     for (int y = 0; y < dims[1]; ++y)
00607     {
00608       for (int x = 0; x < dims[0]; ++x, ++depth_pixel)
00609       {
00610         pcl::PointXYZRGBA &pt = cloud_color.at (x,y);
00611         float depth = static_cast<float> (*depth_pixel) * depth_image_units_;
00612         if (depth == 0.0f) 
00613           pt.x = pt.y = pt.z = std::numeric_limits<float>::quiet_NaN ();
00614         else
00615         {
00616           pt.x = (static_cast<float> (x) - centerX) * scaleFactorX * depth;
00617           pt.y = (static_cast<float> (y) - centerY) * scaleFactorY * depth; 
00618           pt.z = depth;
00619         }
00620 
00621         color_pixel = reinterpret_cast<unsigned char*> (rgb_image->GetScalarPointer (x, y, 0));
00622         pt.r = color_pixel[0];
00623         pt.g = color_pixel[1];
00624         pt.b = color_pixel[2];
00625       }
00626     }
00627     // Handle timestamps
00628     uint64_t timestamp;
00629     if (getTimestampFromFilepath (depth_image_file, timestamp))
00630     {
00631       cloud_color.header.stamp = timestamp;
00632     }
00633 
00634     pcl::toPCLPointCloud2 (cloud_color, blob);
00635   }
00636   else
00637   {
00638     pcl::PointCloud<pcl::PointXYZ> cloud;
00639     cloud.width = dims[0];
00640     cloud.height = dims[1];
00641     cloud.is_dense = false;
00642     cloud.points.resize (depth_image->GetNumberOfPoints ());
00643     for (int y = 0; y < dims[1]; ++y)
00644     {
00645       for (int x = 0; x < dims[0]; ++x, ++depth_pixel)
00646       {
00647         pcl::PointXYZ &pt = cloud.at (x,y);
00648         float depth = static_cast<float> (*depth_pixel) * depth_image_units_;
00649         if (depth == 0.0f) 
00650           pt.x = pt.y = pt.z = std::numeric_limits<float>::quiet_NaN ();
00651         else
00652         {
00653           pt.x = ((float)x - centerX) * scaleFactorX * depth;
00654           pt.y = ((float)y - centerY) * scaleFactorY * depth; 
00655           pt.z = depth;
00656         }
00657       }
00658     }
00659     // Handle timestamps
00660     uint64_t timestamp;
00661     if (getTimestampFromFilepath (depth_image_file, timestamp))
00662     {
00663       cloud.header.stamp = timestamp;
00664     }
00665 
00666     pcl::toPCLPointCloud2 (cloud, blob);
00667   }
00668   // Origin 0, orientation is forward
00669   origin = Eigen::Vector4f::Zero ();
00670   orientation = Eigen::Quaternionf::Identity ();
00671 
00672   return (true);
00673 #else
00674     PCL_ERROR ("[pcl::ImageGrabber::loadNextCloudVTK] Attempted to read image files, but PCL was not built with VTK [no -DPCL_BUILT_WITH_VTK]. \n");
00675     return (false);
00676 #endif //PCL_BUILT_WITH_VTK
00677 
00678 }
00679 
00680 bool
00681 pcl::ImageGrabberBase::ImageGrabberImpl::getCloudPCLZF (size_t idx, 
00682                                                         pcl::PCLPointCloud2 &blob,
00683                                                         Eigen::Vector4f &origin, 
00684                                                         Eigen::Quaternionf &orientation, 
00685                                                         double &fx, 
00686                                                         double &fy, 
00687                                                         double &cx, 
00688                                                         double &cy) const
00689 {
00690   if (idx > depth_pclzf_files_.size ())
00691   {
00692     return (false);
00693   }
00694   // Get the proper files
00695   const std::string &depth_pclzf_file = depth_pclzf_files_[idx];
00696   const std::string &xml_file = xml_files_[idx];
00697   if (rgb_pclzf_files_.size () > 0)
00698   {
00699     pcl::PointCloud<pcl::PointXYZRGBA> cloud_color;
00700     const std::string &rgb_pclzf_file = rgb_pclzf_files_[idx];
00701     pcl::io::LZFRGB24ImageReader rgb;
00702     pcl::io::LZFBayer8ImageReader bayer;
00703     pcl::io::LZFYUV422ImageReader yuv;
00704     pcl::io::LZFDepth16ImageReader depth;
00705     if (manual_intrinsics_)
00706     {
00707       pcl::io::CameraParameters manual_params;
00708       manual_params.focal_length_x = focal_length_x_;
00709       manual_params.focal_length_y = focal_length_y_;
00710       manual_params.principal_point_x = principal_point_x_;
00711       manual_params.principal_point_y = principal_point_y_;
00712       fx = focal_length_x_;
00713       fy = focal_length_y_;
00714       cx = principal_point_x_;
00715       cy = principal_point_y_;
00716       rgb.setParameters (manual_params); 
00717       yuv.setParameters (manual_params); 
00718       bayer.setParameters (manual_params); 
00719       depth.setParameters (manual_params); 
00720     }
00721     else
00722     {
00723       rgb.readParameters (xml_file);
00724       yuv.readParameters (xml_file);
00725       bayer.readParameters (xml_file);
00726       depth.readParameters (xml_file);
00727       // update intrinsics
00728       pcl::io::CameraParameters loaded_params = depth.getParameters ();
00729       // Set intrinsics so we can update our estimate, if necessary
00730       fx = loaded_params.focal_length_x;
00731       fy = loaded_params.focal_length_y;
00732       cx = loaded_params.principal_point_x;
00733       cy = loaded_params.principal_point_y;
00734     }
00735     cloud_color.is_dense = false;
00736     if (num_threads_ == 1)
00737     {
00738       if (!rgb.read (rgb_pclzf_file, cloud_color))
00739         if (!yuv.read (rgb_pclzf_file, cloud_color))
00740           bayer.read (rgb_pclzf_file, cloud_color);
00741       depth.read (depth_pclzf_file, cloud_color);
00742     }
00743     else
00744     {
00745       if (!rgb.read (rgb_pclzf_file, cloud_color))
00746         if (!yuv.readOMP (rgb_pclzf_file, cloud_color, num_threads_)) // Only YUV speeds up currently
00747           bayer.read (rgb_pclzf_file, cloud_color);
00748       depth.readOMP (depth_pclzf_file, cloud_color, num_threads_);
00749     }
00750     // handle timestamps
00751     uint64_t timestamp;
00752     if (getTimestampFromFilepath (depth_pclzf_file, timestamp))
00753     {
00754       cloud_color.header.stamp = timestamp;
00755     }
00756     pcl::toPCLPointCloud2 (cloud_color, blob);
00757   }
00758   else
00759   {
00760     pcl::PointCloud<pcl::PointXYZ> cloud;
00761     pcl::io::LZFDepth16ImageReader depth;
00762     if (manual_intrinsics_)
00763     {
00764       pcl::io::CameraParameters manual_params;
00765       manual_params.focal_length_x = focal_length_x_;
00766       manual_params.focal_length_y = focal_length_y_;
00767       manual_params.principal_point_x = principal_point_x_;
00768       manual_params.principal_point_y = principal_point_y_;
00769       // Set intrinsics so we can update our estimate, if necessary
00770       fx = focal_length_x_;
00771       fy = focal_length_y_;
00772       cx = principal_point_x_;
00773       cy = principal_point_y_;
00774       depth.setParameters (manual_params); 
00775     }
00776     else
00777     {
00778       depth.readParameters (xml_file);
00779       // update intrinsics
00780       pcl::io::CameraParameters loaded_params = depth.getParameters ();
00781       fx = loaded_params.focal_length_x;
00782       fy = loaded_params.focal_length_y;
00783       cx = loaded_params.principal_point_x;
00784       cy = loaded_params.principal_point_y;
00785     }
00786     cloud.is_dense = false;
00787     if (num_threads_ == 1)
00788       depth.read (depth_pclzf_file, cloud);
00789     else
00790       depth.readOMP (depth_pclzf_file, cloud, num_threads_);
00791     // handle timestamps
00792     uint64_t timestamp;
00793     if (getTimestampFromFilepath (depth_pclzf_file, timestamp))
00794     {
00795       cloud.header.stamp = timestamp;
00796     }
00797     pcl::toPCLPointCloud2 (cloud, blob);
00798   }
00799 
00800   // Origin 0, orientation is forward
00801   origin = Eigen::Vector4f::Zero ();
00802   orientation = Eigen::Quaternionf::Identity ();
00803   return (true);
00804 }     
00805    
00807 //
00808 #ifdef PCL_BUILT_WITH_VTK
00809 bool
00810 pcl::ImageGrabberBase::ImageGrabberImpl::getVtkImage (
00811     const std::string &filename, 
00812     vtkSmartPointer<vtkImageData> &image) const
00813 {
00814 
00815   vtkSmartPointer<vtkImageReader2> reader;
00816   // Check extension to generate the proper reader
00817   int retval;
00818   std::string upper = boost::algorithm::to_upper_copy (filename);
00819   if (upper.find (".TIFF") < upper.npos)
00820   {
00821     vtkSmartPointer<vtkTIFFReader> tiff_reader = vtkSmartPointer<vtkTIFFReader>::New ();
00822     retval = tiff_reader->CanReadFile (filename.c_str ());
00823     reader = tiff_reader;
00824   }
00825   else if (upper.find (".PNG") < upper.npos)
00826   {
00827     vtkSmartPointer<vtkPNGReader> png_reader = vtkSmartPointer<vtkPNGReader>::New ();
00828     retval = png_reader->CanReadFile (filename.c_str ());
00829     reader = png_reader;
00830   }
00831   else if (upper.find (".JPG") < upper.npos || upper.find (".JPEG") < upper.npos)
00832   {
00833     vtkSmartPointer<vtkJPEGReader> jpg_reader = vtkSmartPointer<vtkJPEGReader>::New ();
00834     retval = jpg_reader->CanReadFile (filename.c_str ());
00835     reader = jpg_reader;
00836   }
00837   else if (upper.find (".PPM") < upper.npos)
00838   {
00839     vtkSmartPointer<vtkPNMReader> ppm_reader = vtkSmartPointer<vtkPNMReader>::New ();
00840     retval = ppm_reader->CanReadFile (filename.c_str ());
00841     reader = ppm_reader;
00842   }
00843   else
00844   {
00845     PCL_ERROR ("[pcl::ImageGrabber::getVtkImage] Attempted to access an invalid filetype: %s\n", filename.c_str ());
00846     return (false);
00847   }
00848   if (retval == 0)
00849   {
00850     PCL_ERROR ("[pcl::ImageGrabber::getVtkImage] Image file can't be read: %s\n", filename.c_str ());
00851     return (false);
00852   }
00853   else if (retval == 1)
00854   {
00855     PCL_ERROR ("[pcl::ImageGrabber::getVtkImage] Can't prove that I can read: %s\n", filename.c_str ());
00856     return (false);
00857   }
00858   reader->SetFileName (filename.c_str ());
00859   reader->Update ();
00860   image = reader->GetOutput ();
00861   return (true);
00862 }
00863 #endif //PCL_BUILT_WITH_VTK
00864 
00866 size_t
00867 pcl::ImageGrabberBase::ImageGrabberImpl::numFrames () const
00868 {
00869   if (pclzf_mode_)
00870     return (depth_pclzf_files_.size ());
00871   else
00872     return (depth_image_files_.size ());
00873 }
00874 
00876 pcl::ImageGrabberBase::ImageGrabberBase (const std::string& directory, float frames_per_second, bool repeat, bool pclzf_mode)
00877   : impl_ (new ImageGrabberImpl (*this, directory, frames_per_second, repeat, pclzf_mode))
00878 {
00879 }
00880 
00882 pcl::ImageGrabberBase::ImageGrabberBase (const std::string& rgb_dir, const std::string &depth_dir, float frames_per_second, bool repeat)
00883   : impl_ (new ImageGrabberImpl (*this, rgb_dir, depth_dir, frames_per_second, repeat))
00884 {
00885 }
00886 
00888 pcl::ImageGrabberBase::ImageGrabberBase (const std::vector<std::string>& depth_image_files, float frames_per_second, bool repeat)
00889   : impl_ (new ImageGrabberImpl (*this, depth_image_files, frames_per_second, repeat))
00890 {
00891 }
00892 
00894 pcl::ImageGrabberBase::~ImageGrabberBase () throw ()
00895 {
00896   stop ();
00897   delete impl_;
00898 }
00899 
00901 void 
00902 pcl::ImageGrabberBase::start ()
00903 {
00904   if (impl_->frames_per_second_ > 0)
00905   {
00906     impl_->running_ = true;
00907     impl_->time_trigger_.start ();
00908   }
00909   else // manual trigger to preload the first cloud
00910     impl_->trigger ();
00911 }
00912 
00914 void 
00915 pcl::ImageGrabberBase::stop ()
00916 {
00917   if (impl_->frames_per_second_ > 0)
00918   {
00919     impl_->time_trigger_.stop ();
00920     impl_->running_ = false;
00921   }
00922 }
00923 
00925 void
00926 pcl::ImageGrabberBase::trigger ()
00927 {
00928   if (impl_->frames_per_second_ > 0)
00929     return;
00930   impl_->trigger ();
00931 }
00932 
00934 bool 
00935 pcl::ImageGrabberBase::isRunning () const
00936 {
00937   return (impl_->running_);
00938 }
00939 
00941 std::string 
00942 pcl::ImageGrabberBase::getName () const
00943 {
00944   return ("ImageGrabber");
00945 }
00946 
00948 void 
00949 pcl::ImageGrabberBase::rewind ()
00950 {
00951   impl_->cur_frame_ = 0;
00952 }
00953 
00955 float 
00956 pcl::ImageGrabberBase::getFramesPerSecond () const
00957 {
00958   return (impl_->frames_per_second_);
00959 }
00960 
00962 bool 
00963 pcl::ImageGrabberBase::isRepeatOn () const
00964 {
00965   return (impl_->repeat_);
00966 }
00967 
00969 void
00970 pcl::ImageGrabberBase::setRGBImageFiles (const std::vector<std::string>& rgb_image_files) 
00971 {
00972   impl_->rgb_image_files_ = rgb_image_files;
00973   impl_->cur_frame_ = 0;
00974 }
00975 
00976 
00978 void
00979 pcl::ImageGrabberBase::setCameraIntrinsics (const double focal_length_x, 
00980                                             const double focal_length_y, 
00981                                             const double principal_point_x, 
00982                                             const double principal_point_y)
00983 {
00984   impl_->focal_length_x_ = focal_length_x;
00985   impl_->focal_length_y_ = focal_length_y;
00986   impl_->principal_point_x_ = principal_point_x;
00987   impl_->principal_point_y_ = principal_point_y;
00988   impl_->manual_intrinsics_ = true;
00989   // If we've already preloaded a valid cloud, we need to recompute it
00990   if (impl_->valid_)
00991   {
00992     impl_->rewindOnce ();
00993     impl_->loadNextCloud ();
00994   }
00995 }
00996 
00997 void
00998 pcl::ImageGrabberBase::getCameraIntrinsics (double &focal_length_x, 
00999                                             double &focal_length_y, 
01000                                             double &principal_point_x, 
01001                                             double &principal_point_y) const
01002 {
01003   focal_length_x = impl_->focal_length_x_;
01004   focal_length_y = impl_->focal_length_y_;
01005   principal_point_x = impl_->principal_point_x_;
01006   principal_point_y = impl_->principal_point_y_;
01007 }
01008 
01009 
01010 
01012 void
01013 pcl::ImageGrabberBase::setDepthImageUnits (const float units)
01014 {
01015   impl_->depth_image_units_ = units;
01016 }
01018 size_t
01019 pcl::ImageGrabberBase::numFrames () const
01020 {
01021   return (impl_->numFrames ());
01022 }
01023 
01025 bool
01026 pcl::ImageGrabberBase::getCloudAt (size_t idx,
01027                                    pcl::PCLPointCloud2 &blob,
01028                                    Eigen::Vector4f &origin, 
01029                                    Eigen::Quaternionf &orientation) const
01030 {
01031   double fx, fy, cx, cy;
01032   return (impl_->getCloudAt (idx, blob, origin, orientation, fx, fy, cx, cy));
01033 }
01034 
01036 bool
01037 pcl::ImageGrabberBase::atLastFrame () const
01038 {
01039   if (impl_->cur_frame_ == numFrames () - 1)
01040     return (true);
01041   else
01042     return (false);
01043 }
01044 
01046 std::string
01047 pcl::ImageGrabberBase::getCurrentDepthFileName () const
01048 {
01049   std::string pathname;
01050   if (impl_->pclzf_mode_)
01051     pathname = impl_->depth_pclzf_files_[impl_->cur_frame_];
01052   else
01053     pathname = impl_->depth_image_files_[impl_->cur_frame_];
01054   std::string basename = boost::filesystem::basename (pathname);
01055   return (basename);
01056 }
01058 std::string
01059 pcl::ImageGrabberBase::getPrevDepthFileName () const
01060 {
01061   std::string pathname;
01062   if (impl_->pclzf_mode_)
01063     pathname = impl_->depth_pclzf_files_[impl_->cur_frame_-1];
01064   else
01065     pathname = impl_->depth_image_files_[impl_->cur_frame_-1];
01066   std::string basename = boost::filesystem::basename (pathname);
01067   return (basename);
01068 }
01069     
01071 std::string
01072 pcl::ImageGrabberBase::getDepthFileNameAtIndex (size_t idx) const
01073 {
01074   std::string pathname;
01075   if (impl_->pclzf_mode_)
01076     pathname = impl_->depth_pclzf_files_[idx];
01077   else
01078     pathname = impl_->depth_image_files_[idx];
01079   std::string basename = boost::filesystem::basename (pathname);
01080   return (basename);
01081 }
01082 
01084 bool
01085 pcl::ImageGrabberBase::getTimestampAtIndex (size_t idx, uint64_t &timestamp) const
01086 {
01087   std::string filename;
01088   if (impl_->pclzf_mode_)
01089     filename = impl_->depth_pclzf_files_[idx];
01090   else
01091     filename = impl_->depth_image_files_[idx];
01092   return (impl_->getTimestampFromFilepath (filename, timestamp));
01093 }
01094 
01096 void
01097 pcl::ImageGrabberBase::setNumberOfThreads (unsigned int nr_threads)
01098 {
01099   impl_->num_threads_ = nr_threads;
01100 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:24:53