Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Average diameter of complex shapes from pixels in df, Python

I have a DataFrame of multiple particles, that have gotten the group numbers (1,2,3,4) like this:

Groups: 
 [[0 0 0 1 1 1 0 0]
 [0 2 0 1 1 1 0 0]
 [0 0 0 1 1 1 0 0]
 [0 0 0 0 1 0 0 0]
 [0 3 3 0 0 4 0 0]
 [0 3 0 0 0 4 0 0]
 [0 0 0 0 0 4 0 0]
 [0 0 0 0 0 4 0 0]]
Number of particles: 4

I have then calculated the areas of the particles and created a DataFrame (assuming 1 pixel = 1 nm):

   Particle #  Size [pixel #]  A [nm2]  
1           1              10       10     
2           2               1        1     
3           3               3        3     
4           4               4        4     

Now I want to calculate the diameter of the particles. However, the shapes of the particles are complex, therefore I am looking for a method to calculate the average diameter (considering the shapes are not perfectly round) and adding another column next to A [nm2] with the average diameter.

Will this be possible?

Here is my full code:

import numpy as np
from skimage import measure
import pandas as pd

final = [
    [0, 0, 0, 255, 255, 255, 0, 0],
    [0, 255, 0, 255, 255, 255, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, ],
    [0, 0, 0, 0, 255, 0, 0, 0],
    [0, 255, 255, 0, 0, 255, 0, 0],
    [0, 255, 0, 0, 0, 255, 0, 0],
    [0, 0, 0, 0, 0, 255, 0, 0],
    [0, 0, 0, 0, 0, 255, 0, 0]
]

final = np.asarray(final)

groups, group_count = measure.label(final > 0, return_num = True, connectivity = 1)
 
print('Groups: \n', groups)
print(f'Number of particles: {group_count}')

df = (pd.DataFrame(dict(zip(['Particle #', 'Size [pixel #]'],
                            np.unique(groups, return_counts=True))))
        .loc[lambda d: d['Particle #'].ne(0)]
     )

pixel_nm_size = 1*1

df['A [nm2]'] = df['Size [pixel #]'] * pixel_nm_size

Any help is appreciated!

like image 460
Fred Avatar asked Sep 14 '26 05:09

Fred


1 Answers

I think you are looking for regionprops.

Specifically, either equivalent_diameter, or just perimeter.

props = measure.regionprops_table(groups, properties = ['label', 'equivalent_diameter', 'perimeter'])
df = pd.DataFrame(props)

edit

from the docs:

equivalent_diameter_area: float
The diameter of a circle with the same area as the region.

So, the function takes your labeled region, measures the area and constructs a circle with that area (there is only one such circle for each area). Then it measures the diameter of the circle.

You can also look at major_axis_length and minor_axis_length. These are computed by fitting an ellipse around the object and measuring the long and short axis that define it.

like image 179
warped Avatar answered Sep 15 '26 18:09

warped



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!