yu4u / noise2noise

An unofficial and partial Keras implementation of "Noise2Noise: Learning Image Restoration without Clean Data"
MIT License
1.07k stars 237 forks source link

Adding poisson noise model #14

Open shivamsaboo17 opened 5 years ago

shivamsaboo17 commented 5 years ago

The paper also describes training with poisson noise model. But it is a bit unclear how this can be achieved. I am following these instructions https://stackoverflow.com/questions/19289470/adding-poisson-noise-to-an-image# This is adding noise, but also changes the intensity of the image. Further in the paper although they say that poisson is signal dependent, they add noise with a fixed lambda = 30. To achieve this I am taking dividing the image(0-255) with 255 and multiply it with 30 and then sampling a poisson filter and adding it to my image. Am I going in the wrong direction?

yu4u commented 5 years ago

Well, as you mentioned, it is unclear how they created the Poisson noise. From the paper:

While zero-mean, it is harder to remove because it is signal-dependent. We use the L2 loss, and vary the noise magnitude λ ∈ [0, 50] during training

This is somewhat strange because the parameter lambda should be the intensities or RGB values of the images, thus can not be set as a parameter.

The author of the PyTorch implementation has a similar question: https://github.com/joeylitalien/noise2noise-pytorch/blob/790704a79f9a3620200260cd50ad2968f74522d3/src/datasets.py#L123-L130

shivamsaboo17 commented 5 years ago

@yu4u you are right. That's what I was thinking. I'll maybe contact the paper authors and hope to get a reply. Will update here if found anything useful.

yu4u commented 5 years ago

I'm afraid that they simply used np.random.poisson(lambda). So I compared the result of the above implementation and the noisy image in the paper (lambda=30). It seems that their results are noisier than the above implementation...

In terms of your implementation, the noise seems to be not zero-mean.

yu4u commented 5 years ago

By the way, I thought similar implementation as that of you.

img = img.astype(np.float)
sampled_lambda = np.random.uniform(min_lambda, max_lambda)
noise = (np.random.poisson(img) - img) * sampled_lambda / 100 # or 255?
noise_img = img + noise
noise_img = np.clip(noise_img, 0, 255).astype(np.uint8)

But the resulting images are less noisy...

victorca25 commented 5 years ago

Poisson noise is not additive it's applied, I believe that's what's wrong. That means that this step is not necessary:

noise_img = img + noise

And the last line should instead be:

noise_img = np.clip(noise, 0, 255).astype(np.uint8)

victorca25 commented 5 years ago

The scikit image code (https://github.com/scikit-image/scikit-image/blob/master/skimage/util/noise.py) has an implementation for Poisson noise that can be used as a reference:

elif mode == 'poisson':

Determine unique values in image & calculate the next power of two

  vals = len(np.unique(image))
  vals = 2 ** np.ceil(np.log2(vals))
   # Generating noise for each unique value in image.
  out = np.random.poisson(image * vals) / float(vals)