Metric for concavity of objects in skimage or in general in python

1.6k Views Asked by At

I have a code where at some point I get a set of 2D binary numpy arrays to represent the objects which are mainly ellipses and circles (cell nuclei)

I need a metric about how rough (jagged) the edges are. There is nuclear contour index in pathological literature: which is perimeter/ sqrt(area) this works but in our case we specifically need to see how "rough" the perimeter is. Nuclear contour indices of ellipse and circle are different even if both have smooth edges. In our case a circle with rough edge is much more significant than an ellipse with smooth edge.

I thought about using convexity hull explained here: I think in this case if the metric will be the same of for many minor concavities (which is the significant case for us) and one major concavity (which is not as significant) like in the pictures below.enter image description here

I also tried openCV however I found it hard to comprehend mathematically what actually happens in there and it looks very much like the skimage convexity hull and I would prefer to stick to skimage

1

There are 1 best solutions below

4
On BEST ANSWER

I think solidity (i.e. the ratio of pixels in an object to pixels of the convex hull) might be a good index to start off your tests. It can be computed in a straightforward way through the function skimage.measure.regionprops. The results I've obtained using this approach are shown below:

solidity

If that metric is not adequate for your application, you could try out compactness of circular variance. Take a look here for a comprehensive compilation of morphological features.

This is the code I used to generate the toy example above:

import numpy as np
from skimage import io, draw, transform, measure
import matplotlib.pyplot as plt

N = 512
rr, cc = draw.circle(r=N/2, c=N/2, radius=N/3, shape=(N, N))
steps = [4, 16, 32]
smooth = np.zeros(shape=(N, N), dtype=np.uint8)
smooth[rr, cc] = 255

fig, ax = plt.subplots(1, len(steps), figsize=(12, 5))

for i, s in enumerate(steps):
    jagged = transform.resize(smooth[::s, ::s], (N, N))
    jagged[jagged>0] = 1
    props = measure.regionprops(measure.label(jagged))
    ax[i].imshow(img)
    ax[i].set_title('Solidity={}'.format(props[0].solidity))

plt.show(fig)