I want to segment stones on the ground and count the area of the stones like this :
I have written OpenCV for 2 years and find it's really hard to segment the stones only using OpenCV RGB picture, so I use kinect fusion to scan the ground and get a point cloud, in which the stones is higher than the ground.
I use the Point Cloud Library to segment the ground plane (in green color) like this:
Now I am trying to project the rest points onto the ground plane and get a 2D image in OpenCV Mat format(the height of the original point become the value of the projected point in the ground 2D image), which turn out to be a gray Mat picture. But this is very difficult for me, and could you give me some advice?
If I succeed to get my new gray Mat, then I can do segmentation on it , which is quite easy for me.
by the way, is there a point cloud viewer that I can see the (x,y,z) coordinate of the points?
This is my main code:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPLYFile ("MeshedReconstruction.ply", *cloud);
pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
pcl::PointIndices::Ptr inliers_groud (new pcl::PointIndices);
// Create the segmentation object
pcl::SACSegmentation<pcl::PointXYZ> seg;
// Optional
seg.setOptimizeCoefficients (true);
// Mandatory
seg.setModelType (pcl::SACMODEL_PLANE);
seg.setMethodType (pcl::SAC_RANSAC);
seg.setDistanceThreshold (0.01);//1cm
seg.setInputCloud (cloud);
seg.segment (*inliers_groud, *coefficients);
if (inliers_groud->indices.size () == 0)
{
PCL_ERROR ("Could not estimate a planar model for the given dataset.");
return (-1);
}
std::cerr << "Model coefficients: " << coefficients->values[0] << " "
<< coefficients->values[1] << " "
<< coefficients->values[2] << " "
<< coefficients->values[3] << std::endl;
std::cerr << "Model inliers_groud: " << inliers_groud->indices.size () << std::endl;
// Create the filtering object
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud (cloud);
extract.setIndices (inliers_groud);
extract.setNegative(false);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_groud (new pcl::PointCloud<pcl::PointXYZ>);
extract.filter (*cloud_groud);//get the ground plane
std::cerr << "Ground cloud after filtering: " << std::endl;
std::cerr << *cloud_groud << std::endl;
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ> ("samp11-utm_ground.pcd", *cloud_groud, false);
My Answer:
Look at this PCL api:http://docs.pointclouds.org/1.7.2/a02405.html#ga4375e99ec2ae368eec9379f506568611
I successfully solved this problem!
And the result is great(the purple plane is original ground, and the green plane is transformed ground plane which is the X-O-Y plane):
Now if a pcl::PointXYZ is (x0, y0, z0), then the point on Mat (x0,y0) is z0. The result: