def main(): # Experiment specifications imagename = 'image_Lena512rgb.png' # Load noise-free image y = np.array(Image.open(imagename)) / 255 # Possible noise types to be generated 'gw', 'g1', 'g2', 'g3', 'g4', 'g1w', # 'g2w', 'g3w', 'g4w'. noise_type = 'g3' noise_var = 0.02 # Noise variance seed = 0 # seed for pseudorandom noise realization # Generate noise with given PSD noise, psd, kernel = get_experiment_noise(noise_type, noise_var, seed, y.shape) # N.B.: For the sake of simulating a more realistic acquisition scenario, # the generated noise is *not* circulant. Therefore there is a slight # discrepancy between PSD and the actual PSD computed from infinitely many # realizations of this noise with different seeds. # Generate noisy image corrupted by additive spatially correlated noise # with noise power spectrum PSD z = np.atleast_3d(y) + np.atleast_3d(noise) # Call BM3D With the default settings. y_est = bm3d_rgb(z, psd) # To include refiltering: # y_est = bm3d_rgb(z, psd, 'refilter'); # For other settings, use BM3DProfile. # profile = BM3DProfile(); # equivalent to profile = BM3DProfile('np'); # profile.gamma = 6; # redefine value of gamma parameter # y_est = bm3d_rgb(z, psd, profile); # Note: For white noise, you may instead of the PSD # also pass a standard deviation # y_est = bm3d_rgb(z, sqrt(noise_var)); # If the different channels have varying PSDs, you can supply a MxNx3 PSD or a list of 3 STDs: # y_est = bm3d_rgb(z, np.concatenate((psd1, psd2, psd3), 2)) # y_est = bm3d_rgb(z, [sigma1, sigma2, sigma3]) psnr = get_psnr(y, y_est) print("PSNR:", psnr) # PSNR ignoring 16-pixel wide borders (as used in the paper), due to refiltering potentially leaving artifacts # on the pixels near the boundary of the image when noise is not circulant psnr_cropped = get_cropped_psnr(y, y_est, [16, 16]) print("PSNR cropped:", psnr_cropped) # Ignore values outside range for display (or plt gives an error for multichannel input) y_est = np.minimum(np.maximum(y_est, 0), 1) z_rang = np.minimum(np.maximum(z, 0), 1) plt.title("y, z, y_est") plt.imshow(np.concatenate((y, np.squeeze(z_rang), y_est), axis=1)) plt.show()
def generate_red_img(noisy_img, pred_psd, gt_img): noisy_img = np.array(noisy_img) noisy_img = noisy_img / 255.0 gt_img = np.array(gt_img) gt_img = gt_img / 255.0 profile = BM3DProfile() profile.bs_ht = random.choice([2, 4, 8]) profile.transform_2d_wiener_name = random.choice(['dct', 'dst']) profile.bs_wiener = random.choice([4, 5, 6, 7, 8, 9, 10, 11, 12]) cspace = random.choice(['opp', 'YCbCr']) cff = random.uniform(1, 15) red_img = bm3d_rgb(noisy_img, cff * pred_psd[0], profile, colorspace=cspace) red_img = np.minimum(np.maximum(red_img, 0), 1) psnr = get_psnr(gt_img, red_img) red_img = Image.fromarray(np.uint8(red_img * 255.0)) return red_img, cff, profile.bs_ht, cspace, profile.transform_2d_wiener_name, profile.bs_wiener, psnr
def generate_red_img(noisy_img, pred_psd, gt_img): noisy_img = np.array(noisy_img) noisy_img = noisy_img / 255.0 gt_img = np.array(gt_img) gt_img = gt_img / 255.0 profile = BM3DProfile() profile.bs_ht = 4 profile.transform_2d_wiener_name = 'dst' profile.bs_wiener = choose_neighborhood cspace = 'YCbCr' cff = choose_cff red_img = bm3d_rgb(noisy_img, cff * pred_psd[0], profile, colorspace=cspace) red_img = np.minimum(np.maximum(red_img, 0), 1) psnr = get_psnr(gt_img, red_img) red_img = Image.fromarray(np.uint8(red_img * 255.0)) return red_img, cff, profile.bs_ht, cspace, profile.transform_2d_wiener_name, profile.bs_wiener, psnr
def main(t, sigma, args=None): # Experiment specifications #imagename = 'image_Lena512rgb.png' imagepath = args.path + '\\' imagename = imagepath + 'ref\\' + t + '_r.bmp' # Load noise-free image y = np.array(Image.open(imagename)) / 255 # Possible noise types to be generated 'gw', 'g1', 'g2', 'g3', 'g4', 'g1w', # 'g2w', 'g3w', 'g4w'. noise_type = 'gw' noise_var = (sigma / 255)**2 # Noise variance 25 std seed = 0 # seed for pseudorandom noise realization # Generate noise with given PSD noise, psd, kernel = get_experiment_noise(noise_type, noise_var, seed, y.shape) # N.B.: For the sake of simulating a more realistic acquisition scenario, # the generated noise is *not* circulant. Therefore there is a slight # discrepancy between PSD and the actual PSD computed from infinitely many # realizations of this noise with different seeds. # Generate noisy image corrupted by additive spatially correlated noise # with noise power spectrum PSD z = np.atleast_3d(y) + np.atleast_3d(noise) z_rang = np.minimum(np.maximum(z, 0), 1) noisyimagename = imagepath + 'noisy\\' + t + '_g.bmp' plt.imsave(noisyimagename, z_rang) z = np.array(Image.open(noisyimagename)) / 255 # Call BM3D With the default settings. y_est = bm3d_rgb(z, psd) # To include refiltering: # y_est = bm3d_rgb(z, psd, 'refilter'); # For other settings, use BM3DProfile. # profile = BM3DProfile(); # equivalent to profile = BM3DProfile('np'); # profile.gamma = 6; # redefine value of gamma parameter # y_est = bm3d_rgb(z, psd, profile); # Note: For white noise, you may instead of the PSD # also pass a standard deviation # y_est = bm3d_rgb(z, sqrt(noise_var)); # If the different channels have varying PSDs, you can supply a MxNx3 PSD or a list of 3 STDs: # y_est = bm3d_rgb(z, np.concatenate((psd1, psd2, psd3), 2)) # y_est = bm3d_rgb(z, [sigma1, sigma2, sigma3]) psnr = get_psnr(y, y_est) print("PSNR:", psnr) # PSNR ignoring 16-pixel wide borders (as used in the paper), due to refiltering potentially leaving artifacts # on the pixels near the boundary of the image when noise is not circulant psnr_cropped = get_cropped_psnr(y, y_est, [16, 16]) print("PSNR cropped:", psnr_cropped) # Ignore values outside range for display (or plt gives an error for multichannel input) y_est = np.minimum(np.maximum(y_est, 0), 1) z_rang = np.minimum(np.maximum(z, 0), 1) opath = 'bm3d_{0}.bmp'.format(t) plt.imsave(opath.format(t), y_est) y_est = np.array(Image.open(opath.format(t))) / 255 psnr = get_psnr(y, y_est) print("PSNR 2:", psnr) mse = ((y_est - y)**2).mean() * 255 print("MSE:", mse) #plt.imsave(imagepath+ 'noisy\\' + t + '_g.bmp', z_rang) # TEST CV2 PSNR try: from skimage.metrics import structural_similarity as compare_ssim except Exception: from skimage.measure import compare_ssim import cv2 opath = 'bm3d_{0}.bmp'.format(t) argref = imagename # path of noisy image d = cv2.imread(opath) tref = cv2.imread(argref) (score, diff) = compare_ssim(tref, d, full=True, multichannel=True) psnr2 = cv2.PSNR(tref, d) print('#######################') print('CV2 PSNR, SSIM: {:.2f}, {:.2f}'.format(psnr2, score)) print('#######################') print('') #plt.title("y, z, y_est") #plt.imshow(np.concatenate((y, np.squeeze(z_rang), y_est), axis=1)) #plt.show() return psnr, mse
seed = 0 # seed for pseudorandom noise realization noise, psd, kernel = get_experiment_noise(noise_type, noise_var, seed, y.shape) noise_cube, psd_cube, kernel_cube = get_experiment_noise( noise_type, noise_cube_var, seed, y_cube.shape) # Generate noisy image corrupted by additive spatially correlated noise # with noise power spectrum PSD z = (np.atleast_3d(y) + np.atleast_3d(noise)) # Call BM3D With the default settings. y_est = bm3d(z, psd) # Note: For white noise, you may instead of the PSD # also pass a standard deviation # y_est = bm3d(z, sqrt(noise_var)); psnr = get_psnr(y, y_est) print("PSNR:", psnr) # PSNR ignoring 16-pixel wide borders (as used in the paper), due to refiltering potentially leaving artifacts # on the pixels near the boundary of the image when noise is not circulant psnr_cropped = get_cropped_psnr(y, y_est, [16, 16]) print("PSNR cropped:", psnr_cropped) # Ignore values outside range for display (or plt gives an error for multichannel input) y_est = np.minimum(np.maximum(y_est, 0), 1) z_rang = np.squeeze(np.minimum(np.maximum(z, 0), 1)) plt.title("y, z, y_est") plt.imshow(np.concatenate((y, z_rang, y_est), axis=1), cmap='gray') plt.show()
def main(): # Experiment specifications # The multichannel example data is acquired from: http://www.bic.mni.mcgill.ca/brainweb/ # (C.A. Cocosco, V. Kollokian, R.K.-S. Kwan, A.C. Evans, # "BrainWeb: Online Interface to a 3D MRI Simulated Brain Database" # NeuroImage, vol.5, no.4, part 2/4, S425, 1997 # -- Proceedings of 3rd International Conference on Functional Mapping of the Human Brain, Copenhagen, May 1997. data_name = 'brainslice.mat' table_name = 'slice_sample' # Load noise-free image # Data should be in same shape as with Image.open, but channel count can be any (M x N x channels) # Noise-free data should be between 0 and 1. y = loadmat(data_name)[table_name] # Possible noise types to be generated 'gw', 'g1', 'g2', 'g3', 'g4', 'g1w', # 'g2w', 'g3w', 'g4w'. noise_type = 'g2' noise_var = 0.02 # Noise variance seed = 0 # seed for pseudorandom noise realization # Generate noise with given PSD noise, psd, kernel = get_experiment_noise(noise_type, noise_var, seed, y.shape) # N.B.: For the sake of simulating a more realistic acquisition scenario, # the generated noise is *not* circulant. Therefore there is a slight # discrepancy between PSD and the actual PSD computed from infinitely many # realizations of this noise with different seeds. # Generate noisy image corrupted by additive spatially correlated noise # with noise power spectrum PSD z = np.atleast_3d(y) + np.atleast_3d(noise) # Call BM3D With the default settings. # The call is identical to that of the grayscale BM3D. y_est = bm3d(z, psd) # To include refiltering: # y_est = bm3d(z, psd, 'refilter'); # For other settings, use BM3DProfile. # profile = BM3DProfile(); # equivalent to profile = BM3DProfile('np'); # profile.gamma = 6; # redefine value of gamma parameter # y_est = bm3d(z, psd, profile); # Note: For white noise, you may instead of the PSD # also pass a standard deviation # y_est = bm3d(z, sqrt(noise_var)); # Instead of passing a singular PSD, you may also pass equal number of PSDs to the channels: # y_est = bm3d(z, np.concatenate((psd1, psd2, psd3, psd4, psd5), 2)) # y_est = bm3d(z, [sigma1, sigma2, sigma3, sigma4, sigma5]) psnr = get_psnr(y, y_est) print("PSNR:", psnr) # PSNR ignoring 16-pixel wide borders (as used in the paper), due to refiltering potentially leaving artifacts # on the pixels near the boundary of the image when noise is not circulant psnr_cropped = get_cropped_psnr(y, y_est, [16, 16]) print("PSNR cropped:", psnr_cropped) # Ignore values outside range for display (or plt gives an error for multichannel input) y_est = np.minimum(np.maximum(y_est, 0), 1) z_rang = np.minimum(np.maximum(z, 0), 1) plt.title("y, z, y_est") disp_mat = np.concatenate([ np.concatenate( (y[:, :, i], np.squeeze(z_rang[:, :, i]), y_est[:, :, i]), axis=1) for i in range(y_est.shape[2]) ], axis=0) plt.imshow(disp_mat) plt.show()
def main(): # Experiment specifications imagename = 'cameraman256.png' # Load noise-free image y = np.array(Image.open(imagename)) / 255 # Generate blurry + noisy image experiment_number = 3 if experiment_number == 1: sigma = np.sqrt(2) / 255 v = np.zeros((15, 15)) for x1 in range(-7, 8, 1): for x2 in range(-7, 8, 1): v[x1 + 7, x2 + 7] = 1 / (x1 ** 2 + x2 ** 2 + 1) v = v / np.sum(v) elif experiment_number == 2: sigma = np.sqrt(8) / 255 s1 = 0 v = np.zeros((15, 15)) for a1 in range(-7, 8, 1): s1 = s1 + 1 s2 = 0 for a2 in range(-7, 8, 1): s2 = s2 + 1 v[s1-1, s2-1] = 1 / (a1 ** 2 + a2 ** 2 + 1) elif experiment_number == 3: bsnr = 40 sigma = -1 # if "sigma=-1", then the value of sigma deps on the BSNR v = np.ones((9, 9)) v = v / np.sum(v) elif experiment_number == 4: sigma = 7 / 255 v = np.atleast_2d(np.array([1, 4, 6, 4, 1])).T @ np.atleast_2d(np.array([1, 4, 6, 4, 1])) v = v / np.sum(v) elif experiment_number == 5: sigma = 2 / 255 v = gaussian_kernel((25, 25), 1.6) else: # 6 + sigma = 8 / 255 v = gaussian_kernel((25, 25), 0.4) y_blur = correlate(np.atleast_3d(y), np.atleast_3d(v), mode='wrap') # performs blurring (by circular convolution) if sigma == -1: # check whether to use BSNR in order to define value of sigma sigma = np.sqrt(np.linalg.norm(np.ravel(y_blur - np.mean(y_blur)), 2) ** 2 / (y.shape[0] * y.shape[1] * 10 ** (bsnr / 10))) z = y_blur + sigma * np.random.normal(size=y_blur.shape) # Call BM3D deblurring With the default settings. y_est = bm3d_deblurring(z, sigma, v) # To include refiltering: # y_est = bm3d_deblurring(z, sigma, v, 'refilter'); # For other settings, use BM3DProfile. # profile = BM3DProfile(); # equivalent to profile = BM3DProfile('np'); # profile.gamma = 6; # redefine value of gamma parameter # y_est = bm3d_deblurring(z, sigma, v, profile); # Note: You may also pass a PSD # y_est = bm3d_deblurring(z, psd, v); psnr = get_psnr(y, y_est) print("PSNR:", psnr) # PSNR ignoring 16-pixel wide borders (as used in the paper), due to refiltering potentially leaving artifacts # on the pixels near the boundary of the image when noise is not circulant psnr_cropped = get_cropped_psnr(y, y_est, [16, 16]) print("PSNR cropped:", psnr_cropped) # Ignore values outside range for display (or plt gives an error for multichannel input) y_est = np.minimum(np.maximum(y_est, 0), 1) z_rang = np.minimum(np.maximum(z, 0), 1) plt.title("y, z, y_est") plt.imshow(np.concatenate((y, np.squeeze(z_rang), y_est), axis=1), cmap='gray') plt.show()