How to get a specific cluster after region growing using pcl library? - point-cloud-library

I am trying to segment the input point cloud using surface normal based region growing, following the tutorial here:http://pointclouds.org/documentation/tutorials/region_growing_segmentation.php.
I have been able to achieve satisfactory results for my use case and I could also visualize the segments using pcl::PointCloud ::Ptr colored_cloud = reg.getColoredCloud ();
However, I am not able to find a way to extract a particular cluster that contains all points with normals oriented in a particular direction, for example, the cluster which has all the points with point normals along the z-axis. I assume that such an access to the cluster should be possible, please correct me if I am wrong. Also, any alternative methods to get the feature/s of the individual cluster would be very helpful. Thanks in advance.

Take a look at these lines (from the tutorial you mention):
std::vector <pcl::PointIndices> clusters;
reg.extract (clusters);
Each "cluster" is repressented by pcl::PointIndices, which is just a wrapper for a vector<int> of indices in the input cloud.
Here is a simple example for calculating the mean normal for each cluster:
std::vector<Eigen::Vector3f> mean_normals(clusters.size(), Eigen::Vector3f({ 0.,0.,0. }));
for (auto cluster_idx = 0; cluster_idx < clusters.size(); cluster_idx++)
{
for (auto point_idx: clusters[cluster_idx].indices)
{
mean_normals[cluster_idx] += normals->points[point_idx].getNormalVector3fMap();
}
mean_normals[cluster_idx].normalize();
}
You may also use pcl::PointIndices to create a new cloud for each cluster using pcl::ExtractIndices, as in this tutorial. Short example:
pcl::PointCloud<pcl::PointXYZ>::Ptr cluster_cloud(new pcl::PointCloud<pcl::PointXYZ>)
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud (cloud);
extract.setIndices (clusters[cluster_idx]);
extract.filter (*cluster_cloud);

You gotta convert cluster which is pcl::PointIndices to pcl::PointIndicesConstPtr to feed it into extract.setIndices(). Here is an example:
pcl::PointCloud<pcl::PointXYZRGB>::Ptr desired_object_cloud (new pcl::PointCloud<pcl::PointXYZRGB> ());
pcl::ExtractIndices<pcl::PointXYZRGB> extract;
extract.setInputCloud (cloud);
pcl::PointIndices::Ptr cluster_ptr(new pcl::PointIndices(clusters[cluster_idx]));
extract.setIndices (cluster_ptr);
extract.setNegative (false);
extract.filter(*desired_object_cloud);

Related

Usage of pcl::CropHull

Hello I am looking for a way to find out points/indices of point cloud which lie within a set of pre-defined polygon points/indices.
My Input would be either of the following.
Set of indices of the cloud forming a 2D polygon. Eg : 21480, 4491, 20399, 19034, 21322, 5240, 5870, 21480
Set of coordinates(x,y,z) which correspond to the above indices in the cloud.
enter image description here
May I politelly suggest you the documentation pcl::CropHull
In your case. the methods:
setHullCloud (PointCloudPtr points)
setCropOutside (bool crop_outside)
and then
filter (PointCloud &output)
should do the job.
If this did not answer your problem please be more specific to which problems you are exactly facing when using pcl::CropHull (with code if possible)

PDAL diff execution

I have two point clouds one is of an area before development, one is after.
I want to isolate the land surface points (A) now under the new buildings and I want to isolate the new buildings (B).
So I see PDAL has a diff function, would this enable me to export A and B as described above?
I would also like to add a +/- of 10cm to the selection, is this possible.
This is not the intent of pdal diff. According to https://www.pdal.io/apps/diff.html:
The command checks for the equivalence of the following items:
Different schema
Expected count
Metadata
Actual point count
Byte-by-byte point data
A separate PDAL kernel would be required for what you are looking to do.

How to implement KdTree using PCLPointCloud2 used in loadOBJfile in point cloud library?

