# Different Volume Calculation Results

**URL:** <https://discourse.slicer.org/t/different-volume-calculation-results/37896>\
**Category:** Development\
**Created:** [August 14, 2024, 10:46pm UTC](https://discourse.slicer.org/t/different-volume-calculation-results/37896 "2024-08-14T22:46:24Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![dzzhang](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/dzzhang/32/66871_2.png) [@dzzhang](https://discourse.slicer.org/u/dzzhang)\
**Post date:** [August 14, 2024, 10:46pm UTC](https://discourse.slicer.org/t/different-volume-calculation-results/37896/1 "2024-08-14T22:46:24Z")

</div>

I have a binary mask, I loaded it in 3D slicer as a segmentation file, and in Data module, I used “export visible segments to model”. Then in Models module, I can see the model volume is 55349.06 mm^3 (none smooth).

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/7/b/7bde0346c20532c6dc214004a396b623def3964e.jpeg)

Then, I used my own vtk codes to calculate its volume:

```auto
mask = vtk.vtkNIFTIImageReader()
mask.SetFileName('origCT_nodule_0.nii.gz')
mask.Update()
nodule = vtk.vtkDiscreteMarchingCubes()
nodule.SetInputData(mask.GetOutput())
nodule.Update()

massProperties = vtk.vtkMassProperties()
massProperties.SetInputData(nodule.GetOutput())
massProperties.Update()
volume = massProperties.GetVolume()
print(volume)

```

However, the volume is 47789.92 mm^3. I visualized it to check what happened:

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/5/5/551daf7049b1e25383d35573ca2ff25bde8f107e.png)  
Oh, it seems this is an unclosed surface representation. I know 3D Slicer will close it first and then calculate its volume (as in the first screenshot). Then, I used vtkFillHolesFilter() to close the surface first:

```auto
fill_holes_filter = vtk.vtkFillHolesFilter()
fill_holes_filter.SetInputData(nodule.GetOutput())
fill_holes_filter.SetHoleSize(100.0)
fill_holes_filter.Update()

```

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/8/5/8560eacd372a3029bd93ef93df9d614f633791ab.png)

This time, the volume is 40265.35 mm^3. What happened???

> **[origCT\_nodule\_0.nii.gz](https://drive.google.com/file/d/1U_n0JB-oBHwwA_0QbKkXfjeiQDnLhhVH/view?usp=sharing)**
>
> Google Drive file.

---

<div class="post-metadata">

**Author:** ![chir.set](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/chir.set/32/66982_2.png) [@chir.set](https://discourse.slicer.org/u/chir.set)\
**Post date:** [August 15, 2024, 8:17am UTC](https://discourse.slicer.org/t/different-volume-calculation-results/37896/2 "2024-08-15T08:17:34Z")

</div>

> [@dzzhang](#):
>
> `vtk.vtkMassProperties()`

This class needs also a triangulated surface, try applying vtkTriangleFilter().

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [August 15, 2024, 9:43am UTC](https://discourse.slicer.org/t/different-volume-calculation-results/37896/3 "2024-08-15T09:43:10Z")

</div>

Estimating volume from a mesh is much more complicated and many things can influence the result. Slicer uses more robust and accurate surface reconstruction method than discrete marching cubes. If you use a simpler method then you will get a different, most likely less accurate results.

If you have a labelmap image then you can compute the volume very easily and robustly, using `Segment Statistics` module. There is only one single computation method (multiply the volume of one voxel by the number of voxels in the segment), so there are no options, no questions, no doubts.

---

<div class="post-metadata">

**Author:** ![dzzhang](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/dzzhang/32/66871_2.png) [@dzzhang](https://discourse.slicer.org/u/dzzhang)\
**Post date:** [August 15, 2024, 5:11pm UTC](https://discourse.slicer.org/t/different-volume-calculation-results/37896/4 "2024-08-15T17:11:12Z")

</div>

I tried the following codes but there’s no luck

> t = vtk.vtkTriangleFilter()  
> t.SetInputData(nodule.GetOutput())  
> t.PassVertsOn()  
> t.PassLinesOn()  
> t.Update()

---

<div class="post-metadata">

**Author:** ![dzzhang](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/dzzhang/32/66871_2.png) [@dzzhang](https://discourse.slicer.org/u/dzzhang)\
**Post date:** [August 15, 2024, 5:24pm UTC](https://discourse.slicer.org/t/different-volume-calculation-results/37896/5 "2024-08-15T17:24:50Z")

</div>

Solved it by using the following codes, thanks for the idea:

```
image_data = mask_image2.GetOutput()
spacing = image_data.GetSpacing()

# Extract the voxel data and convert to a NumPy array
dims = image_data.GetDimensions()
scalars = image_data.GetPointData().GetScalars()
from vtkmodules.util import numpy_support
mask_image_array = numpy_support.vtk_to_numpy(scalars)
mask_image_array = mask_image_array.reshape(dims, order='F') # Reshape to 3D array with Fortran order

# Convert the segmentation mask to a binary array (1 for segmented regions, 0 otherwise)
binary_array = np.where(mask_image_array > 0, 1, 0)

# Count the number of non-zero voxels
voxel_count = binary_array.sum()

# Calculate the volume in physical units (e.g., mm^3)
voxel_volume = spacing[0] * spacing[1] * spacing[2]
total_volume = voxel_count * voxel_volume

print(total_volume)

```
