简体   繁体   中英

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

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

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 .

在此处输入图像描述
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):
在此处输入图像描述

binary_gauss (noise image after threshold - values are -1 , 0 , 1 ):
在此处输入图像描述

noisey_im (im + binary_gauss after threshold):
在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM