I have multiple grids (numpy arrays [Nk,Ny,Nx]) and would like to use Hausdorff distance as a metric of similarity of these grids. There are several modules in scipy (scipy.spatial.distance.cdist,scipy.spatial.distance.pdist) which allow to calculate Euclidean distance between 2D arrays. Now to compare grids I have to choose some cross-section (e.g. grid1[0,:] & grid2[0,:]) and compare it between each other. Is it possible to calculate Hausdorff distance between 3D grids directly?
We can compute the fractional Hausdorff distance, in which say 90% of the points in A have that distance or less to some point in B. This is the same as taking the upper envelope of the m Voronoi surfaces, A − b1,A − b2,...,A − bm. The running time of an algorithm based on this approach is O(nm(n + m)polylog(n + m)).
The Hausdorff distance is the longest distance you can be forced to travel by an adversary who chooses a point in one of the two sets, from where you then must travel to the other set. In other words, it is the greatest of all the distances from a point in one set to the closest point in the other set.
The average Hausdorff distance is a widely used performance measure to calculate the distance between two point sets. In medical image segmentation, it is used to compare ground truth images with segmentation results and allows ranking different segmentation results.
Hausdorff Distance Image Comparison. The function h(A,B) is called the directed Hausdorff `distance' from A to B (this function is not symmetric and thus is not a true distance). It identifies the point that is farthest from any point of B, and measures the distance from a to its nearest neighbor in B.
In computer graphics the Hausdorff distance is used to measure the difference between two different representations of the same 3D object particularly when generating level of detail for efficient display of complex 3D models. A measure for the dissimilarity of two shapes is given by Hausdorff distance up to isometry, denoted DH.
We propose Hausdorff distance as a 3D aperture metric for the rough-walled 3D rock fracture. To verify its plausibility, we construct a fracture model from a 3D scanned crystalline rock sample.
You can use igl::hausdorff in libigl. If your first mesh has vertices in the rows of a matrix VA with face indices FA and likewise VB and FB for your second mesh, then will compute the Hausdorff distance d between the two meshes.
It turns the set of non-empty compact subsets of a metric space into a metric space in its own right. It is named after Felix Hausdorff and Dimitrie Pompeiu .
I am newby here, but faced with the same challenge and tried to attack it directly on a 3D level.
So here is the function I did:
def Hausdorff_dist(vol_a,vol_b):
dist_lst = []
for idx in range(len(vol_a)):
dist_min = 1000.0
for idx2 in range(len(vol_b)):
dist= np.linalg.norm(vol_a[idx]-vol_b[idx2])
if dist_min > dist:
dist_min = dist
dist_lst.append(dist_min)
return np.max(dist_lst)
The input needs to be numpy.array, but the rest is working directly.
I have 8000 vs. 5000 3D points and this runs for several minutes, but at the end it gets to the distance you are looking for.
This is however checking the distance between two points, not neccesarily the distance of two curves. (neither mesh).
Edit (on 26/11/2015):
Recenty finished the fine-tuned version of this code. Now it is splitted into two part.
First is taking care of grabbing a box around a given point and taking all the radius. I consider this as a smart way to reduce the number of points required to check.
def bbox(array, point, radius):
a = array[np.where(np.logical_and(array[:, 0] >= point[0] - radius, array[:, 0] <= point[0] + radius))]
b = a[np.where(np.logical_and(a[:, 1] >= point[1] - radius, a[:, 1] <= point[1] + radius))]
c = b[np.where(np.logical_and(b[:, 2] >= point[2] - radius, b[:, 2] <= point[2] + radius))]
return c
And the other code for the distance calculation:
def hausdorff(surface_a, surface_b):
# Taking two arrays as input file, the function is searching for the Hausdorff distane of "surface_a" to "surface_b"
dists = []
l = len(surface_a)
for i in xrange(l):
# walking through all the points of surface_a
dist_min = 1000.0
radius = 0
b_mod = np.empty(shape=(0, 0, 0))
# increasing the cube size around the point until the cube contains at least 1 point
while b_mod.shape[0] == 0:
b_mod = bbox(surface_b, surface_a[i], radius)
radius += 1
# to avoid getting false result (point is close to the edge, but along an axis another one is closer),
# increasing the size of the cube
b_mod = bbox(surface_b, surface_a[i], radius * math.sqrt(3))
for j in range(len(b_mod)):
# walking through the small number of points to find the minimum distance
dist = np.linalg.norm(surface_a[i] - b_mod[j])
if dist_min > dist:
dist_min = dist
dists.append(dist_min)
return np.max(dists)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With