Go to the documentation of this file.00001
00060 #include <pcl/point_types.h>
00061 #include <pcl/io/pcd_io.h>
00062 #include <pcl/features/integral_image_normal.h>
00063 #include <pcl/features/normal_3d_omp.h>
00064 #include <pcl/segmentation/sac_segmentation.h>
00065 #include <pcl/ModelCoefficients.h>
00066 #include <pcl/sample_consensus/method_types.h>
00067 #include <pcl/sample_consensus/model_types.h>
00068
00069 #include "cob_3d_mapping_common/stop_watch.h"
00070 #include "cob_3d_mapping_common/point_types.h"
00071
00072 #include "cob_3d_features/organized_normal_estimation_omp.h"
00073 #include "cob_3d_features/organized_normal_estimation.h"
00074
00075 using namespace pcl;
00076
00077 void
00078 determinePlaneNormal (PointCloud<PointXYZ>::Ptr& p, Eigen::Vector3f& normal)
00079 {
00080 SACSegmentation<PointXYZ> seg;
00081 seg.setOptimizeCoefficients (true);
00082 seg.setModelType (SACMODEL_PLANE);
00083 seg.setMethodType (SAC_RANSAC);
00084 seg.setMaxIterations (50);
00085 seg.setDistanceThreshold (0.01);
00086 seg.setInputCloud (p);
00087 ModelCoefficients coefficients_plane;
00088 pcl::PointIndices inliers_plane;
00089 seg.segment (inliers_plane, coefficients_plane);
00090 normal (0) = coefficients_plane.values[0];
00091 normal (1) = coefficients_plane.values[1];
00092 normal (2) = coefficients_plane.values[2];
00093 }
00094
00095 int
00096 main (int argc, char** argv)
00097 {
00098 if (argc < 2)
00099 {
00100 std::cerr << "Error: Please specify a PCD file (rosrun cob_3d_features profile_ne test.pcd)." << std::endl;
00101 return -1;
00102 }
00103 PointCloud<PointXYZ>::Ptr p (new PointCloud<PointXYZ>);
00104 PointCloud<Normal>::Ptr n (new PointCloud<Normal>);
00105 PointCloud<InterestPoint>::Ptr ip (new PointCloud<InterestPoint>);
00106 pcl::PointCloud<pcl::PointNormal> p_n;
00107 PrecisionStopWatch t;
00108 std::string file_ = argv[1];
00109 PCDReader r;
00110 if (r.read (file_, *p) == -1)
00111 return -1;
00112
00113 Eigen::Vector3f normal;
00114 determinePlaneNormal (p, normal);
00115
00116
00117 cob_3d_features::OrganizedNormalEstimation<PointXYZ, Normal, PointLabel> ne;
00118 ne.setPixelSearchRadius (8, 2, 2);
00119
00120 ne.setInputCloud (p);
00121 PointCloud<PointLabel>::Ptr labels (new PointCloud<PointLabel>);
00122 ne.setOutputLabels (labels);
00123 t.precisionStart ();
00124 ne.compute (*n);
00125 std::cout << t.precisionStop () << "s\t for organized normal estimation" << std::endl;
00126
00127 cob_3d_features::OrganizedNormalEstimationOMP<PointXYZ, Normal, PointLabel> ne_omp;
00128 ne_omp.setPixelSearchRadius (8, 2, 2);
00129
00130 ne_omp.setInputCloud (p);
00131
00132 ne_omp.setOutputLabels (labels);
00133 t.precisionStart ();
00134 ne_omp.compute (*n);
00135 std::cout << t.precisionStop () << "s\t for organized normal estimation (OMP)" << std::endl;
00136 concatenateFields (*p, *n, p_n);
00137 io::savePCDFileASCII ("normals_organized.pcd", p_n);
00138
00139 double good_thr = 0.97;
00140 unsigned int ctr = 0, nan_ctr = 0;
00141 double d_sum = 0;
00142 for (unsigned int i = 0; i < p->size (); i++)
00143 {
00144 if (pcl_isnan(n->points[i].normal[0]))
00145 {
00146 nan_ctr++;
00147 continue;
00148 }
00149 double d = normal.dot (n->points[i].getNormalVector3fMap ());
00150 d_sum += fabs (1 - fabs (d));
00151 if (fabs (d) > good_thr)
00152 ctr++;
00153 }
00154 std::cout << "Average error: " << d_sum / p->size () << std::endl;
00155 std::cout << "Ratio of good normals: " << (double)ctr / p->size () << std::endl;
00156 std::cout << "Invalid normals: " << nan_ctr << std::endl;
00157
00158 IntegralImageNormalEstimation<PointXYZ, Normal> ne2;
00159 ne2.setNormalEstimationMethod (ne2.COVARIANCE_MATRIX);
00160 ne2.setMaxDepthChangeFactor (0.02f);
00161 ne2.setNormalSmoothingSize (10.0f);
00162 ne2.setDepthDependentSmoothing (true);
00163 ne2.setInputCloud (p);
00164 t.precisionStart ();
00165 ne2.compute (*n);
00166 std::cout << t.precisionStop () << "s\t for integral image normal estimation" << std::endl;
00167 concatenateFields (*p, *n, p_n);
00168 io::savePCDFileASCII ("normals_integral.pcd", p_n);
00169
00170 ctr = 0;
00171 nan_ctr = 0;
00172 d_sum = 0;
00173 for (unsigned int i = 0; i < p->size (); i++)
00174 {
00175 if (pcl_isnan(n->points[i].normal[0]))
00176 {
00177 nan_ctr++;
00178 continue;
00179 }
00180 double d = normal.dot (n->points[i].getNormalVector3fMap ());
00181 d_sum += fabs (1 - fabs (d));
00182 if (fabs (d) > good_thr)
00183 ctr++;
00184 }
00185 std::cout << "Average error: " << d_sum / p->size () << std::endl;
00186 std::cout << "Ratio of good normals: " << (double)ctr / p->size () << std::endl;
00187 std::cout << "Invalid normals: " << nan_ctr << std::endl;
00188
00189 NormalEstimationOMP<PointXYZ, Normal> ne3;
00190 ne3.setInputCloud (p);
00191 ne3.setNumberOfThreads (4);
00192 ne3.setKSearch (256);
00193
00194 t.precisionStart ();
00195 ne3.compute (*n);
00196 std::cout << t.precisionStop () << "s\t for vanilla normal estimation" << std::endl;
00197 concatenateFields (*p, *n, p_n);
00198 io::savePCDFileASCII ("normals_vanilla.pcd", p_n);
00199
00200 ctr = 0;
00201 nan_ctr = 0;
00202 d_sum = 0;
00203 for (unsigned int i = 0; i < p->size (); i++)
00204 {
00205 if (pcl_isnan(n->points[i].normal[0]))
00206 {
00207 nan_ctr++;
00208 continue;
00209 }
00210 double d = normal.dot (n->points[i].getNormalVector3fMap ());
00211 d_sum += fabs (1 - fabs (d));
00212 if (fabs (d) > good_thr)
00213 ctr++;
00214 }
00215 std::cout << "Average error: " << d_sum / p->size () << std::endl;
00216 std::cout << "Ratio of good normals: " << (double)ctr / p->size () << std::endl;
00217 std::cout << "Invalid normals: " << nan_ctr << std::endl;
00218
00219 return 0;
00220 }