00001
00063 #include <boost/program_options.hpp>
00064 #include <iostream>
00065
00066 #include <pcl/point_types.h>
00067 #include <pcl/io/pcd_io.h>
00068 #include <pcl/common/file_io.h>
00069
00070 #include <opencv2/ml/ml.hpp>
00071 #include <sensor_msgs/PointCloud2.h>
00072
00073 #include <cob_3d_mapping_common/label_defines.h>
00074
00075 using namespace std;
00076 using namespace pcl;
00077
00078 string file_plane;
00079 string file_edge;
00080 string file_corner;
00081 string file_sphere;
00082 string file_cylinder;
00083 string file_folder = "";
00084
00085 double svm_gamma;
00086 double svm_c;
00087 int svm_k;
00088
00089 int svm_samples;
00090
00091 void readOptions(int argc, char* argv[])
00092 {
00093 using namespace boost::program_options;
00094
00095 options_description cmd_line("Options");
00096 cmd_line.add_options()
00097 ("help", "produce help messsage")
00098 ("svm_gamma,g", value<double>(&svm_gamma)->default_value(1.0),
00099 "Training parameter gamma")
00100 ("svm_c,c", value<double>(&svm_c)->default_value(1.0),
00101 "Training parameter c")
00102 ("svm_k,k", value<int>(&svm_k)->default_value(0),
00103 "Set k_fold != 0 to use train_auto")
00104 ("folder,f", value<string>(&file_folder),
00105 "path to folder containing a pcd file for each class. "
00106 "If this is defined all seperatly defined files will be ignored.")
00107 ("svm_max_samples,s", value<int>(&svm_samples)->default_value(0),
00108 "maximal number of samples per class. (0 for all)")
00109 ;
00110 variables_map vm;
00111 store(command_line_parser(argc, argv).options(cmd_line).run(), vm);
00112 notify(vm);
00113
00114 if (vm.count("help"))
00115 {
00116 cout << "Reads files containing FPFH features and creates a SVM model" << endl;
00117 cout << "The following files from the defined folder containing the strings are used:" << endl;
00118 cout << "\t \"fpfh_plane.pcd\"" << endl;
00119 cout << "\t \"fpfh_edge.pcd\"" << endl;
00120 cout << "\t \"fpfh_cor.pcd\"" << endl;
00121 cout << "\t \"fpfh_sph.pcd\"" << endl;
00122 cout << "\t \"fpfh_cyl.pcd\"" << endl;
00123 cout << cmd_line << endl;
00124 exit(0);
00125 }
00126
00127 if (vm.count("folder"))
00128 {
00129 vector<string> files;
00130
00131 sensor_msgs::PointCloud2 c;
00132 getAllPcdFilesInDirectory(file_folder, files);
00133 for (unsigned int i = 0; i < files.size(); i++)
00134 {
00135 files[i] = file_folder + files[i];
00136
00137
00138
00139
00140 if(string::npos != files[i].rfind("fpfh_plane"))
00141 file_plane = files[i];
00142 else if (string::npos != files[i].rfind("fpfh_edge"))
00143 file_edge = files[i];
00144 else if (string::npos != files[i].rfind("fpfh_cor"))
00145 file_corner = files[i];
00146 else if (string::npos != files[i].rfind("fpfh_sph"))
00147 file_sphere = files[i];
00148 else if (string::npos != files[i].rfind("fpfh_cyl"))
00149 file_cylinder = files[i];
00150 }
00151 }
00152 }
00153
00154 int main(int argc, char** argv)
00155 {
00156 readOptions(argc, argv);
00157
00158 PointCloud<FPFHSignature33>::Ptr p_plane (new PointCloud<FPFHSignature33>);
00159 PointCloud<FPFHSignature33>::Ptr p_edge (new PointCloud<FPFHSignature33>);
00160 PointCloud<FPFHSignature33>::Ptr p_corner (new PointCloud<FPFHSignature33>);
00161 PointCloud<FPFHSignature33>::Ptr p_cylinder (new PointCloud<FPFHSignature33>);
00162 PointCloud<FPFHSignature33>::Ptr p_sphere (new PointCloud<FPFHSignature33>);
00163
00164 PCDReader reader;
00165 cout << "Read "<< file_plane << " for plane." << endl;
00166 reader.read(file_plane, *p_plane);
00167 cout << "Read "<< file_edge << " for edge." << endl;
00168 reader.read(file_edge, *p_edge);
00169 cout << "Read "<< file_corner << " for corner." << endl;
00170 reader.read(file_corner, *p_corner);
00171 cout << "Read "<< file_sphere << " for sph." << endl;
00172 reader.read(file_sphere, *p_sphere);
00173 cout << "Read "<< file_cylinder << " for cyl." << endl;
00174 reader.read(file_cylinder, *p_cylinder);
00175
00176 int plane_samples, edge_samples, corner_samples, sphere_samples, cylinder_samples, sample_count;
00177
00178 if (svm_samples == 0)
00179 {
00180 plane_samples = p_plane->height * p_plane->width;
00181 edge_samples = p_edge->height * p_edge->width;
00182 sphere_samples = p_sphere->height * p_sphere->width;
00183 cylinder_samples = p_cylinder->height * p_cylinder->width;
00184 corner_samples = p_corner->height * p_corner->width;
00185 }
00186 else
00187 {
00188 plane_samples = edge_samples = corner_samples = sphere_samples = cylinder_samples = svm_samples;
00189 }
00190 sample_count = plane_samples + edge_samples + corner_samples + sphere_samples + cylinder_samples;
00191 cout << "Found " << sample_count << " samples." << endl;
00192 cv::Mat train_data(sample_count, 33, CV_32FC1);
00193 cv::Mat train_data_classes(sample_count, 1, CV_32FC1);
00194
00195
00196 float* row;
00197 int i_end = 0;
00198 for (int i = 0; i < plane_samples; i ++)
00199 {
00200 train_data_classes.at<float>(i + i_end) = SVM_PLANE;
00201 row = train_data.ptr<float>(i + i_end);
00202 for(int j = 0; j < 33; j++)
00203 {
00204 row[j] = p_plane->points[i].histogram[j];
00205 }
00206 }
00207
00208
00209 i_end += plane_samples;
00210 for (int i = 0; i < edge_samples; i ++)
00211 {
00212 train_data_classes.at<float>(i + i_end) = SVM_EDGE;
00213 row = train_data.ptr<float>(i + i_end);
00214 for(int j = 0; j < 33; j++)
00215 {
00216 row[j] = p_edge->points[i].histogram[j];
00217 }
00218 }
00219
00220 i_end += edge_samples;
00221 for (int i = 0; i < corner_samples; i ++)
00222 {
00223 train_data_classes.at<float>(i + i_end) = SVM_COR;
00224 row = train_data.ptr<float>(i + i_end);
00225 for(int j = 0; j < 33; j++)
00226 {
00227 row[j] = p_corner->points[i].histogram[j];
00228 }
00229 }
00230
00231
00232 i_end += corner_samples;
00233 for (int i = 0; i < sphere_samples; i ++)
00234 {
00235 train_data_classes.at<float>(i + i_end) = SVM_SPH;
00236 row = train_data.ptr<float>(i + i_end);
00237 for(int j = 0; j < 33; j++)
00238 {
00239 row[j] = p_sphere->points[i].histogram[j];
00240 }
00241 }
00242
00243
00244 i_end += sphere_samples;
00245 for (int i = 0; i < cylinder_samples; i ++)
00246 {
00247 train_data_classes.at<float>(i + i_end) = SVM_CYL;
00248 row = train_data.ptr<float>(i + i_end);
00249 for(int j = 0; j < 33; j++)
00250 {
00251 row[j] = p_cylinder->points[i].histogram[j];
00252 }
00253 }
00254
00255 cout << "Begin training..." << endl;
00256 CvSVM svm;
00257 CvSVMParams params;
00258 params.svm_type = CvSVM::C_SVC;
00259 params.kernel_type = CvSVM::RBF;
00260 params.nu = 0.5;
00261 params.C = svm_c;
00262 params.gamma = svm_gamma;
00263
00264 params.term_crit.type = CV_TERMCRIT_ITER | CV_TERMCRIT_EPS;
00265 params.term_crit.max_iter = 1000;
00266 params.term_crit.epsilon = 0.00001;
00267 cout << "Starting training process with " << sample_count << " samples." << endl;
00268 if(svm_k == 0)
00269 svm.train(train_data, train_data_classes, cv::Mat(), cv::Mat(), params);
00270 else
00271 svm.train_auto(train_data, train_data_classes, cv::Mat(), cv::Mat(), params, svm_k);
00272 string file_xml = file_folder + "SVM_fpfh_rng_g_c.xml";
00273 svm.save(file_xml.c_str());
00274
00275 cout << "Training process completed." << endl;
00276 }