pc_head_stitcher.cpp
Go to the documentation of this file.
00001 #include <limits>
00002 #include <opencv/cv.h>
00003 #include <opencv2/imgproc/imgproc.hpp>
00004 #include <opencv2/highgui/highgui.hpp>
00005 
00006 #include <hrl_phri_2011/PHRIPointCloudCapture.h>
00007 #include <hrl_phri_2011/pcl_features.h>
00008 #include <hrl_phri_2011/utils.h>
00009 
00010 typedef hrl_phri_2011::PHRIPointCloudCapture PCC;
00011 typedef map<string, Eigen::Affine3d, less<string>, 
00012             Eigen::aligned_allocator<std::pair<const string, Eigen::Affine3d> > > map_str_t3d;
00013 
00014 void findOverlaps(const PCRGB::Ptr& target_pc, const PCRGB::Ptr& source_pc,
00015                   pcl::IndicesPtr& target_inds_list, pcl::IndicesPtr& source_inds_list, 
00016                   double icp_radius=0.03, bool use_rgb=false, double color_weight=0.001) 
00017                   {
00018     KDTree::Ptr kd_tree(new pcl::KdTreeFLANN<PRGB> ());
00019     kd_tree->setInputCloud(target_pc);
00020     if(use_rgb){
00021         boost::shared_ptr<pcl::DefaultPointRepresentation<PRGB> const> 
00022             pt_rep(new pcl::DefaultPointRepresentation<PRGB>(color_weight, color_weight, color_weight));
00023         kd_tree->setPointRepresentation(pt_rep);
00024     }
00025     vector<bool> target_inds(target_pc->points.size(), false);
00026     vector<bool> source_inds(source_pc->points.size(), false);
00027     for(uint32_t i=0;i<source_pc->points.size();i++) {
00028         vector<int> inds;
00029         vector<float> dists;
00030         kd_tree->radiusSearch(*source_pc, i, icp_radius, inds, dists);
00031         for(uint32_t j=0;j<inds.size();j++) 
00032             target_inds[inds[j]] = true;
00033         if(inds.size() > 0)
00034             source_inds[i] = true;
00035     }
00036     for(uint32_t i=0;i<target_pc->points.size();i++) 
00037         if(target_inds[i])
00038             target_inds_list->push_back(i);
00039     for(uint32_t i=0;i<source_pc->points.size();i++) 
00040         if(source_inds[i])
00041             source_inds_list->push_back(i);
00042 }
00043 
00044 void findTransformFromOverlapICP(const PCRGB::Ptr& target_pc, const PCRGB::Ptr& source_pc,
00045                                  Eigen::Affine3d& tf_mat) 
00046                                  {
00047     int icp_iters, use_rgb;
00048     double color_weight, icp_radius;
00049     ros::param::param<int>("~icp_iters", icp_iters, 10);
00050     ros::param::param<double>("~color_weight", color_weight, 0.0005);
00051     ros::param::param<double>("~icp_radius", icp_radius, 0.05);
00052     ros::param::param<int>("~use_rgb", use_rgb, 1);
00053     ROS_INFO("PS %d %f %f", icp_iters, color_weight, icp_radius);
00054 
00055     pcl::IndicesPtr target_inds_list(new vector<int>()), source_inds_list(new vector<int>());
00056     findOverlaps(target_pc, source_pc, target_inds_list, source_inds_list, icp_radius, use_rgb, color_weight);
00057     ROS_INFO("INDS %d %d", target_inds_list->size(), source_inds_list->size());
00058     PCRGB::Ptr target_pc_ol(new PCRGB());
00059     PCRGB::Ptr source_pc_ol(new PCRGB());
00060     extractIndices(target_pc, target_inds_list, target_pc_ol);
00061     extractIndices(source_pc, source_inds_list, source_pc_ol);
00062     ROS_INFO("PC COUNT %d %d", target_pc_ol->points.size(), source_pc_ol->points.size());
00063     computeICPRegistration(target_pc_ol, source_pc_ol, tf_mat, icp_iters, color_weight);
00064 }
00065 
00066 void erodePC(const PCRGB::Ptr& target_pc, const vector<int>& inds, PCRGB::Ptr& eroded_pc) 
00067 {
00068     cv::Mat pc_img = cv::Mat::zeros(640, 480, CV_32F);
00069     cv::Mat pc_img_eroded = cv::Mat::zeros(640, 480, CV_32F);
00070     for(uint32_t i=0;i<inds.size();i++) 
00071         if(target_pc->points[i].x == target_pc->points[i].x &&
00072            target_pc->points[i].y == target_pc->points[i].y &&
00073            target_pc->points[i].z == target_pc->points[i].z) {
00074             pc_img.at<uint8_t>(inds[i] % 640, inds[i] / 640) = 1.0;
00075         }
00076 
00077     IplImage pc_img_ipl = pc_img, pc_img_eroded_ipl = pc_img_eroded;
00078     int num_erode;
00079     ros::NodeHandle nh_priv("~");
00080     nh_priv.param<int>("num_erode", num_erode, 2);
00081     if(num_erode > 0)
00082         cvErode(&pc_img_ipl, &pc_img_eroded_ipl, NULL, num_erode);
00083     else
00084         pc_img_eroded_ipl = pc_img_ipl;
00085     pcl::IndicesPtr inds_erode(new vector<int>());
00086     for(uint32_t i=0;i<inds.size();i++) 
00087         if(pc_img_eroded.at<uint8_t>(inds[i] % 640, inds[i] / 640) == 1.0)
00088             inds_erode->push_back(i);
00089 
00090     pcl::ExtractIndices<PRGB> extract_inds;
00091     extract_inds.setInputCloud(target_pc);
00092     extract_inds.setIndices(inds_erode);
00093     extract_inds.filter(*eroded_pc);
00094 }
00095 
00096 void extractPCs(const vector<PCC::Ptr> & captures, vector<PCRGB::Ptr>& pc_list) 
00097 {
00098     double z_cutoff;
00099     ros::param::param<double>("~z_cutoff", z_cutoff, -0.2);
00100     BOOST_FOREACH(PCC::Ptr pcc, captures) {
00101         map_str_t3d cap_poses;
00102         for(uint32_t i=0;i<pcc->frame_names.size();i++) 
00103             tf::poseMsgToEigen(pcc->saved_frames[i].pose, cap_poses[pcc->frame_names[i]]);
00104 
00105         PCRGB pc_raw, pc_trans, pc_filtered;
00106         pcl::fromROSMsg(pcc->pc_capture, pc_raw);
00107         std::vector<int> inds;
00108 
00109         Eigen::Affine3d pc_tf(cap_poses["/head_center"].inverse() * cap_poses["/openni_rgb_optical_frame"]);
00110         transformPC(pc_raw, pc_trans, pc_tf);
00111 
00112         for(size_t i=0;i<pc_trans.points.size();i++) {
00113             const PRGB p = pc_trans.points[i];
00114             PRGB new_p;
00115             if(p.x == p.x && p.y == p.y && p.z == p.z &&
00116                p.x > -0.22 && p.x < 0.22 && p.y > -0.15 && p.y < 0.15 && p.z > z_cutoff && p.z < 0.25) {
00117                 new_p.x = p.x; new_p.y = p.y; new_p.z = p.z; new_p.rgb = p.rgb;
00118                 inds.push_back(i);
00119                 pc_filtered.points.push_back(new_p);
00120             } else {
00121                 new_p.x = numeric_limits<float>::quiet_NaN();
00122                 new_p.y = numeric_limits<float>::quiet_NaN();
00123                 new_p.z = numeric_limits<float>::quiet_NaN();
00124             }
00125         }
00126         //boxFilter(pc_trans, pc_filtered, -0.22, 0.22, -0.15, 0.15, -0.2, 0.25);
00127 
00128         //pc_list.push_back(PCRGB::Ptr(new PCRGB(pc_filtered)));
00129         PCRGB::Ptr pc_eroded(new PCRGB());
00130         erodePC(pc_filtered.makeShared(), inds, pc_eroded);
00131         //pc_eroded->header.frame_id = "/head_center";
00132         //pubLoop(*pc_eroded, "/stitched_head");
00133 
00134         pc_list.push_back(pc_eroded);
00135     }
00136 }
00137 
00138 void concatRegisteredPC(PCRGB::Ptr& target_pc, const PCRGB::Ptr& source_pc, double keep_radius) 
00139 {
00140     PCRGB::Ptr source_tf_pc(new PCRGB()), source_filtered_pc(new PCRGB());
00141     Eigen::Affine3d tf_mat;
00142     findTransformFromOverlapICP(target_pc, source_pc, tf_mat);
00143     transformPC(*source_pc, *source_tf_pc, tf_mat);
00144 
00145     pcl::IndicesPtr target_inds_list(new vector<int>()), source_inds_list(new vector<int>());
00146     findOverlaps(target_pc, source_tf_pc, target_inds_list, source_inds_list, keep_radius);
00147     pcl::ExtractIndices<PRGB> extract_inds;
00148     extract_inds.setNegative(true);
00149     extract_inds.setInputCloud(source_tf_pc);
00150     extract_inds.setIndices(source_inds_list);
00151     extract_inds.filter(*source_filtered_pc);
00152     target_pc->operator+=(*source_filtered_pc);
00153 }
00154 
00155 void stitchPCs(std::vector<PCC::Ptr> &captures, double keep_radius) 
00156 {
00157     vector<PCRGB::Ptr> pc_list;
00158     extractPCs(captures, pc_list);
00159     int num_pc = (int) pc_list.size();
00160     PCRGB::Ptr pc_combo(new PCRGB());
00161     pc_combo->operator+=(*pc_list[0]);
00162     ROS_INFO("Begin Stitching");
00163     for(int i=1;i<=num_pc/2-1;i++) {
00164         concatRegisteredPC(pc_combo, pc_list[i], keep_radius);
00165         ROS_INFO("Stitched cloud %d", i);
00166     }
00167     for(int i=num_pc-1;i>=num_pc/2;i--) {
00168         concatRegisteredPC(pc_combo, pc_list[i], keep_radius);
00169         ROS_INFO("Stitched cloud %d", i);
00170     }
00171     pc_combo->header.frame_id = "/head_center";
00172     ROS_INFO("Publishing PC to topic /stitched_head");
00173     pubLoop(*pc_combo, "/stitched_head");
00174 }
00175 
00176 void displayRawPCs(std::vector<PCC::Ptr> &captures) 
00177 {
00178     vector<PCRGB::Ptr> pc_list;
00179     extractPCs(captures, pc_list);
00180     PCRGB pc_combo;
00181     BOOST_FOREACH(PCRGB::Ptr const pc, pc_list) {
00182         pc_combo += *pc;
00183     }
00184     pc_combo.header.frame_id = "/head_center";
00185     pubLoop(pc_combo, "/stitched_head");
00186 }
00187 
00188 int main(int argc, char **argv)
00189 {
00190     ros::init(argc, argv, "pc_head_stitcher");
00191 
00192     // Load bag
00193     rosbag::Bag bag;
00194     bag.open(std::string(argv[1]), rosbag::bagmode::Read);
00195     rosbag::View view(bag, rosbag::TopicQuery("/point_cloud_captures"));
00196     std::vector<PCC::Ptr> captures;
00197     BOOST_FOREACH(rosbag::MessageInstance const m, view) {
00198         captures.push_back(m.instantiate<PCC>());
00199     }
00200     double keep_radius;
00201     ros::NodeHandle nh_priv("~");
00202     nh_priv.param<double>("keep_radius", keep_radius, 0.01);
00203 
00204     if(argc == 2)
00205         stitchPCs(captures, keep_radius);
00206     if(argc == 3 && argv[2][0] == 'd') 
00207         displayRawPCs(captures);
00208 
00209     return 0;
00210 }


hrl_phri_2011
Author(s): Kelsey Hawkins
autogenerated on Wed Nov 27 2013 12:22:40