Okay, so I have one OBJ file which I read into PCLpointcloud2. Now I want to feed it into a K-dTree. Which is not taking PCLPointCloud2 as input. I want to query any general point if it lies on the surface of my OBJ file.
I am finding it hard to understand their documentation. So how can it be done?
Plus, kindly point me to a good reference easily interpretable. And what is "PointT" BTW? Is it custom build type defined by us? please elaborate.
Look at the code in the provided tool pcl_mesh_sampling (in the PCL code directory under tools/mesh_sampling.cpp). It is relatively simple. It loads a model from PLY or OBJ then for each triangle it samples random points from the triangle. The final point cloud then undergoes a voxel-grid sample to make the points relatively uniform. Alternatively, you can just run the pcl_mesh_sampling program on your obj file to get an output PCD which you can then visualise with pcl_viewer before loading the PCD file into your own code.
Once you have the final point cloud, you can build and use a KD-Tree as per http://pointclouds.org/documentation/tutorials/kdtree_search.php
PointT is the template argument. The point cloud library can handle a variety of point types, from simple PointXYZ (having just x,y,z) to more complicated points like PointXYZRGBNormal (having x,y,z,normal_x,normal_y,normal_z, curvature, r, g, and b channels). Each algorithm is templated on the point type that you want to use. It would probably be easier if you used PointXYZ with your OBJ file, so use pcl::PointXYZ for all your template arguments. For more on templates see http://www.tutorialspoint.com/cplusplus/cpp_templates.htm and http://pointclouds.org/documentation/tutorials/adding_custom_ptype.php.
Update (reply to latest comment)
Added here because this reply is too long for a comment.
I think I see what you are getting at. So when you sample points from the point cloud & build a KD-tree of the object surface, and for each point you keep track which faces are nearby that point (probably all the faces adjacent to the face from which the point was sampled should be sufficient? Just one face is definitely insufficient). Then when the query point is given, you find the nearest point in the KD-tree and check whether the query point is on the "outside" or inside of the full list of nearby faces associated with that point in the KD-tree. If it's on the "inside" of all of them perhaps it is an interior point. But I cannot guarantee that this is true. That is my thinking on that question at the moment. But I do wonder if you want a mesh-based approach really. By the way, if you break your mesh up into convex parts then you can have nice guarantees when processing each convex part.

Constrained (Delaunay) Triangulation

For a university project I need to implement a computer graphics paper that has been relased a couple of years ago. At one point, I need to triangulate the results I get from my simulation. I guess its easier to explain what I need looking at a picture contained within the paper:
Let's say I already have got all the information it takes to reconstruct the contour lines that you can see in the second thumbnail. Using those I need to do some triangulation using those siluettes as constrains. I have searched the internet for triangulation libraries like CGAL, VTK, Triangle, Triangle++, ... but I always ended up throwing my hands up in horror. I am not a good programmer and it seems impossible to me to get into one of those APIs before the deadline of this project passes.
I would appreciate any kind of help like code snipplets, tips, etc...
I know that the algorithms need segments (pairs of points) as input, so let's say I have got one std::vector containing all pairs of points defining the siluette as well as the left and right side of the rectangle.
Can you somehow give me a code snipplet for i.e. CGAL that I could use for my purpose? First of all I just want to achieve the state of the third thumbnail. Lateron I will have to do some displacement within the "cracks" and finally write the information into a VBO for OpenGL rendering.
I have started working it out with CGAL. One simple problem still drives me crazy:
It is possible to attach informations (like ints) to points before adding them up to the triangulator object. I do this since I need on the one hand an int-flag that I use lateron to define my texture coordinates and on the other hand an index which I use so that I can create a indexed VBO.
http://doc.cgal.org/latest/Triangulation_2/Triangulation_2_2info_insert_with_pair_iterator_2_8cpp-example.html
But instead of points I only want to insert constraint-edges. If I insert both CGAL returns strange results since points have been fed into two times (once as point and once as point of a constrained edge).
http://doc.cgal.org/latest/Triangulation_2/Triangulation_2_2constrained_8cpp-example.html
Is it possible to connect in the same way as with points information to "Constraints" so that I can only use this function cdt.insert_constraint( Point(j,0), Point(j,6)); before I iterate over the resulting faces?
Lateron when I loop over the triangles I need some way to access the int-flags that I defined before. Like this but not on acutal points but the "ends" defined by the constraint edges:
for(CDT::Finite_faces_iterator fit = m_cdt.finite_faces_begin(); fit != m_cdt.finite_faces_end(); ++fit, ++k) {
int j = k*3;
for(int i=0; i < 3; i++) {
indices[j+i] = fit->vertex(i)->info().first;
}
}

