# Centroid determination

**URL:** <https://discourse.slicer.org/t/centroid-determination/3541>\
**Category:** Support\
**Tags:** segmentation\
**Created:** [July 20, 2018, 12:59pm UTC](https://discourse.slicer.org/t/centroid-determination/3541 "2018-07-20T12:59:52Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Naia](https://avatars.discourse-cdn.com/v4/letter/n/94ad74/32.png) [@Naia](https://discourse.slicer.org/u/Naia)\
**Post date:** [July 20, 2018, 12:59pm UTC](https://discourse.slicer.org/t/centroid-determination/3541/1 "2018-07-20T12:59:52Z")

</div>

I am trying to determine the centroid of several previously segmented materials. I can’t find this option in the Quantification module “Segment Statistics” of this software.  
Is there any solution to this problem or the software 3D Slicer does’nt have any module that determines the centroid of an already segmented material?

I am currently using version 4.8.1 of the 3D Slicer software.

---

<div class="post-metadata">

**Author:** ![laoweijianglin](https://avatars.discourse-cdn.com/v4/letter/l/cab0a1/32.png) [@laoweijianglin](https://discourse.slicer.org/u/laoweijianglin)\
**Post date:** [July 22, 2018, 3:13am UTC](https://discourse.slicer.org/t/centroid-determination/3541/2 "2018-07-22T03:13:16Z")

</div>

I have the same issue as yours.

---

<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:** [July 22, 2018, 11:49am UTC](https://discourse.slicer.org/t/centroid-determination/3541/3 "2018-07-22T11:49:48Z")

</div>

It is shown in this example how to get the centroid using numpy and then transform the raw array coordinates to scene RAS coordinates: [https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Get\_centroid\_of\_a\_segment\_in\_world\_.28RAS.29\_coordinates](https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Get_centroid_of_a_segment_in_world_.28RAS.29_coordinates)

---

<div class="post-metadata">

**Author:** ![szhang](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@szhang](https://discourse.slicer.org/u/szhang)\
**Post date:** [September 22, 2020, 8:19pm UTC](https://discourse.slicer.org/t/centroid-determination/3541/4 "2020-09-22T20:19:08Z")

</div>

I have some follow-up questions:

1. If there is only vtkMRMLModelNode, how can I find centroid of a VTK model?
2. If 1) is not possible, how can I convert model to segmentation in a loadable script? I cannot find any associated function from slicer.modules.models.logic()

Thank you very much!

---

<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:** [September 22, 2020, 9:01pm UTC](https://discourse.slicer.org/t/centroid-determination/3541/5 "2020-09-22T21:01:07Z")

</div>

You can get center point very quickly as center of bounding box, with a little more computation from centroid of model points, or the exa t centroid (center of gravity assuming the model is filled with material of uniform density) using Segment statistics module.

---

<div class="post-metadata">

**Author:** ![szhang](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@szhang](https://discourse.slicer.org/u/szhang)\
**Post date:** [September 23, 2020, 1:53am UTC](https://discourse.slicer.org/t/centroid-determination/3541/6 "2020-09-23T01:53:42Z")

</div>

I see, thank you.  
I ended up implementing it without referring to bounding box, here’s my sample code as future reference for anyone who needs it:

> md = slicer.util.getNode(‘ModelX’)  
> pd = md.GetPolyData().GetPoints().GetData()  
> from vtk.util.numpy\_support import vtk\_to\_numpy  
> import numpy as np  
> print(np.average(vtk\_to\_numpy(pd), axis=0))

The output should print the average coordinate of all points within a vtkMRMLModelNode.

---

<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:** [September 23, 2020, 2:16am UTC](https://discourse.slicer.org/t/centroid-determination/3541/7 "2020-09-23T02:16:44Z")

</div>

Thank you for sharing the solution! You can use `slicer.util` helper functions to simplify things a bit:

```auto
modelNode = slicer.util.getNode(‘ModelX’)
pointCoordinates = slicer.util.arrayFromModelPoints(modelNode)
import numpy as np
print(np.average(vtk_to_numpy(pd), axis=0))

```

or even shorter (a bit less explicit, so I would only recommend for testing and troubleshooting, not in modules):

```auto
import numpy as np
print(np.average(array('ModelX'), axis=0))

```

---

<div class="post-metadata">

**Author:** ![szhang](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@szhang](https://discourse.slicer.org/u/szhang)\
**Post date:** [September 23, 2020, 2:21am UTC](https://discourse.slicer.org/t/centroid-determination/3541/8 "2020-09-23T02:21:52Z")

</div>

Oh, great! I like the two line solution, and it reads quite explicit to me 🙂

---

<div class="post-metadata">

**Author:** ![Optics\_Bioeng](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/optics_bioeng/32/66534_2.png) [@Optics\_Bioeng](https://discourse.slicer.org/u/Optics_Bioeng)\
**Post date:** [July 3, 2023, 4:55am UTC](https://discourse.slicer.org/t/centroid-determination/3541/9 "2023-07-03T04:55:17Z")

</div>

I have a question about getting a centroid of segment.  
I ran this code below, but it couldn’t work.

```python
segmentationNode = slicer.util.getNode("vtkMRMLSegmentationNode1")
segmentId = "Segment_1"

# Get array voxel coordinates
seg=slicer.util.arrayFromSegment(segmentationNode, segmentId)
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)
# and the array is cropped to minimum size in the segmentation
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]

# Get segmentation voxel coordinates
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)
segImageExtent = segImage.GetExtent()
# origin of the array in voxel coordinates is determined by the start extent
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])

# Get segmentation physical coordinates
ijkToWorld = vtk.vtkMatrix4x4()
segImage.GetImageToWorldMatrix(ijkToWorld)
mean_World = [0, 0, 0, 1]
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)
mean_World = mean_World[0:3]

# If segmentation node is transformed, apply that transform to get RAS coordinates
transformWorldToRas = vtk.vtkGeneralTransform()
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)
mean_Ras = transformWorldToRas.TransformPoint(mean_World)

# Show mean position value and jump to it in all slice viewers
print(mean_Ras)
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)

```

from [Documentation/Nightly/ScriptRepository - Slicer Wiki](https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Get_centroid_of_a_segment_in_world_.28RAS.29_coordinates)  
I got error below

```python
TypeError Traceback (most recent call last)
Cell In[15], line 11
      8 mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]
     10 # Get segmentation voxel coordinates
---> 11 segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)
     12 segImageExtent = segImage.GetExtent()
     13 # origin of the array in voxel coordinates is determined by the start extent

TypeError: GetBinaryLabelmapRepresentation() takes exactly 2 arguments (1 given)

```

Could you teach me the reason why this error happen?  
Thank you

---

<div class="post-metadata">

**Author:** ![rbumm](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/rbumm/32/9404_2.png) [@rbumm](https://discourse.slicer.org/u/rbumm)\
**Post date:** [July 3, 2023, 7:01am UTC](https://discourse.slicer.org/t/centroid-determination/3541/10 "2023-07-03T07:01:11Z")

</div>

> [@Optics\_Bioeng](#):
>
> `GetBinaryLabelmapRepresentation`

You should probably call the function [as shown in the latest script repository](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#get-a-representation-of-a-segment).
