噪声图像中的长边界检测
我正在尝试从一张比较嘈杂的图片中提取出一条长的边界(别在意绿色的部分,反正这张图片最后会转成灰度图)。我试过用各种边缘检测和阈值算法来提取边界。目前为止,我最接近的结果是使用了scikit-image中的局部Otsu阈值算法:
尽管如此,我还是无法提取出有意义的边界——当我尝试对这张图片进行边缘检测时,结果被噪声搞得一团糟,而阈值处理又把噪声放大了。边界检测算法非常依赖于计算图像的变化,所以在二值图像中,突然的变化会严重影响它们的效果,但我觉得这是必要的,因为其他方法根本无法区分出边界。
有没有办法让局部Otsu阈值在一个特定的全局阈值下平滑掉噪声,或者让某个边界提取算法忽略那些看起来像噪声的部分?
或者,是否最好写一个基于局部Otsu阈值的替代方案,只在返回类似线条的模式时才应用阈值?
任何帮助我找到合适的边界提取方法都非常感谢。
2 个回答
通常,处理噪声干扰时,最好的办法是先减少噪声。
在你的图像上使用各种降噪操作,可以帮助改善边界检测算法的效果。常见的简单降噪方法有空间模糊和中值滤波。不过,如果你知道噪声存在于某个特定的频率范围,使用频域的陷波滤波器也常常很有效。
关键是要在减少噪声的同时,不破坏你想要找到的边界。根据图像的内容,这通常需要反复尝试。
你这儿的Saffman-Taylor不稳定性真不错;)
Glenn说得对,在你尝试检测边缘之前,可能需要先做一些过滤,因为边缘检测对噪声非常敏感。既然你要检测边缘,就应该试试一种能保留边缘的去噪滤镜。这里有一些例子:
http://scikit-image.org/docs/dev/auto_examples/plot_denoise.html
下面是一个对你图像进行过滤的快速尝试:
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()
你需要多尝试几次才能把这个弄好。我还建议你从边缘图像中过滤掉一些小的线段;也许一些几何特性会对你有帮助:
http://scikit-image.org/docs/dev/auto_examples/plot_regionprops.html
祝你好运!