Question

I'm trying to extract a single long boundary from a rather noisy image (forgive the green, the image is converted to grayscale in any case). I've tried running various edge detection and threshold algorithms to extract the boundary. The closest I've gotten so far is by using the local Otsu threshold bundled with scikit-image:

Even so, I'm still unable to extract any meaningful boundary - when I try to use edge detection on the image, it gets caught up in the noise, which is drastically amplified by the thresholding - the boundary detection algorithms are so heavily dependent on calculating the derivative, so the sharp transitions in a binary image really hurts their performance, but I believe it's necessary since no other method has managed to distinguish the boundary at all.

Is there some way to either force the local Otsu threshold to flatten out the noise under a particular global threshold, or get one of the boundary extraction algorithms to ignore things that look like?

enter image description here

Or is it best to write a replacement based on the local Otsu thresholding, that only applies the threshold when it returns a pattern resembling a line?

Any help finding the right way to get the relevant boundary is appreciated.

Was it helpful?

Solution

That's a nice Saffman-Taylor instability you got there ;)

Glenn is right, you'll probably want to do some filtering before you try detecting edges (gradients tend to be very sensitive to noise). Since you're detecting edges, you'll want to try an edge-preserving denoising filter. Here are some examples:

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

Below is a quick attempt at filtering your image:

from skimage import io
from skimage import color
from skimage import filter
import matplotlib.pyplot as plt

image = color.rgb2gray(io.imread('4g1te.png'))
denoised = filter.denoise_tv_bregman(image, 1)
edges = filter.canny(denoised, 1, 0.01, 0.1)

fig, axes = plt.subplots(ncols=2)
axes[0].imshow(denoised)
axes[1].imshow(edges)
for ax in axes:
    ax.set_axis_off()
plt.show()

denoised image and Canny edges

You'll need to play around quite a bit to get this right. I'd also try filtering out small line-segments from the edge image; maybe, some geometrical properties would be helpful with that:

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

Good luck!

OTHER TIPS

Often, the best way to deal with detection in the presence of noise is to first reduce the noise.

Prefiltering your image with various noise reducing operations may help to improve the behavior of your boundary detection algorithms. Common (simple) noise reducing methods are spatial blurring or median filtering. However, if you know that the noise exists at a particular frequency range, a frequency-domain notch filter can often be useful as well.

The trick is to reduce noise without also destroying the boundary that you want to find. Depending on image content, this is often a process of trial and error.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top