Issue with morphological filters

Matteo matteo.niccoli at gmail.com
Wed Mar 25 16:13:20 EDT 2015


 *Issues with morphological filters when trying to remove white holes in 
black objects in a binary images. Using opening or filling holes on 
inverted (or complement) of the original binary.*

Hi there 

I have a series of derivatives calculated on geophysical data.

Many of these derivatives have nice continuous maxima, so I treat them as 
images on which I do some cleanup with morphological filter. 

Here's one example of operations that I do routinely, and successfully:

# threshold theta map  using Otsu method

thresh_th = threshold_otsu(theta)

binary_th = theta > thresh_th

# clean up small objects

label_objects_th, nb_labels_th = sp.ndimage.label(binary_th)

sizes_th = np.bincount(label_objects_th.ravel())

mask_sizes_th = sizes_th > 175

mask_sizes_th[0] = 0

binary_cleaned_th = mask_sizes_th[label_objects_th]

# further enhance with morphological closing (dilation followed by an 
erosion) to remove small dark spots and connect small bright cracks

# followed by an extra erosion

selem = disk(1)

closed_th = closing(binary_cleaned_th, selem)/255

eroded_th = erosion(closed_th, selem)/255

# Finally, extract lienaments using skeletonization

skeleton_th=skeletonize(binary_th)

skeleton_cleaned_th=skeletonize(binary_cleaned_th)

# plot to compare

fig = plt.figure(figsize=(20, 7))

ax = fig.add_subplot(1, 2, 1)

imshow(skeleton_th, cmap='bone_r', interpolation='none')

ax2 = fig.add_subplot(1, 3, 2)

imshow(skeleton_cleaned_th, cmap='bone_r', interpolation='none')

ax.set_xticks([])

ax.set_yticks([])

ax2.set_xticks([])
ax2.set_yticks([])

Unfortunately I cannot share the data as it is proprietary, but I will for 
the next example, which is the one that does not work.

There's one derivative that shows lots of detail but not continuous maxima. 
As a workaround I created filled contours in Matplotlib

exported as an image. The image is attached.

Now I want to import back the image and plot it to test: 

# import back image 

cfthdr=io.imread('filled_contour.png') 

# threshold using using Otsu method 

thresh_thdr = threshold_otsu(cfthdr) 

binary_thdr = cfthdr > thresh_thdr 

# plot it 

fig = plt.figure(figsize=(5, 5)) 

ax = fig.add_subplot(1, 1, 1) 

ax.set_xticks([]) 

ax.set_yticks([]) 

plt.imshow(binary_thdr, cmap='bone') 

plt.show() 

The above works without issues. 

 

Next I want to fill the white holes inside the black blobs. I thought of 2 
strategies.

The first would be to use opening; the second to invert the image, and then 
fill the holes as in here: 

http://scikit-image.org/docs/dev/auto_examples/plot_holes_and_peaks.html 

By the way, I found a similar example for opencv here

http://stackoverflow.com/questions/10316057/filling-holes-inside-a-binary-object
 
Let's start with opening. When I try: 

selem = disk(1) 

opened_thdr = opening(binary_thdr, selem) 

or:

selem = disk(1) 

opened_thdr = opening(cfthdr, selem) 

I get an error message like this: 

--------------------------------------------------------------------------- 

ValueError                                Traceback (most recent call last) 

<ipython-input-49-edc0d01ba327> in <module>() 

      1 #binary_thdr=img_as_float(binary_thdr,force_copy=False) 

----> 2 opened_thdr = opening(binary_thdr, selem)/255 

      3 

      4 # plot it 

      5 fig = plt.figure(figsize=(5, 5)) 

C:\...\skimage\morphology\grey.pyc in opening(image, selem, out) 

    160     shift_y = True if (h % 2) == 0 else False 

    161 

--> 162     eroded = erosion(image, selem) 

    163     out = dilation(eroded, selem, out=out, shift_x=shift_x, 
shift_y=shift_y) 

    164     return out 

C:\...\skimage\morphology\grey.pyc in erosion(image, selem, out, shift_x, 
shift_y) 

     58     selem = img_as_ubyte(selem) 

     59     return cmorph._erode(image, selem, out=out, 

---> 60                          shift_x=shift_x, shift_y=shift_y) 

     61 

     62 

C:\...\skimage\morphology\cmorph.pyd in skimage.morphology.cmorph._erode 
(skimage\morphology\cmorph.c:2658)() 

ValueError: Buffer has wrong number of dimensions (expected 2, got 3) 

--------------------------------------------------------------------------- 

Any idea of what is going on and how I can fix it? 

 

As for inverting (or finding the complement) and then hole filling, that 
would be my preferred option. 

However, I have not been able to invert the image. I tried numpy.invert, 
adapting the last example from here: 

http://docs.scipy.org/doc/numpy/reference/generated/numpy.invert.html 

I tried something like this: 

http://stackoverflow.com/a/16724700 

and this: 

http://stackoverflow.com/a/2498909 

But none of these methods worked. Is there a way in scikit.image to do 
that, and if not, do you have any suggestions? 

Thank you,

Matteo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/scikit-image/attachments/20150325/5ac5d602/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: filled_contours.png
Type: image/png
Size: 19400 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/scikit-image/attachments/20150325/5ac5d602/attachment.png>


More information about the scikit-image mailing list