图像噪声是指存在于图像数据中的不必要的或多余的干扰信息。
很多时候将图像噪声看做多维随机过程,因而描述噪声的方法完全可以借用随机过程的描述,也就是用它的高斯分布函数和概率密度分布函数。
图像噪声的产生来自图像获取中的环境条件和传感元器件自身的质量,图像在传输过程中产生图像噪声的主要因素是所用的传输信道受到了噪声的污染。
在噪声的概念中,通常采用信噪比(Signal-Noise Rate, SNR)衡量图像噪声,单位为dB,SNR越小,噪声占比越大。为了方便,下面采用信号像素点的占比充当SNR,举个:假设一张图像的宽x高 = 10x10 ,共计100个像素,想让其中20个像素点变为噪声,其余80个像素点保留原值,则这里定义的SNR=80/100 = 0.8 。
高斯噪声是指噪声的概率密度函数(灰度值的统计直方图)服从高斯分布的一类噪声。通常是因为不良照明和高温引起的传感器噪声,一般在RGB图像中显现比较明显。
特别的,如果一个噪声,它的幅度分布服从高斯分布,而它的功率谱密度又是均匀分布的,则称它为高斯白噪声(了解即可)。
高斯分布(正态分布):
其中有means(平均值)和sigma(标准方差)两个参数。对于每个输入像素,我们可以通过与符合高斯分布的随机数相加, 得到输出像素:Pout = Pin + F(means,sigma).
给一副数字图像加上高斯噪声的处理顺序如下:
代码举例:
import numpy as np
import cv2
import random
def GaussianNoise(src,means,sigma,percetage):
NoiseImg=src
NoiseNum=int(percetage*src.shape[0]*src.shape[1])
for i in range(NoiseNum):
#每次取一个随机点
#把一张图片的像素用行和列表示的话,randX 代表随机生成的行,randY代表随机生成的列
#random.randint生成随机整数
randX=random.randint(0,src.shape[0]-1)
randY=random.randint(0,src.shape[1]-1)
#此处在原有像素灰度值上加上随机数
NoiseImg[randX,randY]=NoiseImg[randX,randY]+random.gauss(means,sigma)
#若灰度值小于0则强制为0,若灰度值大于255则强制为255
if NoiseImg[randX, randY]< 0:
NoiseImg[randX, randY]=0
elif NoiseImg[randX, randY]>255:
NoiseImg[randX, randY]=255
return NoiseImg
img = cv2.imread('path/lenna.png',0)
img1 = GaussianNoise(img,2,4,0.8)
‘’‘
这里的0.8代表的是噪声占比,而不是SNR。这步会改变原本img的值,也就是img=img1,所以为了对比,下面重新获取原始图片。
’‘’
img = cv2.imread('path/lenna.png',0)
cv2.imshow('source',img)
cv2.imshow('lenna_GaussianNoise',img1)
cv2.waitKey(0)
结果如下:
直观来说,高斯噪声主要是使图片变模糊了。
给一副数字图像加上椒盐噪声的处理顺序:
代码举例:
import numpy as np
import cv2
import random
def pepperSaltsNoise(src,percetage):
NoiseImg=src
NoiseNum=int(percetage*src.shape[0]*src.shape[1])
for i in range(NoiseNum): #返还一个迭代器
#每次取一个随机点
#把一张图片的像素用行和列表示的话,randX 代表随机生成的行,randY代表随机生成的列
#random.randint生成随机整数
randX=random.randint(0,src.shape[0]-1)
randY=random.randint(0,src.shape[1]-1)
#random.random生成随机浮点数,随意取到一个像素点有一半的可能是白点255,一半的可能是黑点0
if random.random()<=0.5:
NoiseImg[randX,randY]=0
else:
NoiseImg[randX,randY]=255
return NoiseImg
img=cv2.imread('path/lenna.png',0)
img1=pepperSaltsNoise(img,0.2)
img=cv2.imread('path/lenna.png',0)
cv2.imshow('source',img)
cv2.imshow('lenna_PepperandSalt',img1)
cv2.waitKey(0)
结果如下:
泊松噪声:符合泊松分布的噪声模型。
乘性噪声:一般由信道不理想引起,它们与信号的关系是相乘,信号在它在,信号不在他也就不在。
瑞利噪声:相比高斯噪声而言,其形状向右歪斜,这对于拟合某些歪斜直方图噪声很有用。瑞利噪声的实现可以借由平均噪声来实现。
伽马噪声:其分布服从了伽马曲线的分布。伽马噪声的实现,需要使用b个服从指数分布的噪声叠加而来。指数分布的噪声,可以使用均匀分布来实现。(b=1时为指数噪声,b>1时通过若干个指数噪声叠加,得到伽马噪声)
上述代码只是为了熟悉整个流程,如今封装好的第三方接口已经能满足很多需求,只需简单调用即可,如下:
import cv2
import numpy as np
from PIL import Image
from skimage import util
'''
def random_noise(image, mode='gaussian', seed=None, clip=True, **kwargs):
功能:为浮点型图片添加各种随机噪声
参数:
image:输入图片(将会被转换成浮点型),ndarray型
mode: 可选择,str型,表示要添加的噪声类型
gaussian:高斯噪声
localvar:高斯分布的加性噪声,在“图像”的每个点处具有指定的局部方差。
poisson:泊松噪声
salt:盐噪声,随机将像素值变成1
pepper:椒噪声,随机将像素值变成0或-1,取决于矩阵的值是否带符号
s&p:椒盐噪声
speckle:均匀噪声(均值mean方差variance),out=image+n*image
seed: 可选的,int型,如果选择的话,在生成噪声前会先设置随机种子以避免伪随机
clip: 可选的,bool型,如果是True,在添加均值,泊松以及高斯噪声后,会将图片的数据裁剪到合适范围内。如果谁False,则输出矩阵的值可能会超出[-1,1]
mean: 可选的,float型,高斯噪声和均值噪声中的mean参数,默认值=0
var: 可选的,float型,高斯噪声和均值噪声中的方差,默认值=0.01(注:不是标准差)
local_vars:可选的,ndarry型,用于定义每个像素点的局部方差,在localvar中使用
amount: 可选的,float型,是椒盐噪声所占比例,默认值=0.05
salt_vs_pepper:可选的,float型,椒盐噪声中椒盐比例,值越大表示盐噪声越多,默认值=0.5,即椒盐等量
返回值:ndarry型,且值在[0,1]或者[-1,1]之间,取决于是否是有符号数
'''
img = cv2.imread("path/lenna.png")
noise_gs_img=util.random_noise(img,mode='gaussian')
cv2.imshow("source", img)
cv2.imshow("lenna",noise_gs_img)
#cv2.imwrite('lenna_noise.png',noise_gs_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果如下:
图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。这里已经简单介绍过滤波和卷积,下面主要侧重滤波去噪。
滤波目的:
滤波要求:
对原图像从左到右从上到下的每个像素进行滤波,也就是进行卷积操作,最终得到处理后的图像,其卷积核如下所示:
当然,Kernel矩阵大小不一定是3x3,Kernel矩阵越大,均值滤波的效果就越明显。迭代次数也可以设置,多次迭代就会效果越来越好。
优点:算法简单,计算速度快;
缺点:不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊。
中值滤波跟均值滤波唯一不同是,不是用均值来替换中心每个像素,而是将周围像素和中心像素排序以后,取中值。如下:
由此,上图中的中心像素就由150变为了124。显然对消除椒盐噪声,中值滤波的效果要比均值滤波更好,因为椒盐噪声的取值通常为0和255,排序后要么为最小值要么为最大值,噪声点会被中值取代。
优点:抑制效果很好,画面的清晰度基本保持;
缺点:对高斯噪声的抑制效果不是很好。
最大最小值滤波是一种比较保守的图像处理手段,与中值滤波类似,首先要排序周围像素的像素值,然后将中心像素值与最小和最大像素值比较,如果比最小值小,则替换中心像素为最小值,如果中心像素比最大值大,则替换中心像素为最大值。如下:
最大最小值滤波在一定程度上也可以缓解椒盐噪声,但它相对保守,只是将中心像素替换为最大最小值,一般来说,对椒盐噪声的效果没有中值滤波好。
除此之外,还有双边滤波、限幅滤波、引导滤波等,它们用的比较少,这里就不展开了。
主要是增强图像中的有用信息,它可以是一个失真的过程,其目的是要改善图像的视觉效果,针对给定图像的应用场合。
图像增强可以分为两种:
主要是对每个像素点都做线性变换,从而对图像的对比度和亮度进行调整: y = a ∗ x + b . y=a*x+b. y=a∗x+b.
参数 a 影响图像的对比度,参数 b 影响图像的亮度,具体可分为以下几种情况:
a>1: 增强图像的对比度(图像像素之间的差值),图像看起来更加清晰;
a<1: 减小了图像的对比度, 图像看起来变模糊 ;
a=1 and b≠0:图像整体的灰度值上移或者下移,也就是图像整体变亮或者变暗,不会改变图像的对比度,b>0时图像变亮,b<0时图像变暗;
a=-1 and b=255:图像翻转。这里所说的翻转不是图像位置翻转,而是像素值翻转,例如,原像素为20,40,变换后为235,215,这是这里翻转的意思。
对处于某个感兴趣区域的x,将其对比度系数a增大或减小,从而增大或减小这个区域的对比度。(简单理解就是分段函数)
对数变换将图像的低灰度值部分扩展,将其高灰度值部分压缩,以达到强调图像低灰度部分的目的;同时可以很好的压缩像素值变化较大的图像的动态范围,目的是突出我们需要的细节。 y = c ∗ l o g ( 1 + x ) . y=c*log(1+x). y=c∗log(1+x).
它有利于过黑图像,但用的不是很多,因为它涉及到log运算,往往效率比较低。
幂律变换主要用于图像的校正,对漂白的图片或者是过黑的图片进行修正。 y = c ∗ x γ . y=c*x^{\gamma}. y=c∗xγ.
如下图,当 γ = 1 \gamma = 1 γ=1是,上式就变成了y=cx,当 γ < 1 \gamma <1 γ<1时,其图像类似于对数变换,适合处理过黑图像。
因此,根据 γ \gamma γ的大小,主要可分为以下两种情况:
γ > 1 \gamma > 1 γ>1: 处理漂白的图片,进行灰度级压缩;
γ < 1 \gamma < 1 γ<1: 处理过黑的图片,对比度增强,使得细节看的更加清楚。
领域处理包括直方图均衡化(详情见学习记录一)以及各种图像滤波方法,它们不再是按点进行处理,如滤波就是每次对卷积核大小的领域做操作,直方图均衡化对所有像素进行操作。