I am trying to compute the volume (or surface area) of a 3D numpy array. The voxels are anisotropic in a lot of cases, and I have the pixel to cm conversion factor in each direction.
Does anyone know a good place to find a toolkit or package to do the above??
Right now, I have some in-house code, but I am looking to upgrade to something more industrial strength in terms of accuracy.
Edit1: Here is some (poor) sample data. This is much smaller than the typical sphere. I will add better data when I can generate it! It is in (self.)tumorBrain.tumor.
One option is to use VTK. (I'm going to use the tvtk python bindings for it here...)
At least in some circumstances, getting the area within the isosurface will be a bit more accurate.
Also, as far as surface area goes, tvtk.MassProperties calculates surface area as well. It's mass.surface_area (with the mass object in the code below).
import numpy as np
from tvtk.api import tvtk
def main():
# Generate some data with anisotropic cells...
# x,y,and z will range from -2 to 2, but with a
# different (20, 15, and 5 for x, y, and z) number of steps
x,y,z = np.mgrid[-2:2:20j, -2:2:15j, -2:2:5j]
r = np.sqrt(x**2 + y**2 + z**2)
dx, dy, dz = [np.diff(it, axis=a)[0,0,0] for it, a in zip((x,y,z),(0,1,2))]
# Your actual data is a binary (logical) array
max_radius = 1.5
data = (r <= max_radius).astype(np.int8)
ideal_volume = 4.0 / 3 * max_radius**3 * np.pi
coarse_volume = data.sum() * dx * dy * dz
est_volume = vtk_volume(data, (dx, dy, dz), (x.min(), y.min(), z.min()))
coarse_error = 100 * (coarse_volume - ideal_volume) / ideal_volume
vtk_error = 100 * (est_volume - ideal_volume) / ideal_volume
print 'Ideal volume', ideal_volume
print 'Coarse approximation', coarse_volume, 'Error', coarse_error, '%'
print 'VTK approximation', est_volume, 'Error', vtk_error, '%'
def vtk_volume(data, spacing=(1,1,1), origin=(0,0,0)):
data[data == 0] = -1
grid = tvtk.ImageData(spacing=spacing, origin=origin)
grid.point_data.scalars = data.T.ravel() # It wants fortran order???
grid.point_data.scalars.name = 'scalars'
grid.dimensions = data.shape
iso = tvtk.ImageMarchingCubes(input=grid)
mass = tvtk.MassProperties(input=iso.output)
return mass.volume
main()
This yields:
Ideal volume 14.1371669412
Coarse approximation 14.7969924812 Error 4.66731094565 %
VTK approximation 14.1954890878 Error 0.412544796894 %
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