Issue with morphological filters
*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-ob... 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
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.niccoli@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-ob...
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 -- 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+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
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....@gmail.com <javascript:>> 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-ob...
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
-- 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...@googlegroups.com <javascript:>. For more options, visit https://groups.google.com/d/optout. <filled_contours.png>
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.mo... Juan. On Fri, Mar 27, 2015 at 9:09 AM, Matteo <matteo.niccoli@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....@gmail.com <javascript:>> 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-ob...
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
-- 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...@googlegroups.com <javascript:>. For more options, visit https://groups.google.com/d/optout. <filled_contours.png>
-- 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+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Hello Juan Here it is: http://nbviewer.ipython.org/urls/dl.dropbox.com/s/ancfxe2gx1fbyyp/morphology... 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.mo...
Juan.
On Fri, Mar 27, 2015 at 9:09 AM, Matteo <matteo....@gmail.com <javascript:>> 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....@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-ob...
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
...
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.niccoli@gmail.com> wrote:
Hello Juan Here it is: http://nbviewer.ipython.org/urls/dl.dropbox.com/s/ancfxe2gx1fbyyp/morphology... 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.mo...
Juan.
On Fri, Mar 27, 2015 at 9:09 AM, Matteo <matteo....@gmail.com <javascript:>> 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....@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-ob...
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+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
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....@gmail.com <javascript:>> wrote:
Hello Juan
Here it is:
http://nbviewer.ipython.org/urls/dl.dropbox.com/s/ancfxe2gx1fbyyp/morphology... 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.mo...
Juan.
On Fri, Mar 27, 2015 at 9:09 AM, Matteo <matteo....@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....@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-ob...
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...@googlegroups.com <javascript:>. For more options, visit https://groups.google.com/d/optout.
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_lin...>, 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....@gmail.com> wrote:
Hello Juan
Here it is:
http://nbviewer.ipython.org/urls/dl.dropbox.com/s/ancfxe2gx1fbyyp/morphology... 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.mo...
Juan.
On Fri, Mar 27, 2015 at 9:09 AM, Matteo <matteo....@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....@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-ob...
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...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
participants (2)
-
Juan Nunez-Iglesias
-
Matteo