图像加噪
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而导致图像变为白色。