Antoni Buades 提出指标 method noise 对数字图像降噪方法的性能进行了评价和比较。他首先针对几个被广泛使用的降噪算法计算并分析了降噪性能。同时,基于图像中所有像素的非局部平均,提出了全新的数字图像降噪算法 Non Local means Algorithm,并通过实验比较了新算法与常用的平滑滤波方法的性能。
defanisodiff(img,niter=1,kappa=50,gamma=0.1,step=(1.,1.),option=1,ploton=False): """ Anisotropic diffusion. Usage: imgout = anisodiff(im, niter, kappa, gamma, option) Arguments: img - input image niter - number of iterations kappa - conduction coefficient 20-100 ? gamma - max value of .25 for stability step - tuple, the distance between adjacent pixels in (y,x) option - 1 Perona Malik diffusion equation No 1 2 Perona Malik diffusion equation No 2 ploton - if True, the image will be plotted on every iteration Returns: imgout - diffused image. kappa controls conduction as a function of gradient. If kappa is low small intensity gradients are able to block conduction and hence diffusion across step edges. A large value reduces the influence of intensity gradients on conduction. gamma controls speed of diffusion (you usually want it at a maximum of 0.25) step is used to scale the gradients in case the spacing between adjacent pixels differs in the x and y axes Diffusion equation 1 favours high contrast edges over low contrast ones. Diffusion equation 2 favours wide regions over smaller ones. Reference: P. Perona and J. Malik. Scale-space and edge detection using ansotropic diffusion. IEEE Transactions on Pattern Analysis and Machine Intelligence, 12(7):629-639, July 1990. Original MATLAB code by Peter Kovesi School of Computer Science & Software Engineering The University of Western Australia pk @ csse uwa edu au <http://www.csse.uwa.edu.au> Translated to Python and optimised by Alistair Muldal Department of Pharmacology University of Oxford <alistair.muldal@pharm.ox.ac.uk> June 2000 original version. March 2002 corrected diffusion eqn No 2. July 2012 translated to Python April 2019 - Corrected for Python 3.7 - AvW """
# ...you could always diffuse each color channel independently if you # really want if img.ndim == 3: warnings.warn("Only grayscale images allowed, converting to 2D matrix") img = img.mean(2)
# conduction gradients (only need to compute one per dim!) if option == 1: gS = np.exp(-(deltaS/kappa)**2.)/step[0] gE = np.exp(-(deltaE/kappa)**2.)/step[1] elif option == 2: gS = 1./(1.+(deltaS/kappa)**2.)/step[0] gE = 1./(1.+(deltaE/kappa)**2.)/step[1]
# update matrices E = gE*deltaE S = gS*deltaS
# subtract a copy that has been shifted 'North/West' by one # pixel. don't as questions. just do it. trust me. NS[:] = S EW[:] = E NS[1:,:] -= S[:-1,:] EW[:,1:] -= E[:,:-1]
defanisodiff3(stack,niter=1,kappa=50,gamma=0.1,step=(1.,1.,1.),option=1,ploton=False): """ 3D Anisotropic diffusion. Usage: stackout = anisodiff(stack, niter, kappa, gamma, option) Arguments: stack - input stack niter - number of iterations kappa - conduction coefficient 20-100 ? gamma - max value of .25 for stability step - tuple, the distance between adjacent pixels in (z,y,x) option - 1 Perona Malik diffusion equation No 1 2 Perona Malik diffusion equation No 2 ploton - if True, the middle z-plane will be plotted on every iteration Returns: stackout - diffused stack. kappa controls conduction as a function of gradient. If kappa is low small intensity gradients are able to block conduction and hence diffusion across step edges. A large value reduces the influence of intensity gradients on conduction. gamma controls speed of diffusion (you usually want it at a maximum of 0.25) step is used to scale the gradients in case the spacing between adjacent pixels differs in the x,y and/or z axes Diffusion equation 1 favours high contrast edges over low contrast ones. Diffusion equation 2 favours wide regions over smaller ones. Reference: P. Perona and J. Malik. Scale-space and edge detection using ansotropic diffusion. IEEE Transactions on Pattern Analysis and Machine Intelligence, 12(7):629-639, July 1990. Original MATLAB code by Peter Kovesi School of Computer Science & Software Engineering The University of Western Australia pk @ csse uwa edu au <http://www.csse.uwa.edu.au> Translated to Python and optimised by Alistair Muldal Department of Pharmacology University of Oxford <alistair.muldal@pharm.ox.ac.uk> June 2000 original version. March 2002 corrected diffusion eqn No 2. July 2012 translated to Python """
# ...you could always diffuse each color channel independently if you # really want if stack.ndim == 4: warnings.warn("Only grayscale stacks allowed, converting to 3D matrix") stack = stack.mean(3)
# conduction gradients (only need to compute one per dim!) if option == 1: gD = np.exp(-(deltaD/kappa)**2.)/step[0] gS = np.exp(-(deltaS/kappa)**2.)/step[1] gE = np.exp(-(deltaE/kappa)**2.)/step[2] elif option == 2: gD = 1./(1.+(deltaD/kappa)**2.)/step[0] gS = 1./(1.+(deltaS/kappa)**2.)/step[1] gE = 1./(1.+(deltaE/kappa)**2.)/step[2]
# update matrices D = gD*deltaD E = gE*deltaE S = gS*deltaS
# subtract a copy that has been shifted 'Up/North/West' by one # pixel. don't as questions. just do it. trust me. UD[:] = D NS[:] = S EW[:] = E UD[1:,: ,: ] -= D[:-1,: ,: ] NS[: ,1:,: ] -= S[: ,:-1,: ] EW[: ,: ,1:] -= E[: ,: ,:-1]
import numpy as np import matplotlib.pyplot as plt
from skimage import data, img_as_float from skimage.restoration import denoise_nl_means, estimate_sigma from skimage.metrics import peak_signal_noise_ratio from skimage.util import random_noise
# estimate the noise standard deviation from the noisy image sigma_est = np.mean(estimate_sigma(noisy, channel_axis=-1)) print(f'estimated noise standard deviation = {sigma_est}')
from skimage.restoration import denoise_wavelet, estimate_sigma from skimage import data, img_as_float from skimage.util import random_noise from skimage.metrics import peak_signal_noise_ratio
original = img_as_float(data.chelsea()[100:250, 50:300])
# Estimate the average noise standard deviation across color channels. sigma_est = estimate_sigma(noisy, channel_axis=-1, average_sigmas=True) # Due to clipping in random_noise, the estimate will be a bit smaller than the # specified sigma. print(f'Estimated Gaussian noise standard deviation = {sigma_est}')
# VisuShrink is designed to eliminate noise with high probability, but this # results in a visually over-smooth appearance. Repeat, specifying a reduction # in the threshold by factors of 2 and 4. im_visushrink2 = denoise_wavelet( noisy, channel_axis=-1, convert2ycbcr=True, method='VisuShrink', mode='soft', sigma=sigma_est / 2, rescale_sigma=True, ) im_visushrink4 = denoise_wavelet( noisy, channel_axis=-1, convert2ycbcr=True, method='VisuShrink', mode='soft', sigma=sigma_est / 4, rescale_sigma=True, )
# Compute PSNR as an indication of image quality psnr_noisy = peak_signal_noise_ratio(original, noisy) psnr_bayes = peak_signal_noise_ratio(original, im_bayes) psnr_visushrink = peak_signal_noise_ratio(original, im_visushrink) psnr_visushrink2 = peak_signal_noise_ratio(original, im_visushrink2) psnr_visushrink4 = peak_signal_noise_ratio(original, im_visushrink4)