1. 程式人生 > 實用技巧 >影象加噪及平滑處理

影象加噪及平滑處理

影象加噪

python的skimage庫可生成噪聲。

相關函式為

skimage.util.random_noise(image, mode, seed, clip, **kwargs)

mode為加噪型別,其中有’gaussian’為高斯噪聲, ‘s&p’為椒鹽噪聲等。

其餘詳細引數可參考官方文件如下

  1 random_noise(image, mode='gaussian', seed=None, clip=True, **kwargs)
  2     Function to add random noise of various types
to a floating-point image. 3 4 Parameters 5 ---------- 6 image : ndarray 7 Input image data. Will be converted to float. 8 mode : str, optional 9 One of the following strings, selecting the type of noise to add: 10 11 - 'gaussian' Gaussian-distributed additive noise. 12
- 'localvar' Gaussian-distributed additive noise, with specified 13 local variance at each point of `image`. 14 - 'poisson' Poisson-distributed noise generated from the data. 15 - 'salt' Replaces random pixels with 1. 16 - 'pepper' Replaces random pixels with 0 (for unsigned images) or 17
-1 (for signed images). 18 - 's&p' Replaces random pixels with either 1 or `low_val`, where 19 `low_val` is 0 for unsigned images or -1 for signed 20 images. 21 - 'speckle' Multiplicative noise using out = image + n*image, where 22 n is uniform noise with specified mean & variance. 23 seed : int, optional 24 If provided, this will set the random seed before generating noise, 25 for valid pseudo-random comparisons. 26 clip : bool, optional 27 If True (default), the output will be clipped after noise applied 28 for modes `'speckle'`, `'poisson'`, and `'gaussian'`. This is 29 needed to maintain the proper image data range. If False, clipping 30 is not applied, and the output may extend beyond the range [-1, 1]. 31 mean : float, optional 32 Mean of random distribution. Used in 'gaussian' and 'speckle'. 33 Default : 0. 34 var : float, optional 35 Variance of random distribution. Used in 'gaussian' and 'speckle'. 36 Note: variance = (standard deviation) ** 2. Default : 0.01 37 local_vars : ndarray, optional 38 Array of positive floats, same shape as `image`, defining the local 39 variance at every image point. Used in 'localvar'. 40 amount : float, optional 41 Proportion of image pixels to replace with noise on range [0, 1]. 42 Used in 'salt', 'pepper', and 'salt & pepper'. Default : 0.05 43 salt_vs_pepper : float, optional 44 Proportion of salt vs. pepper noise for 's&p' on range [0, 1]. 45 Higher values represent more salt. Default : 0.5 (equal amounts) 46 47 Returns 48 ------- 49 out : ndarray 50 Output floating-point image data on range [0, 1] or [-1, 1] if the 51 input `image` was unsigned or signed, respectively. 52 53 Notes 54 ----- 55 Speckle, Poisson, Localvar, and Gaussian noise may generate noise outside 56 the valid image range. The default is to clip (not alias) these values, 57 but they may be preserved by setting `clip=False`. Note that in this case 58 the output may contain values outside the ranges [0, 1] or [-1, 1]. 59 Use this option with care. 60 61 Because of the prevalence of exclusively positive floating-point images in 62 intermediate calculations, it is not possible to intuit if an input is 63 signed based on dtype alone. Instead, negative values are explicitly 64 searched for. Only if found does this function assume signed input. 65 Unexpected results only occur in rare, poorly exposes cases (e.g. if all 66 values are above 50 percent gray in a signed `image`). In this event, 67 manually scaling the input to the positive domain will solve the problem. 68 69 The Poisson distribution is only defined for positive integers. To apply 70 this noise type, the number of unique values in the image is found and 71 the next round power of two is used to scale up the floating-point result, 72 after which it is scaled back down to the floating-point image range. 73 74 To generate Poisson noise against a signed image, the signed image is 75 temporarily converted to an unsigned image in the floating point domain, 76 Poisson noise is generated, then it is returned to the original range. 77

具體實現

  1 import skimage
  2 import numpy as np
  3 import cv2 as cv
  4 
  5 img = cv.imread(r'Lena.png')
  6 imgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
  7 imgNoise = skimage.util.random_noise(imgGray,mode='s&p')
  8 cv.imshow('LenaGray',imgGray)
  9 cv.imshow('LenaNoise',imgNoise)
 10 
 11 cv.waitKey(0)
 12 cv.destroyAllWindows()

均值濾波

均值濾波是用當前畫素點周圍 N*N 個畫素值的均值來代替當前畫素值,並遍歷影象所有畫素點。

當採用的卷積核寬度和高度越大時,參與運算的畫素點數量越多,去噪效果越好,但是會造成影象失真越嚴重。

實現均值濾波的函式為

cv2.blur(src, ksize, anchor, borderType)

  • src:輸入影象
  • ksize:卷積核大小
  • anchor:錨點,預設值為(-1,-1)表示計算均值的點位於核的中心位置。一般情況下使用預設即可。
  • borderType:邊界樣式。一般情況下使用預設即可。

方框濾波

均值濾波是計算鄰域畫素值的均值,方框濾波可自由選擇濾波結果是計算鄰域畫素值之和的均值還是鄰域畫素之和。

實現方框濾波的函式是

