pybm3d icon indicating copy to clipboard operation
pybm3d copied to clipboard

Clip the output of run_bm3d_wrap before the type conversion.

Open fvdnabee opened this issue 5 years ago • 1 comments

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: astronaut_pybm3d_20-denoised-beforepatch After patch: astronaut_pybm3d_20-denoised-afterpatch

fvdnabee avatar Jun 20 '19 11:06 fvdnabee

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.

zaccharieramzi avatar Jun 20 '19 14:06 zaccharieramzi