Issue with morphological filters

Matteo matteo.niccoli at gmail.com
Mon Nov 16 09:51:18 EST 2015


I never followed up on this (thanks Stéphan for reminding me):

I never got to try regionprops, the last option suggested by Juan. In my 
final version (in this Geophysical tutorial notebook 
<https://github.com/seg/tutorials/blob/master/1508_Mapping_and_validating_lineaments/1508_Mapping_and_validating_lineaments.ipynb>, 
cells 36-40) I ended up exporting the full edges as a full image instead of 
as filled contours. To remove the small objects I used (cell 38) scipy.
ndimage.label and a mask.

Thanks for all the suggestions
Matteo



On Thursday, April 2, 2015 at 7:22:03 AM UTC-6, Matteo wrote:

> OK
> Thanks so much for your efforts Juan, I will take a look. 
> Matteo
>
> On Sunday, March 29, 2015 at 10:03:23 PM UTC-6, Juan Nunez-Iglesias wrote:
>
>> Hmm, I must say I don't know what's going on with either the 
>> reconstruction or the binary_fill_holes. (Originally I thought the image 
>> was inverted but you tried both polarities...) My advice would be to look 
>> at a few iterations of morphological reconstruction manually and see what's 
>> going on...
>>
>> Also, I would use the "grey" colormap, which is the most intuitive to 
>> look at (you used a reversed colormap for a couple of the images).
>>
>> Finally, it may be that you need to fill each "blob" independently. If 
>> so, have a look at skimage.measure.regionprops.filled_image.
>> http://scikit-image.org/docs/dev/api/skimage.measure.html#regionprops
>>
>> Juan.
>>
>>
>>
>>
>> On Sat, Mar 28, 2015 at 2:32 AM, Matteo <matteo.... at gmail.com> wrote:
>>
>>> Hello Juan
>>>
>>> Here it is: 
>>>
>>> http://nbviewer.ipython.org/urls/dl.dropbox.com/s/ancfxe2gx1fbyyp/morphology_test.ipynb?dl=0
>>> I get the same, odd results, with both ndimage's binary_fill_holes, and 
>>> reconstruction. IS it because of the structuring elements/masks?
>>> Thanks for your help.
>>> Matteo
>>>
>>> On Thursday, March 26, 2015 at 11:14:05 PM UTC-6, Juan Nunez-Iglesias 
>>> wrote:
>>>
>>>> Hi Matteo,
>>>>
>>>> Can you try putting this notebook up as a gist and pasting a link to 
>>>> the notebook? It's hard for me to follow all of the steps (and the polarity 
>>>> of the image) without the images inline. Is it just the inverse of what you 
>>>> want? And anyway why aren't you just using ndimage's binary_fill_holes?
>>>>
>>>>
>>>> https://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.ndimage.morphology.binary_fill_holes.html
>>>>
>>>> Juan.
>>>>
>>>>
>>>>
>>>>
>>>> On Fri, Mar 27, 2015 at 9:09 AM, Matteo <matteo.... at gmail.com> wrote:
>>>>
>>>> Hello Juan
>>>>
>>>> Thanks so much for your suggestions.
>>>> Once I convertedthe image as you suggested:
>>>> # import back image
>>>> cfthdr=io.imread('filled_contour_THDR.png')
>>>> cfthdr = color.rgb2gray(cfthdr) > 0.5 
>>>>
>>>> I get good results with opening:
>>>> # clean it up with opening
>>>> selem17 = disk(17)
>>>> opened_thdr = opening(cfthdr, selem17)/255
>>>> # plot it 
>>>> fig = plt.figure(figsize=(5, 5))
>>>> ax = fig.add_subplot(1, 1, 1)
>>>> ax.set_xticks([])
>>>> ax.set_yticks([])
>>>> plt.imshow(opened_thdr,cmap='bone')
>>>> plt.show()
>>>> # not bad
>>>>
>>>>
>>>> With remove_small_objects the advantage is that it does not join blobs 
>>>> in the original:
>>>> cfthdr_inv = ~cfthdr
>>>> test=remove_small_objects(cfthdr,10000)
>>>> # plot it 
>>>> fig = plt.figure(figsize=(5, 5))
>>>> ax = fig.add_subplot(1, 1, 1)
>>>> ax.set_xticks([])
>>>> ax.set_yticks([])
>>>> plt.imshow(test,cmap='bone')
>>>> plt.show() 
>>>>
>>>>
>>>> but with reconstruction done as this:
>>>> # filling holes with morphological reconstruction
>>>> seed = np.copy(cfthdr_inv)
>>>> seed[1:-1, 1:-1] = cfthdr_inv.max()
>>>> mask = cfthdr_inv
>>>> filled = reconstruction(seed, mask, method='erosion')
>>>> # plot it 
>>>> fig = plt.figure(figsize=(5, 5))
>>>> ax = fig.add_subplot(1, 1, 1)
>>>> ax.set_xticks([])
>>>> ax.set_yticks([])
>>>> plt.imshow(filled,cmap='bone',vmin=cfthdr_inv.min(), vmax=cfthdr_inv.
>>>> max())
>>>> plt.show() 
>>>>
>>>> I get a completely white image. Do you have any suggestions as to why?
>>>>
>>>> Thank again. Cheers,
>>>> Matteo
>>>>
>>>>
>>>> On Wednesday, March 25, 2015 at 6:29:43 PM UTC-6, Juan Nunez-Iglesias 
>>>> wrote:
>>>>
>>>> Hi Matteo,
>>>>
>>>> My guess is that even though you are looking at a "black and white" 
>>>> image, the png is actually an RGB png. Just check the output of 
>>>> "print(cfthdr.shape)". Should be straightforward to make it a binary image:
>>>>
>>>> from skimage import color
>>>> cfthdr = color.rgb2gray(cfthdr) > 0.5
>>>>
>>>> Then you should have a binary image. (And inverting should be as simple 
>>>> as "cfthdr_inv = ~cfthdr") We have morphology.binary_fill_holes to do what 
>>>> you want.
>>>>
>>>> btw, there's also morphology.remove_small_objects, which does exactly 
>>>> what you did but as a function call. Finally, it looks like you are not 
>>>> using the latest version of scikit-image (0.11), so you might want to 
>>>> upgrade.
>>>>
>>>> Hope that helps!
>>>>
>>>> Juan.
>>>>
>>>>
>>>>
>>>>
>>>> On Thu, Mar 26, 2015 at 8:48 AM, Matteo <matteo.... at gmail.com> wrote:
>>>>
>>>> *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 
>>>>
>>>> ...
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "scikit-image" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to scikit-image... at googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/scikit-image/attachments/20151116/4ddc9d56/attachment.html>


More information about the scikit-image mailing list