cv2.boxFilter(src, ddepth, ksize, anchor, normalize, borderType)

  • src:輸入影象
  • ddepth:處理結果影象的深度,一般使用-1表示與原影象使用相同的影象深度
  • ksize:卷積核大小
  • anchor:錨點,預設值為(-1,-1)表示計算均值的點位於核的中心位置。一般情況下使用預設即可。
  • normalize:選擇濾波時是否歸一化,預設情況下為1。為1時表示歸一化處理,此時計算的時鄰域畫素值的均值;為0時不需要歸一化處理,此時計算的是鄰域畫素之和,但此時濾波得到的值很可能超過當前畫素值範圍最大值,從而被截斷為最大值而而得到一幅白色影象。
  • borderType:邊界樣式。一般情況下使用預設即可。

高斯濾波

上述均值濾波和方框濾波其鄰域每個畫素權重相等,而高斯濾波會將中心權重加大,遠離中心的權重偏小。同時高斯濾波在使用時核的寬度和高度可以不相同,但必須是奇數。每一種尺寸的卷積核的權重比例也可以不同。需要注意的是需對卷積核進行歸一化處理。

實現高斯濾波的函式時

cv2.GaussianBlur(src, ksize, sigmaX, sigmaY, borderType)

  • src:輸入影象
  • ksize:卷積核大小,必須為奇數
  • sigmaX:卷積核在水平方向的標準差,控制權重比例。
  • sigmaY:卷積核在垂直方向上的標準差,控制權重比例。
  • borderType:邊界樣式。一般情況下使用預設即可。

sigmaY和borderType是可選引數,sigmaX是必選引數,但可設定為0,此時會讓函式自己計算sigmaX具體值,sigmaY也可設定為0。在處理時可以將sigmaX和sigmaY都設定成0,此時函式會根據卷積核的寬度和高度計算得到兩個值。

中值濾波

中值濾波原理與均值濾波基本相同,只是計算的是鄰域畫素的中值而非均值。由於中值濾波需要對畫素值進行排序,故其需要的運算量較大,但在處理過程中噪聲成分很難被選上,故可有效地去除噪聲。

實現中值濾波的函式是

cv2.medianBlur(src, ksize)

  • src:輸入影象
  • ksize:卷積核大小。須是大於1的奇數

雙邊濾波

雙邊濾波在處理時不僅考慮距離資訊,還考慮色彩資訊,故其能夠有效保護影象的邊緣資訊。

實現雙邊濾波的函式是

cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace, borderType)

  • src:輸入影象
  • d:空間距離引數,表示以當前畫素值為中心點的直徑。
  • sigmaColor:處理時選取的顏色差值範圍。該值為0是濾波毫無意義,為255時指定直徑內所有畫素點參與運算。
  • sigmaSpace:座標空間的sigma值。該值越大說明有越多的點能夠參與濾波。
  • borderType:邊界樣式。一般情況下使用預設即可。

2D卷積

當我們想用特定的卷積核實現卷積操作時,可以使用2D卷積來完成。實現的函式是

cv2.filter2D(src, ddepth, kernel, anchor, delta, borderType)

  • src:輸入影象
  • ddepth:處理結果影象深度,一般使用-1表示與原影象使用相同的影象深度
  • kernel:卷積核
  • anchor:錨點,預設值為(-1,-1)表示計算均值的點位於核的中心位置。一般情況下使用預設即可。
  • delta:修正值。在濾波的結果上加上該值作為濾波修正結果
  • borderType:邊界樣式。一般情況下使用預設即可。

結果對比

  1 import matplotlib.pyplot as plt
  2 import numpy as np
  3 import cv2 as cv
  4 
  5 plt.rcParams['font.sans-serif'] = ['SimHei']  # 用來正常顯示中文標籤
  6 
  7 img = cv.imread(r'LenaNoise.png')
  8 # 均值濾波
  9 averFil = cv.blur(img, (5,5))
 10 averFil30 = cv.blur(img,(30,30))
 11 # 方框濾波
 12 boxFil = cv.boxFilter(img, -1, (2,2), normalize=0)
 13 boxFil5 = cv.boxFilter(img, -1, (5,5), normalize=0)
 14 # 高斯濾波
 15 GaussFil = cv.GaussianBlur(img, (5,5), 0, 0)
 16 # 中值濾波
 17 medianFil = cv.medianBlur(img, 3)
 18 # 雙邊濾波
 19 bilFil = cv.bilateralFilter(img, 9, 255, 255)
 20 # 2D卷積
 21 kernel = np.ones((9,9),np.float32)/81
 22 fil2D = cv.filter2D(img, -1, kernel)
 23 
 24 titles = ['original','均值濾波5*5','均值濾波30*30','方框濾波2*2','方框濾波5*5','高斯濾波','中值濾波','雙邊濾波','2D卷積']
 25 images = [img,averFil,averFil30,boxFil,boxFil5,GaussFil,medianFil,bilFil,fil2D]
 26 for i in range(9):
 27     plt.subplot(3,3,i+1), plt.imshow(images[i],'gray')
 28     plt.title(titles[i])
 29     plt.xticks([]), plt.yticks([])
 30 plt.show()

    上述結果除了展示結果對比之外,還驗證了濾波卷積核過大時會導致影象失真嚴重;方框濾波卷積核大小不當時使影象畫素值超過最大值255而導致影象變為白色。