J'étudie le traitement d'image sur le célèbre Gonzales "Traitement d'image numérique" et, en parlant de restauration d'images, de nombreux exemples sont réalisés avec du bruit généré par ordinateur (gaussien, sel et poivre, etc.). Dans MATLAB, il existe des fonctions intégrées pour le faire. Qu'en est-il d'OpenCV?
Autant que je sache, il n’existe pas de fonctions intégrées pratiques comme dans Matlab. Mais avec seulement quelques lignes de code, vous pouvez créer ces images vous-même.
Par exemple, bruit gaussien additif:
Mat gaussian_noise = img.clone();
randn(gaussian_noise,128,30);
Bruit sel et poivre:
Mat saltpepper_noise = Mat::zeros(img.rows, img.cols,CV_8U);
randu(saltpepper_noise,0,255);
Mat black = saltpepper_noise < 30;
Mat white = saltpepper_noise > 225;
Mat saltpepper_img = img.clone();
saltpepper_img.setTo(255,white);
saltpepper_img.setTo(0,black);
Fonction simple pour ajouter du bruit de gaussien, de poivre de sel et de poisson à une image
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,1,(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 = 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
Le bruit "Salt & Pepper" peut être ajouté d'une manière assez simple en utilisant les opérations de matrice NumPy.
def add_salt_and_pepper(gb, prob):
'''Adds "Salt & Pepper" noise to an image.
gb: should be one-channel image with pixels in [0, 1] range
prob: probability (threshold) that controls level of noise'''
rnd = np.random.Rand(gb.shape[0], gb.shape[1])
noisy = gb.copy()
noisy[rnd < prob] = 0
noisy[rnd > 1 - prob] = 1
return noisy
Il existe une fonction random_noise()
du paquet scikit-image. Il comporte plusieurs modèles de bruit intégrés, tels que gaussian
, s&p
(pour le bruit de sel et de poivre), possion
et speckle
.
Ci-dessous, je montre un exemple d'utilisation de cette méthode.
from PIL import Image
import numpy as np
from skimage.util import random_noise
im = Image.open("test.jpg")
# convert PIL Image to ndarray
im_arr = np.asarray(im)
# random_noise() method will convert image in [0, 255] to [0, 1.0],
# inherently it use np.random.normal() to create normal distribution
# and adds the generated noised back to image
noise_img = random_noise(im_arr, mode='gaussian', var=0.05**2)
noise_img = (255*noise_img).astype(np.uint8)
img = Image.fromarray(noise_img)
img.show()
Il existe également un package appelé imgaug qui est dédié à l’augmentation des images de différentes manières. Il fournit des augmentations de bruit gaussien, poissan et sel & poivre. Voici comment vous pouvez l'utiliser pour ajouter du bruit à l'image:
from PIL import Image
import numpy as np
from imgaug import augmenters as iaa
def main():
im = Image.open("bg_img.jpg")
im_arr = np.asarray(im)
# gaussian noise
# aug = iaa.AdditiveGaussianNoise(loc=0, scale=0.1*255)
# poisson noise
# aug = iaa.AdditivePoissonNoise(lam=10.0, per_channel=True)
# salt and pepper noise
aug = iaa.SaltAndPepper(p=0.05)
im_arr = aug.augment_image(im_arr)
im = Image.fromarray(im_arr).convert('RGB')
im.show()
if __== "__main__":
main()
# Adding noise to the image
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
img = cv2.imread('./fruit.png',0)
im = np.zeros(img.shape, np.uint8) # do not use original image it overwrites the image
mean = 0
sigma = 10
cv2.randn(im,mean,sigma) # create the random distribution
Fruit_Noise = cv2.add(img, im) # add the noise to the original image
plt.imshow(Fruit_Noise, cmap='gray')
Les valeurs de mean et sigma peuvent être modifiées pour provoquer un changement de bruit spécifique, tel que le bruit gaussien ou bruit poivre-sel, etc. Vous pouvez utiliser randn ou randu en fonction des besoins. Consultez la documentation: https://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html#cv2.randu
bien qu'il n'y ait pas de fonctions intégrées comme dans matlab "imnoise (image, noiseType, NoiseLevel)" mais on peut facilement ajouter la quantité requise aléatoire Bruit impulsif ou sel et poivre dans une image manuellement . 1. ajouter du bruit d'impulsion aléatoire.
import random as r
def addRvinGray(image,n): # add random valued impulse noise in grayscale
'''parameters:
image: type=numpy array. input image in which you want add noise.
n: noise level (in percentage)'''
k=0 # counter variable
ih=image.shape[0]
iw=image.shape[1]
noisypixels=(ih*iw*n)/100 # here we calculate the number of pixels to be altered.
for i in range(ih*iw):
if k<noisypixels:
image[r.randrange(0,ih)][r.randrange(0,iw)]=r.randrange(0,256) #access random pixel in the image gives random intensity (0-255)
k+=1
else:
break
return image
- ajouter du bruit de sel et de poivre
def addSaltGray(image,n): #add salt-&-pepper noise in grayscale image
k=0
salt=True
ih=image.shape[0]
iw=image.shape[1]
noisypixels=(ih*iw*n)/100
for i in range(ih*iw):
if k<noisypixels: #keep track of noise level
if salt==True:
image[r.randrange(0,ih)][r.randrange(0,iw)]=255
salt=False
else:
image[r.randrange(0,ih)][r.randrange(0,iw)]=0
salt=True
k+=1
else:
break
return image
'' 'Remarque: pour les images couleur: première image divisée en trois ou quatre canaux en fonction de l'image d'entrée en utilisant la fonction d'openv: (B, G, R) = cv2.split (image)
(B, G, R, A) = cv2.split (image)
après division, effectuez les mêmes opérations sur tous les canaux. à la fin, fusionnez tous les canaux: merged = cv2.merge ([B, G, R]) retourne fusionné '' ' J'espère que cela aidera quelqu'un.
#Adding noise
[m,n]=img.shape
saltpepper_noise=zeros((m, n));
saltpepper_noise=Rand(m,n); #creates a uniform random variable from 0 to 1
for i in range(0,m):
for j in range(0,n):
if saltpepper_noise[i,j]<=0.5:
saltpepper_noise[i,j]=0
else:
saltpepper_noise[i,j]=255