Home > OS >  Add Gaussian noise to a binary image knowing noise variance or SNR in python
Add Gaussian noise to a binary image knowing noise variance or SNR in python

Time:08-09

I am using python open cv for image restoration and in the first step, I have to add gaussian noise to my "binary" image. My image pixel values are integers that can take values 0 or 1. How can I add gaussian noise to my image knowing SNR or noise variance?

I came up with this piece of code which adds 15 percent noise to my image but I don't know if this noise is normal Gaussian and how I can find its variance and SNR.

def add_noise(im):
  im_noisy = im.copy()
  for i in range(len(im_noisy)):
    for j in range(len(im_noisy[0])):
      r = np.random.rand()
      if r < 0.15:
        im_noisy[i][j] = -im_noisy[i][j] 1    #(converts 0 to 1 and vice versa)
  return im_noisy

CodePudding user response:

Since the image is binary, the solution is not well defined - we have to select a threshold that above the threshold the noise is 1.
The Gaussian noise supposes to be symmetric, so pixels below the minus threshold are going to be -1.

We may define the threshold by number of sigma's (for example: above 2 sigma, the noise is 1, and below -2 sigma the noise is -1).
When selecting threshold of 2 sigma, statistically we expect that about 2.5% of total pixels are going to be 1 and 2.5% are going to be -1.

enter image description here
Select lower threshold for higher percentage.


  • Create random normal (Gaussian) distribution image with mean=0 and sigma=1:

     sigma = 1
     gauss = np.random.normal(0, sigma, im.shape)  # Create random normal (Gaussian) distribution image with mean=0 and sigma=1.
    
  • Convert to values to -1, 0, 1 - assume pixels value above 2 sigma are "1", below -2 sigma are -1 and other are "0" (2 sigma is an example, we may select other value):

     binary_gauss = (gauss > 2*sigma).astype(np.int8)
     binary_gauss[gauss < -2*sigma] = -1
    
  • After adding binary_gauss to im, clip the result to range [0, 1]:

     noisey_im = (im   binary_gauss).clip(0, 1)
    

Code sample (first part reads a sample image, and convert to binary):

import numpy as np
import cv2  # Used only for testing

im = cv2.imread('chelsea.png', cv2.IMREAD_GRAYSCALE)  # Read input image (for testing).
im = cv2.threshold(im, 0, 1, cv2.THRESH_OTSU)[1]  # Convert image to binary (for testing).
im = im.astype(np.int8)  # Convert to type int8 (8 bits singed)

sigma = 1
gauss = np.random.normal(0, sigma, im.shape)  # Create random normal (Gaussian) distribution image with mean=0 and sigma=1.
binary_gauss = (gauss > 2*sigma).astype(np.int8)  # Convert to binary - assume pixels with value above 2 sigmas are "1".
binary_gauss[gauss < -2*sigma] = -1 # Set all pixels below 2 sigma to "-1".

noisey_im = (im   binary_gauss).clip(0, 1)  # Add noise image, and clip the result ot [0, 1].
noisey_im = noisey_im.astype(np.uint8)  # Convert to type uint8

# Show images (for testing).
cv2.imshow('im', im*255)
cv2.imshow('binary_gauss', (binary_gauss 1).astype(np.uint8)*127)
cv2.imshow('noisey_im', noisey_im*255)
cv2.waitKey()
cv2.destroyAllWindows()

im (input image after converting to binary):
enter image description here

binary_gauss (noise image after threshold - values are -1, 0, 1):
enter image description here

noisey_im (im binary_gauss after threshold):
enter image description here

  • Related