[scikit-image] fill closed contour

Randy Heiland randy.heiland at gmail.com
Mon Jan 8 20:55:53 EST 2018


Thanks Juan. I understand better what the  ndi.measurements.label can do
for me now. I've tweaked my previous script and attached the resulting
output. Does it make sense that I need to "thicken" the contours in order
to get the desired features/regions, or is there something I'm still
missing?

------------
from skimage.morphology import disk
from skimage.feature import canny
from skimage.filters import rank
from scipy import ndimage as ndi
import matplotlib.pyplot as plt
import numpy as np

image = disk(100)
for ix in range(200):
  for iy in range(200):
    xdel=ix-100
    ydel=iy-100
    if (xdel*xdel/50 + ydel*ydel/10) < 110:
      image[iy,ix]=0
    elif (xdel*xdel/10 + ydel*ydel/50) < 110:
      image[iy,ix]=0

edges = canny(image*255.)  # canny expect grayscale, i.e. 0-255 ??!

thicken = rank.gradient(edges, disk(1)) < 5
bdy = thicken.astype(np.uint8)*255

labeled_array, num_features = ndi.measurements.label(edges*1)
print("num_features (edges*1)=",num_features)
labeled_array2, num_features2 = ndi.measurements.label(bdy)
print("num_features (thick)=",num_features2)

fill = ndi.binary_fill_holes(edges)

fig, axes = plt.subplots(ncols=2, nrows=2, figsize=(6, 7))
ax = axes.ravel()

ax[0].imshow(edges*1, cmap=plt.cm.gray, interpolation='nearest')
ax[0].set_title('Canny edges')
ax[1].imshow(labeled_array, cmap=plt.cm.spectral, interpolation='nearest')
ax[1].set_title('labeled_array')

ax[2].imshow(bdy, cmap=plt.cm.gray, interpolation='nearest')
ax[2].set_title('bdy')
ax[3].imshow(labeled_array2, cmap=plt.cm.spectral, interpolation='nearest')
ax[3].set_title('labeled_array2')

plt.axis('off')
plt.show()

-->
num_features (edges*1)= 216
num_features (thick)= 6

-Randy


On Sun, Jan 7, 2018 at 11:36 PM, Juan Nunez-Iglesias <jni.soma at gmail.com>
wrote:

> Oh, I see what's happening. So, in your case, both void spaces are
> actually holes from the perspective of the binary_fill_holes algorithm, so
> they both get filled. I suggest you
>
> a) label both contours using ndi.label
> b) use binary_fill_holes on each label separately
> c) subtract the filled inner hole from the filled outer hole (you can
> optionally add back in the inner contour if you care about that
> single-pixel precision)
>
> This requires being able to robustly identify the inner and outer
> contours, but I don't think that should be too hard? If you only have two,
> you can certainly find them by finding the "larger" of the two bounding
> boxes. You can use skimage.measure.regionprops for this.
>
> I hope that helps!
>
> Juan.
>
> On 8 Jan 2018, 12:21 PM +1100, Randy Heiland <randy.heiland at gmail.com>,
> wrote:
>
> Sure - thanks.
>
> from skimage.morphology import disk
> from skimage.feature import canny
> from scipy import ndimage as ndi
> import matplotlib.pyplot as plt
>
> image = disk(100)
> for ix in range(200):
>   for iy in range(200):
>     xdel=ix-100
>     ydel=iy-100
>     if (xdel*xdel/50 + ydel*ydel/10) < 110:
>       image[iy,ix]=0
>     elif (xdel*xdel/10 + ydel*ydel/50) < 110:
>       image[iy,ix]=0
>
> edges = canny(image*255.)  # canny expect grayscale, i.e. 0-255 ??!
>
> fill = ndi.binary_fill_holes(edges)   # I don't understand the params; can
> I seed a region to fill?
>
> fig, axes = plt.subplots(ncols=3, figsize=(9, 3))
> ax = axes.ravel()
>
> ax[0].imshow(image, cmap=plt.cm.gray, interpolation='nearest')
> #ax[0].imshow(invert_img, cmap=plt.cm.gray)
> #ax[0].set_title('Inverted image')
> ax[0].set_title('Original image')
>
> ax[1].imshow(edges*1, cmap=plt.cm.gray, interpolation='nearest')
> ax[1].set_title('Canny edges')
>
> ax[2].imshow(fill, cmap=plt.cm.spectral, interpolation='nearest')
> ax[2].set_title('Fill')
>
> plt.show()
>
>
>
> On Sun, Jan 7, 2018 at 6:57 PM, Juan Nunez-Iglesias <jni.soma at gmail.com>
> wrote:
>
>> Hi Randy, I was going to suggest binary fill holes. Do you mind posting
>> your image and the code you’ve tried so we can troubleshoot?
>>
>> Thanks,
>>
>> Juan.
>>
>> On 8 Jan 2018, 9:48 AM +1100, Randy Heiland <randy.heiland at gmail.com>,
>> wrote:
>>
>> If I have a binary image with, say, just a contour boundary (simple
>> example: a white background with a black circle, i.e. an "o"), how can I
>> fill the inside of the contour? I've played with both the watershed
>> segmentation and the scipy.ndimage.binary_fill_holes, without success.
>>
>> thanks, Randy
>> _______________________________________________
>> scikit-image mailing list
>> scikit-image at python.org
>> https://mail.python.org/mailman/listinfo/scikit-image
>>
>>
>> _______________________________________________
>> scikit-image mailing list
>> scikit-image at python.org
>> https://mail.python.org/mailman/listinfo/scikit-image
>>
>>
> _______________________________________________
> scikit-image mailing list
> scikit-image at python.org
> https://mail.python.org/mailman/listinfo/scikit-image
>
>
> _______________________________________________
> scikit-image mailing list
> scikit-image at python.org
> https://mail.python.org/mailman/listinfo/scikit-image
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/scikit-image/attachments/20180108/9746d0fc/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: synth_2x2.jpg
Type: image/jpeg
Size: 55253 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/scikit-image/attachments/20180108/9746d0fc/attachment-0001.jpg>


More information about the scikit-image mailing list