圖像加噪
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而導致圖像變為白色。