Extract 3D measurements (volume, centroid... etc) from masked stack

Hello everybody,

I am trying to compute the volumes of some nuclei I have segmented, together with other measures such as the centroid position, for example. The problem is that I have a stack and so far I can only extract 2D data from each frame using skimage.measure.regionprops(). I would like to continue the image analysis in Python, therefore the question:

How can I calculate 3D measurements starting from this stack?

I do know the pixel size in xy and z, but I am not sure that simply computing that for the number of frames is correct. I was trying therefore to use skim age.measure.marching_cubes_lewiner, which computed the 3D surface area. But again, it is the area and I do not know how to translate this in the volume and other measurements.

Sample image and/or code

This is only one frame of the masked stack. I have just opened in Fiji and it appears that all nuclei have the same value. Actually, in the stack I have every nucleus is labeled with a unique integer value so I can recognise them through the stack… anyway, this is just to give an idea.

S16-20200805_30hpf_LM1_eGFP-LAP2B_H2B-RFP_40X_E7_processed_crop-2.tif (1.2 MB)

Please, if you know how I can solve this problem let me know!

Thanks,
Lucrezia

1 Like

@LucreziaF what makes you say “I can only extract 2D data”? Most regionprops properties (including the ones you mentioned) work with 3D arrays. .area will give you the volume in pixels, .centroid will work as you would expect. Does that solve your problem?

Mmmm maybe I am not feeding the right data, but what I have are measurements for every labelled object in the frame, like the area. The information in z is missing. So, I am trying to sum all together taking into account the z step and scale of pixels in x and y but I am not sure this is the right approach…

That’s what I wrote:

labeled_frames = imread(fname=filename)
properties = ['label', 'area']
tables = [regionprops_table(labeled_frames[i], properties=properties) for i in range(len(labeled_frames))]

tables = [pd.DataFrame(table) for table in tables]

So in this case I get a list of data frames, each for every frame, having the area and the label for each object. Then I convert the areas from pixel to micron scale and theoretically I was thinking to multiply that by the z step value inn micron and sum up… But I am wondering if there is a specific function implemented for that.

About the marching_cubes_lewiner, I am a bit confused by the outputs and I am not sure how to use them for my purpose…

Yeah, instead of calling regionprops for each frame, call regionprops on the whole labeled_frames image:

labeled_frames = imread(fname=filename)
properties = ['label', 'area', 'centroid']
table = pd.DataFrame(regionprops_table(labeled_frames, properties=properties))

This will give you the volume of each region and its centroid in 3D.

From your original question I think you only want maching_cubes for volume, not surface area, so you shouldn’t need to use it here I think. .area will give you the volume in 3D. (Yes, we know this is confusing, that’s why there’s an issue about it! :joy:)