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!
CodePudding user response:
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.
CodePudding user response:
IIUC, you could use a custom function to find the height/width of the bounding box and compute the average of both dimensions:
def get_diameter(g):
a = (groups==g)
h = (a.sum(1)!=0).sum()
w = (a.sum(0)!=0).sum()
return (h w)/2
df['diameter'] = df['Particle #'].map(get_diameter)
output:
Particle # Size [pixel #] A [nm2] diameter
1 1 10 10 3.5
2 2 1 1 1.0
3 3 3 3 2.0
4 4 4 4 2.5