pybm3d
pybm3d copied to clipboard
Clip the output of run_bm3d_wrap before the type conversion.
The type conversion of the output of run_bm3d_wrap from np.float32 to the input dtype leads to numeric overflow in the output when the input dtype is uint8. It appears the author has anticipated this overflow, but the clipping happens after the conversion (i.e. when the overflow has already happened).
I included two images of the denoised output for the following script before and after the patch to bm3d.pyx.
import numpy as np
import skimage.data
from skimage.measure import compare_psnr
from skimage import io
import pybm3d
noise_std_dev = 20
img = skimage.data.astronaut()
noise = np.random.normal(scale=noise_std_dev,
size=img.shape).astype(np.int8)
assert img.dtype == np.uint8
noisy_img = (img.astype(np.int16) + noise).clip(0, 255).astype(np.uint8)
out = pybm3d.bm3d.bm3d(noisy_img, noise_std_dev)
noise_psnr = compare_psnr(img, noisy_img)
out_psnr = compare_psnr(img, out)
print("PSNR of noisy image: ", noise_psnr)
print("PSNR of reconstructed image: ", out_psnr)
io.imsave(fname='/tmp/astronaut_pybm3d_{}-denoised.png'.format(noise_std_dev), arr=out)
io.imsave(fname='/tmp/astronaut_pybm3d_{}.png'.format(noise_std_dev), arr=noisy_img)
Before patch:
After patch:
Isn't it a bit weird to clip the values after adding the noise?
I understand it's because you want to keep it in the RGB space of [0, 255] but it then makes the noise not gaussian anymore.