我正在尝试对图像进行去噪。我想通过查看SNR值来了解它是否已去噪。现在,如何估算Python中图像的SNR?
答案 0 :(得分:2)
SNR is defined in different ways,但我想对于您的应用程序而言,其确切定义并不重要。通常,它是信号强度和噪声强度的比率。这里故意将“强度”留得模棱两可,经常使用信号和噪声的功率,但振幅也是可行的。
那么我们假设SNR是图像信号的功率除以噪声信号的功率。噪声的力量仅仅是其方差。您在比较去噪前后的图像,因此大概信号的功率不会改变。我们可以忽略它并将其设置为1。现在,我们的SNR被简单地定义为1/var(noise)
。
因此,您需要做的是估算噪声方差,然后对去噪前后的噪声方差进行比较。您希望看到这种变化减小(随SNR的增加而增加)。
通常,如果不知道没有噪声的图像是什么样的,估计图像的噪声方差就不容易了。您可以将嘈杂的图像视为
image = noiseless_image + noise.
因此,图像的方差是噪声的方差+无噪声图像的方差。如果您不了解后者,那么您将无法获得前者。
但是有一些技巧。如果您愿意为比较的每个图像做一些手工工作,最简单的方法是勾勒出平坦的背景区域(通常可以使用一小部分天空)。在该区域内强度没有自然变化非常重要。现在,只需计算该区域内像素的方差即可。
已为此目的发布了几种全自动方法。我知道J.Immerkær撰写的一篇文章:“快速噪声方差估计”,计算机视觉和图像理解64(2):300-302,1996年。DIPlib库(我是作者)具有an implementation。您可以按照以下说明从Python使用它:
var = dip.EstimateNoiseVariance(img)
(使用img
是库中的图像对象,Numpy数组或其他任何公开缓冲区的对象)。但是,由于尚未正式发布具有Python绑定的库版本,因此,如果要使用此实现,则必须自己获取并编译该库。但是考虑到它是一种非常简单的方法,您可以考虑自己实现。
以下是该方法的伪代码:
mask = gradient magnitude of img
Apply Gaussian smoothing (sigma = 3) to mask
If the image has more than one channel:
mask = max over the channels
Compute the Otsu threshold value for mask
mask = pixels where mask < threshold
error = discrete Laplace of in: apply convolution with [1,-2,1;-2,4,-2;1,-2,1]
MSE = the mean square value of the pixels in error that fall within mask, on a per-channel basis
If the image has more than one channel:
MSE = mean over MSE values for each channel
variance = MSE / 36