Dynamic closest elements

I have a 2D surface ( Grid ) with 50 elements at different locations.
I need to decide which are the 10 closest elements to a given point.
In addition, the given point is constantly moving and i need to do the calculation on each movement.
I know I can calculate the Euclidean distance to each point on each movement, but I want a faster way.
Thanks.
It sounds like you're trying to come up with a way where you can take the 10 closest points at time t and use those to help you figure out the 10 closest at time t+1. Here's an idea to consider.
When you calculate the 10 closest points, also store the angular direction of where they are relative to your current location. Then, when you move you can calculate the direction in which you moved. Focus your search on the space that's opened up to you (think of a circle around point A and another around point B. The space in B but not in A is where you want to focus your search).
Of course, to do this you need to have some way of searching in a particular area of the grid instead of doing a linear search through an array of points to find those close to you. I'd recommend looking into BSP trees for that. If you're not doing it already, using BSP trees instead of linear search might alone be the performance boost you're looking for.
So, I am going to put all the attempts that I went over to figure out my implementation and hopefully you will be able to figure out the best approach for you project.
I am working on somewhat similar project to what you have mentioned. But in my case I need to do extra cycles once I found the points within a given distance threshold. I have tried few iterations, first I started by creating a distance grid. Keep in mind, I am not working on 2D surface but I don't think changing this to 2D will take much work.
Here is how I developed my distance grid (its so simple even a cave man can do it, I making fun of myself) , Also keep in mind I didn't continue using the grid to finish up my implementation.
public double[][] distanceGrid() {
double[] gridSize = combineArrays(generateClusters(1, 3), generateClusters(12, 15));
double [][] pointsDistanceGrid = new double[gridSize.length][gridSize.length];
for (int i = 0; i < pointsDistanceGrid.length; i++) {
for (int j = 0; j < pointsDistanceGrid[i].length; j++) {
pointsDistanceGrid[i][j] = Math.abs(gridSize[i] - gridSize[j] );
System.out.print(" " + pointsDistanceGrid[i][j]);
}
System.out.println("");
}
return pointsDistanceGrid;
}
As I mentioned I didn't use it.
Since I had to deal with a distance threshold, and I decided before finding "The Nearest" i wanted to see all the points that are closer to the particular point that I am looking at, so I implemented this method.
/**
* Given a point method returns an array with point that are within the limit of threshold.
* #param point
* #return
*/
public double[] pointsWithinThreshold(double point) {
double[] neighbors = new double[bigCluster.length];
for (int i = 0; i < bigCluster.length; i++) {
if (bigCluster[i] != point) {
double distance = 0;
distance = Math.abs(point - bigCluster[i]);
if (distance <= getDistanceThreshold()) {
neighbors[i] = bigCluster[i];
}
}
}
return neighbors;
}
After this I realize I don't really care what are all the closest points so I end up not using this and refractor some of this functionalities to a method where I get the closest member and do recursive DFS.
Let me know if you would like to see that, I didn't put it here coz I thought you only need to know the closest 10 member.
Hope this helps and good luck.

Resources