vedo icon indicating copy to clipboard operation
vedo copied to clipboard

Subsample point cloud based on the density of another point cloud

Open ttsesm opened this issue 3 years ago • 6 comments

Hi @marcomusy,

I am trying to subsample a point cloud based on the density of another point cloud. For example I have the following two point clouds of different sizes, i.e. with green and red color:

image

Now I want to do two operations to subsample a point cloud based on 1. a given fixed number of points or 2. based on how the density or the specified fraction of the object size of another point cloud is. The idea is to subsample the smaller point cloud to a given number of points and then the bigger point cloud to a number of points based on the density of the smaller point cloud after the subsampling. So that they have similar density and not one point cloud to be dense and the other sparse and to keep let's say a similar kind of fraction distance between the points of the two point clouds. For example the output in the image bellow:

image

vd.show(pcds[0].clone().subsample(0.05), pcds[1].clone().subsample(0.05), axes=1, interactive=True).close()

is not ideal since the smaller part is more dense than the larger part.

I was checking on the subsample() and density() operations. The subsample() method needs a fraction number so you cannot pass a fixed number of points and the density() function I am not sure whether it is relevant to be used for extracting such a number.

ttsesm avatar Sep 28 '22 09:09 ttsesm

Hi, sorry for the late reply, have you tried to use .subsample(0.01, absolute=True) ? You cannot control a priory the exact number of output points though.

marcomusy avatar Oct 01 '22 16:10 marcomusy

No worries. Yes setting absolute=True doesn't really help much. How I can get the density of a point cloud?

You cannot control a priory the exact number of output points though.

Wouldn't this be quite useful to have, for example I see the equivalent function in Trimesh gives this option subsampling both for more or less point depending whether they need to be added or removed from the final mesh/point cloud

ttsesm avatar Oct 04 '22 10:10 ttsesm

Just pushed a version with a fix for absolute=True:

from vedo import *

tmsh = TetMesh(dataurl+"limb_ugrid.vtk")
pts1  = Points(tmsh)
print(pts1.N())

pts2 = pts1.clone().densify()  # artificially increase density

pts1.subsample(100, absolute=True)
pts2.subsample(100, absolute=True).c("r4")
print(pts1.N(), pts2.N())

show(pts1, pts2, N=2, axes=1)

Screenshot from 2022-10-04 18-07-10 the 2 clouds should have the same density. The density of a point cloud is not a well defined problem.. e.g. you can define it by the convex hull volume, which might not be ideal for non convex distributions..

I will look into the trimesh function!

marcomusy avatar Oct 04 '22 16:10 marcomusy

Yes the absolute=True parameter is fixed now.

I agree regarding measuring density/sparsity that it is a bit ambiguous how to measure it. I am also trying to figure out the best way.

ttsesm avatar Oct 05 '22 09:10 ttsesm

Following your idea with the convex hull volume, I have the following function:

def getDensity(vertices):
    hull = vd.ConvexHull(vertices)

    return vertices.shape[0] / hull.volume()

This gives me the following output: image

How to translate this to the fraction number that the vd.subsample() accepts? If I could give a number of points it would be a direct inversion which I guess I can do it by changing my data from vedo to trimesh where I can use the corresponding function and then port back to vedo.

Also I found this definition of "density" and some corresponding matlab code that could be ported. However, these are giving you a density value per point if I understood correctly and not as an overall point cloud. Probably you are doing something similar in the vedo.density() function.

ttsesm avatar Oct 06 '22 16:10 ttsesm

well it very much depends if you consider "closed" clouds (clouds which may define a surface) or "dense" clouds where points are scattered in the full 3d space... the the concept of "volume" means different things. I don't see any objective way to define it, or translate it to the subsample() method, you need to do it based on the problem at hand.

marcomusy avatar Oct 06 '22 22:10 marcomusy