I have a 4-dimensional ellipsoid from which I want to draw samples uniformly. I thought of an approach using a hyper cube around the ellipsoid. We can draw a sample from it and check if it is in the ellipsoid. But the volume ratio of hypercube and ellipsoid in 4 dimensions is 0.3. That means I have only 30 percent success rate. As my algorithm has speed issues I don't want to use this approach. I have also been looking at Inverse transform sampling. Can you give me an insight on how to do this with a 4-dimensional ellipsoid ?
You can transform your hyper ellipsoid to a sphere.
So the given algorithm is valid for the sphere but can easily transformed to your ellipsoid.
Draw from a gaussian distribution N(0,1) for all coordinates x1, to x4. x=[x1,x2,x3,x4].
Normalize the vector x. ==> You have obtained uniformly distributed vectors on the surface.
Now, draw a radius u from [0,1] for the inner point from unit sphere
p=u**(1/4)*x is the uniformly distributed vector within the 4 dimensional unit sphere.
Related
I have a 2x2 matrix of distances from a depth sensor.
The matrix is cropped so only the points we are interested in is in the frame(All the points in the cropped image contains the object).
My question is how can we determine if this object is flat or not?
The depth image is acquired from Realsense d435. I read the depth image and then multiply it by depth_scale.
The object is recognized using AI for the rgb image that is aligned with the depth image.
And I have 4 points on the object. So, all the distances in that rectangle contains the distance of the object from the sensor.
My first idea was standard deviation of all the points. But then this falls apart if the image is taken from an angle. (since the standard deviation won't be 0)
From an angle the distance of a flat object is changing uniformly on the y axis. Maybe somehow, we can use this information?
The 2x2 matrix is a numpy array in python. Maybe there are some libraries which do this already.
After reprojecting your four depth measurements to the 3D space, it becomes a problem of deciding if your set of points is coplanar. There are several ways you can go about it.
One way to do it is to reproject the points to 3D and fit a plane to all four of them there. Since you're fitting a plane to four points in three dimensions, you get an over-determined system, and it's very unlikely that all points would lie exactly on the estimated plane. At this stage, you could prescribe some tolerance to determine "goodness of fit". For instance, you could look at the R^2 coefficient.
To fit the plane you can use scipy.linalg.lstsq. Here's a good description of how it can be done: Fit plane to a set of points in 3D.
Another way to approach the problem is by calculating the volume of a tetrahedron spanned by the four points in 3D. If they are coplanar (or close to coplanar), the volume of such a tatrahedron should be equal to (or close to) 0. Assuming your pointa reprojected to 3D can be described by (x_0, y_0, z_0), ..., (x_3, y_3, z_3), the volume of the tetrahedron is equal to:
volume = abs(numpy.linalg.det(tetrahedron)) / 6, where
tetrahedron = np.array([[x_0, y_0, z_0, 1], [x_1, y_1, z_1, 1], [x_2, y_2, z_2, 1], [x_3, y_3, z_3, 1]])
To check if your points are on the same plane, (equivalently - if the tetrahedron has a small enough volume), it is now sufficient to check if
volume < TOL
for some defined small tolerance value, which must be determined experimentally.
You can define a surface by choosing three of the four 3D points.
Evaluate the distance from the remaining point to the surface.
How to choose the three points is... it may be good to choose the pattern that maximizes the area of the triangle.
Through a sensor I get the rotation between points in coordinate system A to points in coordinate system B. The measured rotations between the coordinate systems are not 100% identical due to the noise of the sensor.
How can I determine the average or optimal rotation matrix between the coordinate systems? Similar to this problem: stackoverflow: Averaging Quatenion, but contrary to that I do not want to use Quaternions, but try some least square approach.
Given: Rba(n): Rotation matrix from a to b, measured at n different time points
Wanted: Rba optimal
My approach: Minimization of the squared distance.
First I define n random points in space and apply the rotations to these points.
And now I can calculate the rotation by means of the Krabsch algorithm using singular value decomposition to minimize the square distance between the input points and the transformed points.
However, what I don't understand is that the calculated rotation matrix seems to be dependent on the input points. That is, I get different rotation matrices as a result for different input points, although the applied rotation matrices Rba(n) remain the same.
Why is that? And what is the right way?
I have a 3D scatter plot of some data generated using matploblib Axes 3D. I need to decide if it lies on a plane or a curve. I am trying to understand the visual differences that would indicate plane or curve. My guess is that if there are points along a wide range of z values then it lies on a curve because if it lied a plane, this would mean that the points are spread only over a flat surface. Even if my guess is correct, I am only right by virtue of eliminating the only other possibility so how would I tell specifically if it the data lies on a curve?
If the plane is tilted you will also find a wide range of z values.
Assuming you have your 3D points in an nx3 array, you can calculate the plane that fits them using this:
centroid = np.mean(points, axis=0)
_, eigenvalues, eigenvectors = np.linalg.svd(points - centroid, full_matrices=False)
normal = eigenvectors[2]
dispersion = eigenvalues[2]
The plane that best approximates the scattered points is defined by a point (centroid) and its normal vector.
Then, according to the dispersion value along the normal axis you can decide whether it is low enough (the points lie on a plane) or it is too high (they don't lie on a plane).
I have a number of points in 3d space (cartesian x,y,z) and would like to fit a ellipsoid
to that in order to determine the axis ratios. The issue here is that I have a distribution of points (not points on a surface), and the solutions to this problem mainly consider the points on a surface. Also would this fit be iterative (like some optimize or mcmc type method), I work in Python.
The code i am using was given in this answer: Python: fit 3D ellipsoid (oblate/prolate) to 3D points
But this does not work for me ( I think it was meant for points on the surface of an ellipsoid). But I have more density distribution of points rather than surface points.
I assume that you are not after the tightest bounding ellipsoid nor some best fit ellipsoid based on the "outer" points (such as an ellipsoid fit on the convex hull).
I understand that you are after a distribution, i.e. a unit-sum positive function of the coordinates, which you want to have "ellipsoidal" symmetry, so that the loci of equiprobable points are ellipsoids.
If you assume your distribution to be multivariate normal,
P(p) = c.exp(-(p-µ)^T M (p-µ)/2)
then M is the inverse of the covariance matrix and µ the average vector.
I've looked around and all solutions for generating uniform random points in/on the unit ball are designed for 2 or 3 dimensions.
What is a (tractable) way to generate uniform random points inside a ball in arbitrary dimension? Particularly, not just on the surface of the ball.
To preface, generating random points in the cube and throwing out the points with norm greater than 1 is not feasible in high dimension. The ratio of the volume of a unit ball to the volume of a unit cube in high dimension goes to 0. Even in 10 dimensions only about 0.25% of random points in the unit cube are also inside the unit ball.
The best way to generate uniformly distributed random points in a d-dimension ball appears to be by thinking of polar coordinates (directions instead of locations). Code is provided below.
Pick a random point on the unit ball with uniform distribution.
Pick a random radius where the likelihood of a radius corresponds to the surface area of a ball with that radius in d dimensions.
This selection process will (1) make all directions equally likely, and (2) make all points on the surface of balls within the unit ball equally likely. This will generate our desired uniformly random distribution over the entire interior of the ball.
Picking a random direction (on the unit ball)
In order to achieve (1) we can randomly generate a vector from d independent draws of a Gaussian distribution normalized to unit length. This works because a Gausssian distribution has a probability distribution function (PDF) with x^2 in an exponent. That implies that the joint distribution (for independent random variables this is the multiplication of their PDFs) will have (x_1^2 + x_2^2 + ... + x_d^2) in the exponent. Notice that resembles the definition of a sphere in d dimensions, meaning the joint distribution of d independent samples from a Gaussian distribution is invariant to rotation (the vectors are uniform over a sphere).
Here is what 200 random points generated in 2D looks like.
Picking a random radius (with appropriate probability)
In order to achieve (2) we can generate a radius by using the inverse of a cumulative distribution function (CDF) that corresponds to the surface area of a ball in d dimensions with radius r. We know that the surface area of an n-ball is proportional to r^d, meaning we can use this over the range [0,1] as a CDF. Now a random sample is generated by mapping random numbers in the range [0,1] through the inverse, r^(1/d).
Here is a visual of the CDF of x^2 (for two dimensions), random generated numbers in [0,1] would get mapped to the corresponding x coordinate on this curve. (e.g. .1 ➞ .317)
Code for the above
Finally, here is some Python code (assumes you have NumPy installed) that computes all of the above.
# Generate "num_points" random points in "dimension" that have uniform
# probability over the unit ball scaled by "radius" (length of points
# are in range [0, "radius"]).
def random_ball(num_points, dimension, radius=1):
from numpy import random, linalg
# First generate random directions by normalizing the length of a
# vector of random-normal values (these distribute evenly on ball).
random_directions = random.normal(size=(dimension,num_points))
random_directions /= linalg.norm(random_directions, axis=0)
# Second generate a random radius with probability proportional to
# the surface area of a ball with a given radius.
random_radii = random.random(num_points) ** (1/dimension)
# Return the list of random (direction & length) points.
return radius * (random_directions * random_radii).T
For posterity, here is a visual of 5000 random points generated with the above code.