pcd_to_image_projector_algo.cpp
Go to the documentation of this file.
00001 /* 
00002  * Copyright (c) 2010, Dejan Pangercic <dejan.pangercic@cs.tum.edu>, 
00003  Zoltan-Csaba Marton <marton@cs.tum.edu>, Nico Blodow <blodow@cs.tum.edu>
00004  * All rights reserved.
00005  * 
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  * 
00009  *     * Redistributions of source code must retain the above copyright
00010  *       notice, this list of conditions and the following disclaimer.
00011  *     * Redistributions in binary form must reproduce the above copyright
00012  *       notice, this list of conditions and the following disclaimer in the
00013  *       documentation and/or other materials provided with the distribution.
00014  *     * Neither the name of Willow Garage, Inc. nor the names of its
00015  *       contributors may be used to endorse or promote products derived from
00016  *       this software without specific prior written permission.
00017  * 
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028  * POSSIBILITY OF SUCH DAMAGE.
00029  */
00030 
00031 
00032 #include <image_algos/pcd_to_image_projector_algo.h>
00033 #include "highgui.h"  
00034 
00035 using namespace image_algos;
00036 
00037 void  PCDToImageProjector::init (ros::NodeHandle& nh)
00038 {
00039   nh_ = nh;
00040   nh_.param("origin", origin_, std::string("/RightEyeCalcOff"));
00041   nh_.param("child", child_, std::string("/map"));
00042   //nh_.param("input_image_topic", input_image_topic_, std::string("/cop/left/camera"));
00043   //nh_.param("input_cloud_topic", input_cloud_topic_, std::string("/swissranger_test/cloud_sr"));
00044   //nh_.param("output_cluster_topic", output_cluster_topic_, std::string("output_cluster"));
00045   //nh_.param("output_image_topic", output_image_topic_, std::string("image_with_projected_cluster"));
00046   nh_.param("focal_length", focal_length_, 0.00641331974023884);
00047   nh_.param("proj_center_x", proj_center_x_, 833.248646581603);
00048   nh_.param("proj_center_y", proj_center_y_, 661.107370424523);
00049   nh_.param("pix_size_x", pix_size_x_, 7.43100103980579e-06);
00050   nh_.param("pix_size_y", pix_size_y_, 7.4e-06);
00051   //image_sub_ = it_.subscribe(input_image_topic_, 1, &PointCloudToImageProjector::image_cb, this);
00052   //cloud_sub_= nh_.subscribe (input_cloud_topic_, 10, &PointCloudToImageProjector::cloud_cb, this);
00053   //image_pub_ = it_.advertise(output_image_topic_, 1);
00054 }
00055 
00056 
00057 void  PCDToImageProjector::pre  ()
00058 {
00059   //  subimage_ = boost::shared_ptr <OutputType>(new OutputType ());
00060 }
00061 
00062 
00063 void  PCDToImageProjector::post ()
00064 {
00065   cvReleaseImage(&subimage_);
00066   //Nothing TODO
00067 }
00068 
00069 
00070 std::vector<std::string>  PCDToImageProjector::requires ()
00071 {
00072   return std::vector<std::string>();
00073 }
00074 
00075 
00076 std::vector<std::string>  PCDToImageProjector::provides ()
00077 {
00078   return std::vector<std::string>();
00079 }
00080 
00081 void PCDToImageProjector::project_3D_point(const double &x, const double &y, const double &z, int &row, int &column)
00082 {
00083   double temp1,temp2;
00084   if (focal_length_ > 0.0)
00085   {
00086     temp1 = focal_length_ * (x / z );
00087     temp2 = focal_length_ * (y / z );
00088   }
00089   else
00090   {
00091     temp1 = x;
00092     temp2 = y;
00093   }
00094   column = ( temp1 / pix_size_x_ ) + proj_center_x_;
00095   row = ( temp2 / pix_size_y_ ) + proj_center_y_;
00096 }
00097 
00098 
00099 std::string PCDToImageProjector::process (sensor_msgs::PointCloud &cloud_in, IplImage *image)
00100 {
00101   try
00102   {
00103     tf_listener_.transformPointCloud(origin_, cloud_in, cloud_in);
00104   }
00105   catch (tf::TransformException ex)
00106   {
00107     ROS_ERROR("[PCDToImageProjector:] %s",ex.what());
00108   }
00109   ROS_INFO("[PCDToImageProjector:] cloud transformed to %s", origin_.c_str());
00110   //create a sequence storage for projected points 
00111   CvMemStorage* stor = cvCreateMemStorage (0);
00112   CvSeq* seq = cvCreateSeq (CV_SEQ_ELTYPE_POINT, sizeof (CvSeq), sizeof (CvPoint), stor);
00113   if (cloud_in.points.size() == 0)
00114   {
00115     ROS_WARN("[PCDToImageProjector:] Point cloud points with size 0!!! Returning.");
00116     return std::string("[PCDToImageProjector:] Point cloud points with size 0!!! Returning.");
00117   }
00118   for (unsigned long i = 0; i < cloud_in.points.size(); i++)
00119   {
00120     cv::Point3d pt_cv(cloud_in.points[i].x, cloud_in.points[i].y, cloud_in.points[i].z);
00121     CvPoint uv;
00122     project_3D_point(pt_cv.x, pt_cv.y, pt_cv.z, uv.y, uv.x);
00123     if (uv.x < 0 || uv.x > image->width)
00124     {
00125       ROS_WARN("[PCDToImageProjector:] width out of bounds");
00126       continue;
00127     }
00128     if (uv.y < 0 || uv.y > image->height)
00129     {
00130       ROS_WARN("[PCDToImageProjector:] height out of bounds");
00131       continue;
00132     }
00133     //static const int RADIUS = 3;
00134     //cvCircle(image, uv, RADIUS, CV_RGB(255,0,0), -1);
00135     cvSeqPush( seq, &uv );
00136   }
00137   
00138   CvRect rect = cvBoundingRect(seq);
00139   if (rect.width == 0 || rect.height == 0)
00140   {
00141     ROS_WARN("[PCDToImageProjector:] Rectangle's width = height = 0. This is impossible. Skipping ROI extraction.");
00142     return std::string("[PCDToImageProjector:] Rectangle's width = height = 0. This is impossible. Skipping ROI extraction.");
00143   }
00144   CvPoint pt1, pt2;
00145   pt1.x = rect.x;
00146   //check boundary, increase ROI for 10%
00147   if ((rect.x + (rect.width + 0.1*rect.width)) > image->width)
00148   {
00149     rect.width =  image->width - rect.x;
00150   }
00151   else 
00152     rect.width = rect.width + 0.1 * rect.width;
00153   
00154   pt2.x = rect.x + rect.width;
00155   pt1.y = rect.y;
00156   
00157   //check boundary, increase ROI for 10%
00158   if ((rect.y + (rect.height + 0.1*rect.height)) > image->height)
00159   {
00160     rect.height =  image->height - rect.y;
00161   }
00162   else
00163     rect.height = rect.height + 0.1 * rect.height;
00164   pt2.y = rect.y+rect.height;
00165   
00166   //draw rectangle around the points
00167   //cvRectangle(image, pt1, pt2, CV_RGB(255,0,0), 3, 8, 0 );
00168   cvClearMemStorage( stor );
00169   
00170   //get subimage_, aka region of interest
00171   
00172   cvSetImageROI(image,rect);
00173   // sub-image
00174   subimage_ = cvCreateImage( cvSize(rect.width, rect.height), image->depth, image->nChannels );
00175   cvCopy(image, subimage_);
00176   cvResetImageROI(image); // release image ROI
00177   //roi_ = bridge_.cvToImgMsg(subimage_)
00178   //ROS_INFO("[PCDToImageProjector:] image published to %s", output_image_topic_.c_str());
00179   return std::string ("ok");
00180 }
00181 
00182 std::string PCDToImageProjector::process (geometry_msgs::Polygon &cloud_in, IplImage *image)
00183 {
00184   //create a sequence storage for projected points 
00185   CvMemStorage* stor = cvCreateMemStorage (0);
00186   CvSeq* seq = cvCreateSeq (CV_SEQ_ELTYPE_POINT, sizeof (CvSeq), sizeof (CvPoint), stor);
00187   if (cloud_in.points.size() == 0)
00188   {
00189     ROS_WARN("[PCDToImageProjector:] Point cloud points with size 0!!! Returning.");
00190     return std::string("[PCDToImageProjector:] Point cloud points with size 0!!! Returning.");
00191   }
00192   for (unsigned long i = 0; i < cloud_in.points.size(); i++)
00193   {
00194     //transform polygon to right camera frame
00195     geometry_msgs::PointStamped Pstamped_local;
00196     Pstamped_local.point.x = cloud_in.points[i].x;
00197     Pstamped_local.point.y = cloud_in.points[i].y;
00198     Pstamped_local.point.z = cloud_in.points[i].z;
00199     Pstamped_local.header.frame_id = child_;
00200     geometry_msgs::PointStamped Pstamped_global;
00201     try
00202     {
00203       tf_listener_.transformPoint(origin_, Pstamped_local, Pstamped_global);
00204       cloud_in.points[i].x = Pstamped_global.point.x;
00205       cloud_in.points[i].y = Pstamped_global.point.y;
00206       cloud_in.points[i].z = Pstamped_global.point.z;
00207     }
00208     catch (tf::TransformException ex)
00209     {
00210       ROS_ERROR("[PCDToImageProjector:] %s",ex.what());
00211       return ("PCDToImageProjector: failed polygon transform");
00212     }
00213 
00214     cv::Point3d pt_cv(cloud_in.points[i].x, cloud_in.points[i].y, cloud_in.points[i].z);
00215     CvPoint uv;
00216     project_3D_point(pt_cv.x, pt_cv.y, pt_cv.z, uv.y, uv.x);
00217     if (uv.x < 0 || uv.x > image->width)
00218     {
00219       ROS_WARN("[PCDToImageProjector:] width out of bounds");
00220       continue;
00221     }
00222     if (uv.y < 0 || uv.y > image->height)
00223     {
00224       ROS_WARN("[PCDToImageProjector:] height out of bounds");
00225       continue;
00226     }
00227     //static const int RADIUS = 3;
00228     //cvCircle(image, uv, RADIUS, CV_RGB(255,0,0), -1);
00229     cvSeqPush( seq, &uv );
00230   }
00231   CvRect rect = cvBoundingRect(seq);
00232   if (rect.width == 0 || rect.height == 0)
00233   {
00234     ROS_WARN("[PCDToImageProjector:] Rectangle's width = height = 0. This is impossible. Skipping ROI extraction.");
00235     return std::string("[PCDToImageProjector:] Rectangle's width = height = 0. This is impossible. Skipping ROI extraction.");
00236   }
00237   CvPoint pt1, pt2;
00238   pt1.x = rect.x;
00239   //check boundary, increase ROI for 10%
00240   if ((rect.x + (rect.width + 0.1*rect.width)) > image->width)
00241   {
00242     rect.width =  image->width - rect.x;
00243   }
00244   else 
00245     rect.width = rect.width + 0.1 * rect.width;
00246     
00247   pt2.x = rect.x + rect.width;
00248   pt1.y = rect.y;
00249     
00250   //check boundary, increase ROI for 10%
00251   if ((rect.y + (rect.height + 0.1*rect.height)) > image->height)
00252   {
00253     rect.height =  image->height - rect.y;
00254   }
00255   else
00256     rect.height = rect.height + 0.1 * rect.height;
00257   pt2.y = rect.y+rect.height;
00258     
00259   //draw rectangle around the points
00260   //cvRectangle(image, pt1, pt2, CV_RGB(255,0,0), 3, 8, 0 );
00261   cvClearMemStorage( stor );
00262     
00263   //get subimage_, aka region of interest
00264     
00265   cvSetImageROI(image,rect);
00266   // sub-image
00267   subimage_ = cvCreateImage( cvSize(rect.width, rect.height), image->depth, image->nChannels );
00268   cvCopy(image, subimage_);
00269   cvResetImageROI(image); // release image ROI
00270   //roi_ = bridge_.cvToImgMsg(subimage_)
00271   //ROS_INFO("[PCDToImageProjector:] image published to %s", output_image_topic_.c_str());
00272   return std::string ("ok");
00273 }
00274 
00275 
00276 PCDToImageProjector::OutputType PCDToImageProjector::output () 
00277 {
00278   return subimage_;
00279 };
00280 
00281 
00282 #ifdef CREATE_NODE
00283 int main (int argc, char* argv[])
00284 {
00285   return standalone_node < PCDToImageProjector> (argc, argv);
00286 }
00287 #endif
00288 


image_algos
Author(s): Dejan Pangercic
autogenerated on Mon Oct 6 2014 09:35:23