Go to the documentation of this file.00001 #include <ros/ros.h>
00002
00003 #include <pcl16/point_cloud.h>
00004 #include <pcl16/point_types.h>
00005 #include <pcl16/common/pca.h>
00006
00007 #include <opencv2/core/core.hpp>
00008 #include <opencv2/imgproc/imgproc.hpp>
00009 #include <opencv2/highgui/highgui.hpp>
00010 typedef pcl16::PointCloud<pcl16::PointXYZ> XYZPointCloud;
00011
00012 cv::RotatedRect fit2DMassEllipse(XYZPointCloud& obj_cloud)
00013 {
00014 pcl16::PCA<pcl16::PointXYZ> pca;
00015 XYZPointCloud cloud_no_z;
00016 cloud_no_z.header = obj_cloud.header;
00017 cloud_no_z.width = obj_cloud.size();
00018 cloud_no_z.height = 1;
00019 cloud_no_z.is_dense = false;
00020 cloud_no_z.resize(obj_cloud.size());
00021 if (obj_cloud.size() < 3)
00022 {
00023 ROS_WARN_STREAM("Too few points to find ellipse");
00024 cv::RotatedRect obj_ellipse;
00025 obj_ellipse.center.x = 0.0;
00026 obj_ellipse.center.y = 0.0;
00027 obj_ellipse.angle = 0;
00028 obj_ellipse.size.width = 0;
00029 obj_ellipse.size.height = 0;
00030 return obj_ellipse;
00031 }
00032 for (unsigned int i = 0; i < obj_cloud.size(); ++i)
00033 {
00034 cloud_no_z[i] = obj_cloud[i];
00035 cloud_no_z[i].z = 0.0f;
00036 }
00037
00038 pca.setInputCloud(cloud_no_z.makeShared());
00039 Eigen::Vector3f eigen_values;
00040 Eigen::Matrix3f eigen_vectors;
00041 Eigen::Vector4f centroid;
00042 try{
00043 ROS_INFO_STREAM("Getting mean");
00044 centroid = pca.getMean();
00045 ROS_INFO_STREAM("Getting eiven values");
00046 eigen_values = pca.getEigenValues();
00047 ROS_INFO_STREAM("Getting eiven vectors");
00048 eigen_vectors = pca.getEigenVectors();
00049 } catch(pcl16::InitFailedException ife)
00050 {
00051 ROS_WARN_STREAM("Failed to compute PCA");
00052 ROS_WARN_STREAM("ife: " << ife.what());
00053 }
00054
00055 cv::RotatedRect obj_ellipse;
00056 obj_ellipse.center.x = centroid[0];
00057 obj_ellipse.center.y = centroid[1];
00058 obj_ellipse.angle = RAD2DEG(atan2(eigen_vectors(1,0), eigen_vectors(0,0))-0.5*M_PI);
00059
00060 obj_ellipse.size.height = std::max(eigen_values(0)*0.1, 0.07);
00061 obj_ellipse.size.width = std::max(eigen_values(1)*0.1, 0.03);
00062 ROS_INFO_STREAM("Center: (" << obj_ellipse.center.x << ", " << obj_ellipse.center.y << ")");
00063 ROS_INFO_STREAM("angle: " << obj_ellipse.angle);
00064 ROS_INFO_STREAM("size: (" << obj_ellipse.size.height << ", " << obj_ellipse.size.width << ")");
00065 return obj_ellipse;
00066 }
00067
00068 int main()
00069 {
00070 XYZPointCloud input_cloud;
00071 input_cloud.width = 2000;
00072 input_cloud.height = 1;
00073 input_cloud.is_dense = false;
00074 input_cloud.resize(input_cloud.width*input_cloud.height);
00075 for (int i = 0; i < input_cloud.points.size(); ++i)
00076 {
00077 input_cloud[i].x = 2.0 * rand() / (RAND_MAX) - 1.0;
00078 input_cloud[i].y = 2.0 * rand() / (RAND_MAX) - 1.0;
00079 input_cloud[i].z = 1.0 * rand() / (RAND_MAX);
00080 }
00081
00082 cv::RotatedRect ellipse = fit2DMassEllipse(input_cloud);
00083 return 0;
00084 }