head_registration.cpp
Go to the documentation of this file.
00001 
00002 #include <hrl_head_registration/head_registration.h>
00003 
00004 #define USE_COLOR_MODEL
00005 
00006 void extractSkinPC(const PCRGB::Ptr& pc_in, PCRGB::Ptr& pc_out, double thresh) 
00007 {
00008     uint8_t r, g, b; 
00009     double skin_like, h, s, l;
00010     for(uint32_t i=0;i<pc_in->size();i++) {
00011         if(PT_IS_NOT_NAN(pc_in, i)) {
00012             extractRGB(pc_in->points[i].rgb, r, g, b);
00013             skin_like = skin_likelihood(r, g, b);
00014             if(skin_like > thresh) 
00015                 COPY_PT_INTO_CLOUD(pc_in, pc_out, i);
00016         }
00017     }
00018 }
00019 
00020 int32_t findClosestPoint(const PCRGB::Ptr& pc, uint32_t u, uint32_t v)
00021 {
00022     if(PT_IS_NOT_NAN(pc, v*640 + u))
00023         return v*640 + u;
00024     for(uint32_t i=1;i<5;i++) {
00025         for(uint32_t j=1;j<5;j++) {
00026             if(PT_IS_NOT_NAN(pc, v*640 + u + i))
00027                 return v*640 + u + i;
00028             if(PT_IS_NOT_NAN(pc, v*640 + u - i))
00029                 return v*640 + u + i;
00030             if(PT_IS_NOT_NAN(pc, v*640 + u + j*640))
00031                 return v*640 + u + i;
00032             if(PT_IS_NOT_NAN(pc, v*640 + u - j*640))
00033                 return v*640 + u + i;
00034         }
00035     }
00036     return -1;
00037 }
00038 
00039 void generateColorModel(const PCRGB::Ptr& pc_in, Eigen::Vector3d& mean, Eigen::Matrix3d& cov)
00040 {
00041     Eigen::MatrixXd X(3, pc_in->size());
00042     for(uint32_t i=0;i<pc_in->size();i++)
00043         extractHSL(pc_in->points[i].rgb, X(0,i), X(1,i), X(2,i));
00044     mean = X.rowwise().sum() / pc_in->size();
00045     cov = X * X.transpose() / pc_in->size() - mean * mean.transpose();
00046 }
00047 
00048 bool extractPCFromColorModel(const PCRGB::Ptr& pc_in, PCRGB::Ptr& pc_out,
00049                              Eigen::Vector3d& mean, Eigen::Matrix3d& cov, double std_devs)
00050 {
00051     double hue_weight;
00052     ros::param::param<double>("~hue_weight", hue_weight, 1.0);
00053     printf("%f\n", hue_weight);
00054 
00055     Eigen::Vector3d x, x_m;
00056     Eigen::Matrix3d cov_inv = cov.inverse();
00057     for(uint32_t i=0;i<pc_in->size();i++) {
00058         extractHSL(pc_in->points[i].rgb, x(0), x(1), x(2));
00059         x_m = x - mean;
00060         x_m(0) *= hue_weight;
00061         double dist = std::sqrt(x_m.transpose() * cov_inv * x_m);
00062         if(dist <= std_devs) 
00063             pc_out->points.push_back(pc_in->points[i]);
00064     }
00065 }
00066 
00067 void sphereTrim(const PCRGB::Ptr& pc_in, PCRGB::Ptr& pc_out, uint32_t ind, double radius)
00068 {
00069     KDTree::Ptr kd_tree(new pcl::KdTreeFLANN<PRGB> ());
00070     kd_tree->setInputCloud(pc_in);
00071     vector<int> inds;
00072     vector<float> dists;
00073     kd_tree->radiusSearch(*pc_in, ind, radius, inds, dists);
00074     for(uint32_t j=0;j<inds.size();j++)
00075         COPY_PT_INTO_CLOUD(pc_in, pc_out, inds[j]);
00076 }
00077 
00078 namespace pcl {
00079 
00080 class ColorPointRepresentation : public PointRepresentation<PRGB> {
00081 public:
00082     ColorPointRepresentation(float h_mult = 0.0005, float s_mult = 0.0005, float l_mult = 0.0005) {
00083         nr_dimensions_ = 6;
00084         alpha_.resize(6);
00085         alpha_[0] = 1; alpha_[1] = 1; alpha_[2] = 1;
00086         alpha_[3] = h_mult; alpha_[4] = s_mult; alpha_[5] = l_mult;
00087     }
00088     virtual void copyToFloatArray(const PRGB& p, float* out) const {
00089         double h, s, l;
00090         extractHSL(p.rgb, h, s, l);
00091         out[0] = p.x; out[1] = p.y; out[2] = p.z;
00092         out[3] = h; out[4] = s; out[5] = l;
00093     }
00094     //bool isValid<PRGB>(const PRGB& p) const {
00095     //    if(p.x == p.x && p.y == p.y && p.z == p.z)
00096     //        return true;
00097     //    else
00098     //        return false;
00099     //}
00100 };
00101 }
00102 
00103 void computeICPRegistration(const PCRGB::Ptr& target_pc, const PCRGB::Ptr& source_pc,
00104                             Eigen::Affine3d& tf_mat, int max_iters, double color_weight) 
00105                             {
00106     double icp_trans_eps, icp_max_corresp;
00107     ros::param::param<double>("~icp_max_corresp", icp_max_corresp, 0.1);
00108     ros::param::param<double>("~icp_trans_eps", icp_trans_eps, 1e-6);
00109     pcl::IterativeClosestPoint<PRGB, PRGB> icp;
00110     PCRGB::Ptr aligned_pc(new PCRGB());
00111     boost::shared_ptr<pcl::PointRepresentation<PRGB> const> 
00112         pt_rep(new pcl::ColorPointRepresentation(color_weight, color_weight, color_weight));
00113     icp.setPointRepresentation(pt_rep);
00114     icp.setInputTarget(target_pc);
00115     icp.setInputCloud(source_pc);
00116     icp.setTransformationEpsilon(icp_trans_eps);
00117     icp.setMaxCorrespondenceDistance(icp_max_corresp);
00118     icp.setMaximumIterations(max_iters);
00119     icp.align(*aligned_pc);
00120     tf_mat = icp.getFinalTransformation().cast<double>();
00121     /*
00122     icp.setTransformationEpsilon(1e-4);
00123     icp.setMaxCorrespondenceDistance(0.5);
00124     Eigen::Matrix4f cur_tf = Eigen::Matrix4f::Identity(), last_tf;
00125     PCRGB::Ptr last_aligned_pc;
00126 
00127     for(int i=0;i<max_iters;i++) {
00128         last_aligned_pc = aligned_pc;
00129         icp.setInputCloud(last_aligned_pc);
00130         
00131         icp.setMaximumIterations(2);
00132         icp.align(*aligned_pc);
00133         cur_tf = icp.getFinalTransformation() * cur_tf;
00134         if (fabs ((icp.getLastIncrementalTransformation () - last_tf).sum ()) < 
00135                    icp.getTransformationEpsilon ())
00136             icp.setMaxCorrespondenceDistance (icp.getMaxCorrespondenceDistance () - 0.001);
00137         last_tf = icp.getLastIncrementalTransformation();
00138     }
00139     tf_mat = cur_tf.cast<double>();
00140     */
00141 
00142 #if 0
00143     vector<PCRGB::Ptr> pcs;
00144     vector<string> pc_topics;
00145     aligned_pc->header.frame_id = "/openni_rgb_optical_frame";
00146     source_pc->header.frame_id = "/openni_rgb_optical_frame";
00147     target_pc->header.frame_id = "/openni_rgb_optical_frame";
00148     pcs.push_back(aligned_pc);
00149     pcs.push_back(source_pc);
00150     pcs.push_back(target_pc);
00151     pc_topics.push_back("/aligned_pc");
00152     pc_topics.push_back("/source_pc");
00153     pc_topics.push_back("/target_pc");
00154     pubLoop(pcs, pc_topics, 5.0, 5);
00155 #endif
00156 }
00157 
00158 void extractFace(const PCRGB::Ptr& input_pc, PCRGB::Ptr& out_pc, int u_click, int v_click)
00159 {
00160     double trim_radius, skin_thresh;
00161     ros::param::param<double>("~trim_radius", trim_radius, 0.12);
00162     ros::param::param<double>("~skin_thresh", skin_thresh, 0.8);
00163 
00164     PCRGB::Ptr trimmed_pc(new PCRGB());
00165     int32_t closest_ind = findClosestPoint(input_pc, u_click, v_click);
00166     if(closest_ind < 0)
00167         return;
00168     sphereTrim(input_pc, trimmed_pc, closest_ind, trim_radius);
00169     extractSkinPC(trimmed_pc, out_pc, skin_thresh);
00170 }
00171 
00172 void extractFaceColorModel(const PCRGB::Ptr& input_pc, PCRGB::Ptr& out_pc, int u_click, int v_click)
00173 {
00174     double trim_radius, model_radius, color_std_thresh;
00175     ros::param::param<double>("~trim_radius", trim_radius, 0.12);
00176     ros::param::param<double>("~model_radius", model_radius, 0.02);
00177     ros::param::param<double>("~color_std_thresh", color_std_thresh, 1.5);
00178 
00179     int32_t closest_ind = findClosestPoint(input_pc, u_click, v_click);
00180     if(closest_ind < 0)
00181         return;
00182 
00183     PCRGB::Ptr model_pc(new PCRGB());
00184     sphereTrim(input_pc, model_pc, closest_ind, model_radius);
00185     Eigen::Vector3d mean_color;
00186     Eigen::Matrix3d cov_color;
00187     generateColorModel(model_pc, mean_color, cov_color);
00188 
00189     PCRGB::Ptr trimmed_pc(new PCRGB());
00190     sphereTrim(input_pc, trimmed_pc, closest_ind, trim_radius);
00191     extractPCFromColorModel(trimmed_pc, out_pc, mean_color, cov_color, color_std_thresh);
00192 }
00193 
00194 bool findFaceRegistration(const PCRGB::Ptr& template_pc, const PCRGB::Ptr& input_pc,
00195                           int u_click, int v_click, Eigen::Affine3d& tf_mat)
00196 {
00197     double color_weight;
00198     int max_iters;
00199     ros::param::param<double>("~color_weight", color_weight, 0.0);
00200     ros::param::param<int>("~max_iters", max_iters, 200);
00201     PCRGB::Ptr skin_pc(new PCRGB());
00202 
00203 #ifdef USE_COLOR_MODEL
00204     extractFaceColorModel(input_pc, skin_pc, u_click, v_click);
00205 #else
00206     extractFace(input_pc, skin_pc, u_click, v_click);
00207 #endif
00208     if(skin_pc->size() == 0)
00209         return false;
00210     computeICPRegistration(template_pc, skin_pc, tf_mat, max_iters, color_weight);
00211 
00212     return true;
00213 }
00214 
00215 int main(int argc, char **argv)
00216 {
00217     ros::init(argc, argv, "head_registration");
00218     ros::NodeHandle nh;
00219 
00220 #if 0
00221     PCRGB::Ptr input_pc, template_pc;
00222     readPCBag(argv[1], template_pc);
00223     readPCBag(argv[2], input_pc);
00224     int u, v;
00225     FILE* file = fopen(argv[3], "r");
00226     fscanf(file, "%d,%d\n", &u, &v);
00227     fclose(file);
00228 
00229     Eigen::Affine3d tf_mat;
00230     findFaceRegistration(template_pc, input_pc, u, v, tf_mat);
00231 
00232     PCRGB::Ptr tf_pc(new PCRGB());
00233     transformPC(*input_pc, *tf_pc, tf_mat);
00234     tf_pc->header.frame_id = "/base_link";
00235     pubLoop(tf_pc, "test", 5);
00236     return 0;
00237 #endif
00238 
00239 #if 1
00240     PCRGB::Ptr input_pc(new PCRGB()), face_extract_pc(new PCRGB());
00241     readPCBag(argv[1], input_pc);
00242     int u, v;
00243     FILE* file = fopen(argv[2], "r");
00244     fscanf(file, "%d,%d\n", &u, &v);
00245     fclose(file);
00246     Eigen::Affine3d tf_mat;
00247     extractFaceColorModel(input_pc, face_extract_pc, u, v);
00248     face_extract_pc->header.frame_id = "/base_link";
00249     pubLoop(face_extract_pc, "/test", 5);
00250 #endif
00251 
00252 }


hrl_head_registration
Author(s): Kelsey Hawkins
autogenerated on Wed Nov 27 2013 11:45:27