如何在Python中使用OpenCV给图像添加噪声(高斯噪声/椒盐噪声等)

70 投票
3 回答
265575 浏览
提问于 2025-04-18 01:51

我在想,Python的OpenCV或者其他图像处理库里有没有一些函数,可以给图片添加高斯噪声或者椒盐噪声?比如在MATLAB里就有很简单的函数可以做到这一点。

或者,怎么用Python和OpenCV给图片添加噪声呢?

3 个回答

12

你可以看看 cv2.randu() 或者 cv.randn(),它们和 matlab 的用法其实挺像的,我想。

我们来玩一玩吧 ;) :

import cv2
import numpy as np

>>> im = np.empty((5,5), np.uint8) # needs preallocated input image
>>> im
array([[248, 168,  58,   2,   1],  # uninitialized memory counts as random, too ?  fun ;) 
       [  0, 100,   2,   0, 101],
       [  0,   0, 106,   2,   0],
       [131,   2,   0,  90,   3],
       [  0, 100,   1,   0,  83]], dtype=uint8)
>>> im = np.zeros((5,5), np.uint8) # seriously now.
>>> im
array([[0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0]], dtype=uint8)
>>> cv2.randn(im,(0),(99))         # normal
array([[  0,  76,   0, 129,   0],
       [  0,   0,   0, 188,  27],
       [  0, 152,   0,   0,   0],
       [  0,   0, 134,  79,   0],
       [  0, 181,  36, 128,   0]], dtype=uint8)
>>> cv2.randu(im,(0),(99))         # uniform
array([[19, 53,  2, 86, 82],
       [86, 73, 40, 64, 78],
       [34, 20, 62, 80,  7],
       [24, 92, 37, 60, 72],
       [40, 12, 27, 33, 18]], dtype=uint8)

如果想把它应用到一张已有的图片上,只需要在你想要的范围内生成一些噪声,然后把这些噪声加到图片上就可以了:

img = ...
noise = ...

image = img + noise
26

我不知道Python的API里有没有什么方法。不过你可以用下面这段简单的代码给图片添加盐和胡椒噪声。

import numpy as np
import random
import cv2

def sp_noise(image,prob):
    '''
    Add salt and pepper noise to image
    prob: Probability of the noise
    '''
    output = np.zeros(image.shape,np.uint8)
    thres = 1 - prob 
    for i in range(image.shape[0]):
        for j in range(image.shape[1]):
            rdn = random.random()
            if rdn < prob:
                output[i][j] = 0
            elif rdn > thres:
                output[i][j] = 255
            else:
                output[i][j] = image[i][j]
    return output

image = cv2.imread('image.jpg',0) # Only for grayscale image
noise_img = sp_noise(image,0.05)
cv2.imwrite('sp_noise.jpg', noise_img)
130

这个函数可以在一张图片上添加高斯噪声、椒盐噪声、泊松噪声和斑点噪声。

Parameters
----------
image : ndarray
    Input image data. Will be converted to float.
mode : str
    One of the following strings, selecting the type of noise to add:

    'gauss'     Gaussian-distributed additive noise.
    'poisson'   Poisson-distributed noise generated from the data.
    's&p'       Replaces random pixels with 0 or 1.
    'speckle'   Multiplicative noise using out = image + n*image,where
                n is uniform noise with specified mean & variance.


import numpy as np
import os
import cv2
def noisy(noise_typ,image):
   if noise_typ == "gauss":
      row,col,ch= image.shape
      mean = 0
      var = 0.1
      sigma = var**0.5
      gauss = np.random.normal(mean,sigma,(row,col,ch))
      gauss = gauss.reshape(row,col,ch)
      noisy = image + gauss
      return noisy
   elif noise_typ == "s&p":
      row,col,ch = image.shape
      s_vs_p = 0.5
      amount = 0.004
      out = np.copy(image)
      # Salt mode
      num_salt = np.ceil(amount * image.size * s_vs_p)
      coords = [np.random.randint(0, i - 1, int(num_salt))
              for i in image.shape]
      out[coords] = 1

      # Pepper mode
      num_pepper = np.ceil(amount* image.size * (1. - s_vs_p))
      coords = [np.random.randint(0, i - 1, int(num_pepper))
              for i in image.shape]
      out[coords] = 0
      return out
  elif noise_typ == "poisson":
      vals = len(np.unique(image))
      vals = 2 ** np.ceil(np.log2(vals))
      noisy = np.random.poisson(image * vals) / float(vals)
      return noisy
  elif noise_typ =="speckle":
      row,col,ch = image.shape
      gauss = np.random.randn(row,col,ch)
      gauss = gauss.reshape(row,col,ch)        
      noisy = image + image * gauss
      return noisy

撰写回答