寻找噪声图像边缘的最佳方法

3
我有一张噪点图像,如下图所示。假设它是高斯噪声。目前,我使用两个步骤来查找边缘:
  1. 使用高斯滤波器G平滑图像
  2. 根据以下公式查找边缘

    g=1/(1+β∇ (I*G)^2)

其中,G为高斯滤波器,β为控制噪声水平的权重。
然而,高斯滤波器会导致图像中的边缘丢失。我想找到一种更好的方法来保留边缘信息。你能否建议我找到该图像边缘的最佳方法?
这是我上述步骤的结果。

enter image description here

这是我正在处理的带有噪声的图像:

enter image description here

为了获取边缘,这是我编写的 MATLAB 代码:
beta=0.01;
G = fspecial('gaussian',[3 3],1);
I_G = conv2(I,G,'same');
[Gx,Gy] = gradient(I_G);
NormGrad = sqrt(Gx.^2 + Gy.^2); 
g = 1./ (1 + beta* NormGrad.^2);
imshow(g,[]);
2个回答

5

对于你的特定应用,规范的保边平滑滤波器应该是相当合适的。这些滤波器可以同时去除噪声(我应该补充说明是高斯分布的...),同时尽可能地保持边缘。经典的例子包括双边滤波器, Kaiming He的引导滤波器, Gastal和Oliveira的域转换滤波(我过去已经成功使用过)甚至还包括各向异性扩散

为了快速尝试某些东西,引导图像滤波器现在作为MATLAB R2014a的图像处理工具箱的官方功能之一通过imguidedfilter函数提供。如果您没有MATLAB R2014a或更高版本,则可以通过此链接下载代码的原始MATLAB源代码:http://kaiminghe.com/eccv10/guided-filter-code-v1.rar,但您也可以从我上面提供的主网站获取此代码。
假设您没有R2014a,请下载Guided image filter代码,并使用它来过滤您的示例。鉴于您提供了噪声损坏的示例图像的链接,我已经下载并在下面的代码中使用它:
I = im2double(imread('http://i.stack.imgur.com/ACRE8.png')); %// Load in sample image that was corrupted by noise
r = 2; %// Parameters for the Guided image filter
eps = 0.1^2;

%// Filter the image, using itself as a guide
q = guidedfilter(I, I, r, eps);

%// Show the original image and the filtered result
figure;
subplot(1,2,1); imshow(I, []);
subplot(1,2,2); imshow(q, []);

我们展示原始图像,然后在右侧展示引导滤波器的结果:

enter image description here

一旦我们拥有了那个,尝试使用任何规范的边缘检测器来检测边缘。你正在使用的那个在找到边缘之前对图像进行预模糊处理,但这使用了标准平滑化,会错过一些边缘。因为使用引导图像滤镜使我们达到了保持边缘和整体图像基本无噪声的状态,所以我们可以尝试在边缘平滑结果上使用一些简单的滤波器,比如Sobel滤波器:
[Gmag,~] = imgradient(q, 'sobel');
imshow(max(Gmag(:)) - Gmag,[]);

上面的代码使用 imgradient 查找图像梯度,然后通过反转强度来显示图像,使黑色值变为白色,白色变为黑色,如您所示的示例。
... 然后我们得到了这个:

enter image description here

正如您所见,即使存在噪声,我们仍然能够处理掉许多边缘。

1
有许多量化指标可以用来确定一个结果是否比另一个更好,但这需要您参考原始边缘图像。如果您没有那个,那么您只能从定性上看待它。假设您有一个参考,您可以使用PSNR、MSE或任何相关的指标。话虽如此,如果没有可比较的参考,您就无法比较我的方法和你的方法。 - rayryeng
@rayryeng 你说得对,Matlab没有内置的TV。我认为TV在这里会很不错。如果它有效,我会发布第二个答案。 - Ander Biguri
2
@user3051460 - 我认为最好由自己比较我和Ander所写的内容,然后您自己确定哪种方法更好。您是最适合做出这个决定的人,让我们替您比较并不会让您学到什么东西。一个简单的测试可以是将梯度图像二值化为边缘像素,然后在两个图像之间执行SSD。PSNR也是一种很好的方法,您可以在此处查看如何计算它: http://stackoverflow.com/questions/16264141/power-signal-noise-ratio-psnr-of-colored-jpeg-image/16265510#16265510 - rayryeng
@rayryeng:我进行了比较,它的性能完全优于我的方法。目前,我想制作Sobel边缘(在数学上)的公式,看起来像高斯公式g=1/(1+β∇(IG)^2)。你能否为我建议一些参考或上述Sobel边缘检测实现的公式?我试图将你的代码max(Gmag(:)) - Gmag描述为g=1/(1+βGmag),但它们是不同的。'max(Gmag(:)) - Gmag'的范围将从0到max(Gmag(:)),而g=1/(1+βGmag)的范围将从0到1。但当我使用max(Gmag(:)) - Gmag时,我发现它比g=1/(1+βGmag)更准确。 - user3051460
这是我个人认为的另一个问题。请考虑提出另一个问题。 - rayryeng
显示剩余7条评论

3

为了补充@rayryeng的完整且有趣的答案,我将展示如何使用众所周知的Split-Bregman全变差算法进行降噪。

该算法强制图像具有“可能最少的灰度级”*。因此,它将去噪图像(因为相似的灰度级将被转换为相同的),但它将保留边缘。

Matlab没有实现TV,但您可以检查此实现

使用示例(代码自解释)

N = 256; n = N^2;

% Read image;
g=double(imread('http://i.stack.imgur.com/ACRE8.png'));
%fill it with zeroes to make a NxN image
sz=size(g);
img=zeros(N);
img(1:size(g,1),1:size(g,2))=g;
g=img;

% the higher this parameter is, the stronger the denoising
mu = 6;

% denoise 
g_denoise_atv = SB_ATV(g,mu);
%prepare output
denoised=reshape(g_denoise_atv,N,N);
denoised=denoised(1:sz(1),1:sz(2));

% edges
[Gmag,~] = imgradient(denoised, 'sobel');

subplot(131); imshow(g(1:sz(1),1:sz(2)),[]);title('Original');
subplot(132); imshow(denoised,[]);title('Denoised');
subplot(133); imshow(max(Gmag(:)) - Gmag,[]);title('Edges');

enter image description here]

如果您调整mu参数,可以得到非常去噪的(但图像数据丢失较多)图像或非常少去噪的(但保留更多图像质量数据的)图像。

mu=40

enter image description here

mu=1;

进入图片描述

* 这是该方法的非数学解释。对于纯理论研究者,请查阅L1正则化技术。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接