Импульс, Гаусс и соль и перец шум с OpenCV



Я изучаю обработку изображений по знаменитому Гонсалесу "Цифровая обработка изображений" и говорю о восстановлении изображений много примеров сделано с помощью компьютерного шума (Гаусса, соли и перца и т. д.). В MATLAB для этого есть несколько встроенных функций. А как насчет OpenCV?

742   6  

6 ответов:

Насколько я знаю, нет удобных встроенных функций, как в Matlab. Но с помощью всего лишь нескольких строк кода Вы можете создать эти образы самостоятельно.

Например аддитивный гауссов шум:

Mat gaussian_noise = img.clone();
randn(gaussian_noise,128,30);

Соль и перец шум:

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);

Простая функция для добавления гауссова, сольно-перечного спекла и пуассоновского шума к изображению

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

Шум"соль и перец" можно добавить довольно простым способом, используя операции матрицы 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
#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
# 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')
Значения среднего и Сигмы могут быть изменены, чтобы вызвать определенное изменение в шуме, таком как гауссовский или перцово-солевой шум и т. д. Вы можете использовать randn или ранду по необходимости. Взгляните на документацию: https://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html#cv2.randu

Хотя нет встроенных функций, как в matlab "imnoise (image, noiseType, NoiseLevel)", но мы можем легко добавить необходимое количество случайных ценится импульсный шум или соль и перец в изображение вручную. 1. чтобы добавить случайный значимый импульсный шум.

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
  1. добавить соль и перец шум
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

"' Примечание: Для цветных изображений: сначала разбейте изображение на три или четыре канала в зависимости от входного изображения с помощью opencv функция: (B, G, R) = cv2.split (image)
(B, G, R, A) = cv2.split (image)
после расщепления выполните те же операции на всех каналах. в конце сольются все каналы: слияние = cv2.слияние([B, G, R]) возвращение слилось"' Надеюсь, это кому-то поможет.

Comments

    Ничего не найдено.