medpy.metric.binary.obj_asd#

medpy.metric.binary.obj_asd(result, reference, voxelspacing=None, connectivity=1)[source]#

Average surface distance between objects.

First correspondences between distinct binary objects in reference and result are established. Then the average surface distance is only computed between corresponding objects. Correspondence is defined as unique and at least one voxel overlap.

Parameters:
resultarray_like

Input data containing objects. Can be any type but will be converted into binary: background where 0, object everywhere else.

referencearray_like

Input data containing objects. Can be any type but will be converted into binary: background where 0, object everywhere else.

voxelspacingfloat or sequence of floats, optional

The voxelspacing in a distance unit i.e. spacing of elements along each dimension. If a sequence, must be of length equal to the input rank; if a single number, this is used for all axes. If not specified, a grid spacing of unity is implied.

connectivityint

The neighbourhood/connectivity considered when determining what accounts for a distinct binary object as well as when determining the surface of the binary objects. This value is passed to scipy.ndimage.generate_binary_structure and should usually be \(> 1\). The decision on the connectivity is important, as it can influence the results strongly. If in doubt, leave it as it is.

Returns:
asdfloat

The average surface distance between all mutually existing distinct binary object(s) in result and reference. The distance unit is the same as for the spacing of elements along each dimension, which is usually given in mm.

Notes

This is not a real metric, as it is directed. See obj_assd for a real metric of this.

For the understanding of this metric, both the notions of connectedness and surface distance are essential. Please see obj_tpr and obj_fpr for more information on the first and asd on the second.

Examples

>>> arr1 = numpy.asarray([[1,1,1],[1,1,1],[1,1,1]])
>>> arr2 = numpy.asarray([[0,1,0],[0,1,0],[0,1,0]])
>>> arr1
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])
>>> arr2
array([[0, 1, 0],
       [0, 1, 0],
       [0, 1, 0]])
>>> obj_asd(arr1, arr2)
1.5
>>> obj_asd(arr2, arr1)
0.333333333333

With the voxelspacing parameter, the distances between the voxels can be set for each dimension separately:

>>> obj_asd(arr1, arr2, voxelspacing=(1,2))
1.5
>>> obj_asd(arr2, arr1, voxelspacing=(1,2))
0.333333333333

More examples depicting the notion of object connectedness:

>>> arr1 = numpy.asarray([[1,0,1],[1,0,0],[0,0,0]])
>>> arr2 = numpy.asarray([[1,0,1],[1,0,0],[0,0,1]])
>>> arr1
array([[1, 0, 1],
       [1, 0, 0],
       [0, 0, 0]])
>>> arr2
array([[1, 0, 1],
       [1, 0, 0],
       [0, 0, 1]])
>>> obj_asd(arr1, arr2)
0.0
>>> obj_asd(arr2, arr1)
0.0
>>> arr1 = numpy.asarray([[1,0,1],[1,0,1],[0,0,1]])
>>> arr2 = numpy.asarray([[1,0,1],[1,0,0],[0,0,1]])
>>> arr1
array([[1, 0, 1],
       [1, 0, 1],
       [0, 0, 1]])
>>> arr2
array([[1, 0, 1],
       [1, 0, 0],
       [0, 0, 1]])
>>> obj_asd(arr1, arr2)
0.6
>>> obj_asd(arr2, arr1)
0.0

Influence of connectivity parameter can be seen in the following example, where with the (default) connectivity of 1 the first array is considered to contain two objects, while with an increase connectivity of 2, just one large object is detected.

>>> arr1 = numpy.asarray([[1,0,0],[0,1,1],[0,1,1]])
>>> arr2 = numpy.asarray([[1,0,0],[0,0,0],[0,0,0]])
>>> arr1
array([[1, 0, 0],
       [0, 1, 1],
       [0, 1, 1]])
>>> arr2
array([[1, 0, 0],
       [0, 0, 0],
       [0, 0, 0]])
>>> obj_asd(arr1, arr2)
0.0
>>> obj_asd(arr1, arr2, connectivity=2)
1.742955328

Note that the connectivity also influence the notion of what is considered an object surface voxels.