图片加噪声
图像噪声分类
1.加性噪声 f(x,y)=g(x,y)+n(x,y)
一般是图像传输信道噪声和CCD摄像机图像数字化过程中产生
2.乘性噪声 f(x,y)=g(x,y)*n(x,y)
一般由 胶片中颗粒 飞点扫描图像噪声 电视扫描光栅等原因造成
3.量化噪声
模拟到数字产生的差异 量化中的误差
图像噪声模型
1.高斯噪声 (Gaussian noise)
最广泛。传感器非正常环境下产生,电子电路中噪声。 高斯分布
2.脉冲噪声 (Impulsive noise)
双极脉冲:椒盐脉冲,尖峰噪声 散粒噪声
盐噪声:随机的白色像素点
胡椒噪声:随机黑色像素点
3.瑞利噪声 (Rayleigh noise)
4.伽马(爱尔兰)噪声 (Gamma noise)
5.指数噪声(Exponential noise)
6.均匀噪声(Uniform noise)
去噪效果评价算法
1.SNR [信噪比] 计算图像自身的信噪比 输入为一幅图片
2.PSNR [峰值信噪比] 计算两个图像之间的相似度 去噪后的图片和原图做比较
3.SSIM [结构相似性] 衡量两幅图像相似度
Code
import numpy as np
import copy
import cv2
import random
import skimage.metrics
import matplotlib.pyplot as plt
def GaussianNoise(srcImg,percent,sigma,means=0,greyscale=256):
"""
为灰度图像添加 高斯噪声
:param srcImg: 源图像
:param percent: 噪声百分比
:param sigma: 高斯的标准差
:param means=0: 高斯的均值 默认为0
:param greyscale=256: 灰度图像的度 默认为256
"""
(h,w)= srcImg.shape #源图像的长宽
NoiseImg=copy.deepcopy(srcImg) #复制源图像
places=random.sample(range(h*w),int(percent*w*h)) #随机按照百分比选择噪声点位置
for place in places:
x,y=place%w,place//w # 坐标
# f(x,y)=g(x,y)+n(x,y)
fxy=int(NoiseImg[x,y]+random.gauss(means,sigma))
# 范围修正
if fxy<0:
fxy=0
elif fxy>greyscale-1:
fxy=greyscale-1
NoiseImg[x,y]=fxy
return NoiseImg
def SaltPepperNoise(srcImg,percent,mode="BOTH",greyscale=256):
"""
对灰度图像添加椒盐噪声
:param srcImg: 源图片
:param percent: 百分比
:param mode="BOTH": 模式:BOTH:椒盐模式 SALT:盐 PEPPRR 椒
:param greyscale=256: 灰度图像的度 默认为256
"""
(h,w)= srcImg.shape #源图像的长宽
NoiseImg=copy.deepcopy(srcImg) #复制源图像
places=random.sample(range(h*w),int(percent*w*h)) #随机按照百分比选择噪声点位置
for place in places:
x,y=place%w,place//w # 坐标
if mode=="SALT": #加盐
NoiseImg[x,y]=255
elif mode=="PEPPER": #加胡椒
NoiseImg[x,y]=0
else: #
NoiseImg[x,y]=0 if random.random()<=0.5 else 255
return NoiseImg
def RayleighNoise(srcImg,scale,percent,greyscale=256):
"""
对灰度头像加上瑞利噪声
:param srcImg: 源图像
:param scale: 规模
:param percent:百分比
:param greyscale=256: 灰度图像的度 默认为256
"""
(h,w)= srcImg.shape #源图像的长宽
NoiseImg=copy.deepcopy(srcImg) #复制源图像
places=random.sample(range(h*w),int(percent*w*h)) #位置
Rayleighs=np.random.rayleigh(scale,int(percent*w*h)) #瑞利噪声
for i in range(int(percent*w*h)):
x,y=places[i]%w,places[i]//w # 坐标
fxy=NoiseImg[x,y]+int(Rayleighs[i]) #加上噪声
# 范围修正
if fxy<0:
fxy=0
elif fxy>greyscale-1:
fxy=greyscale-1
NoiseImg[x,y]=fxy
return NoiseImg
def GammaNoise(srcImg,k,theta,percent,greyscale=256):
"""
为灰度图像添加伽马噪声
:param srcImg: 源图像
:param k: 伽马分布参数k
:param theta: 伽马分布参数theta
:param percent: 百分比
:param greyscale=256: 灰度图像的度 默认为256
"""
(h,w)= srcImg.shape #源图像的长宽
NoiseImg=copy.deepcopy(srcImg) #复制源图像
places=random.sample(range(h*w),int(percent*w*h)) #位置
Gammas=np.random.gamma(k,theta,int(percent*w*h)) #伽马噪声
for i in range(int(percent*w*h)):
x,y=places[i]%w,places[i]//w # 坐标
fxy=NoiseImg[x,y]+int(Gammas[i]) #加上噪声
# 范围修正
if fxy<0:
fxy=0
elif fxy>greyscale-1:
fxy=greyscale-1
NoiseImg[x,y]=fxy
return NoiseImg
def ExponentialNoise(srcImg,beta,percent,greyscale=256):
"""
为灰度图像添加指数噪声
:param srcImg: 源图像
:param beta: 指数分布参数
:param percent: 百分比
:param greyscale=257: 灰度图像的度 默认为258
"""
(h,w)= srcImg.shape #源图像的长宽
NoiseImg=copy.deepcopy(srcImg) #复制源图像
places=random.sample(range(h*w),int(percent*w*h)) #位置
Expons=np.random.exponential(beta,int(percent*w*h)) #指数噪声
for i in range(int(percent*w*h)):
x,y=places[i]%w,places[i]//w # 坐标
fxy=NoiseImg[x,y]+int(Expons[i]) #加上噪声
# 范围修正
if fxy<0:
fxy=0
elif fxy>greyscale-1:
fxy=greyscale-1
NoiseImg[x,y]=fxy
return NoiseImg
def UniformNoise(srcImg,a,b,percent,greyscale=256):
"""
为灰度图像添加均匀噪声
:param srcImg: 源图像
:param a: 均匀分布参数a low
:param b: 均匀分布参数b high
:param percent: 百分比
:param greyscale=256:灰度图像的度 默认为256
"""
(h,w)= srcImg.shape #源图像的长宽
NoiseImg=copy.deepcopy(srcImg) #复制源图像
places=random.sample(range(h*w),int(percent*w*h)) #位置
unis=np.random.uniform(a,b,int(percent*w*h)) #均匀噪声
for i in range(int(percent*w*h)):
x,y=places[i]%w,places[i]//w # 坐标
fxy=NoiseImg[x,y]+int(unis[i]) #加上噪声
# 范围修正
if fxy<0:
fxy=0
elif fxy>greyscale-1:
fxy=greyscale-1
NoiseImg[x,y]=fxy
return NoiseImg
def cal_SNR(img):
"""
计算图像的SNR 使用方差法
:param img:
"""
snr=np.mean(img)/np.std(img)
return snr
def cal_PSNR(img,img_n):
"""
计算图像的PSNR 使用skimage 自带的方法
:param img: 原始图像
:param img_n: 噪声图像
"""
return skimage.metrics.peak_signal_noise_ratio(img, img_n, data_range=255)
def cal_SSIM(img,img_n):
"""
计算图像的SSIM 使用skimage 自带的方法
:param img: 原始图像
:param img_n: 噪声图像
"""
return skimage.metrics.structural_similarity(img, img_n, data_range=255)
if __name__ == "__main__":
img=cv2.imread('lenna.bmp',0)
# cv2.imshow("original",img)
#高斯噪声
g_per,means,sigma=1.0,0,50
gaussImg=GaussianNoise(img,g_per,sigma)
cv2.imshow("guass",gaussImg)
cv2.imwrite("./image/GuassNoise_per{}_sigma{}_means{}_lenna.jpg".format(g_per,sigma,means),gaussImg)
#椒盐噪声
s_per,mode=0.08,"BOTH"
spImg=SaltPepperNoise(img,s_per)
cv2.imshow("SaltPepper",spImg)
cv2.imwrite("./image/SaltPepperNoise_per{}_mode{}_lenna.jpg".format(s_per,mode),spImg)
#瑞利噪声
scale,r_per=60,0.5
rayImg=RayleighNoise(img,scale,r_per)
cv2.imshow("Rayleigh",rayImg)
cv2.imwrite("./image/RayleighNoise_per{}_scale{}_lenna.jpg".format(r_per,scale),rayImg)
#伽马噪声
k,theta,ga_per=30,4,0.5
gammaImg=GammaNoise(img,k,theta,ga_per)
cv2.imshow("Gamma",gammaImg)
cv2.imwrite("./image/GammaNoise_k{}_theta{}_per{}_lenna.jpg".format(k,theta,ga_per),gammaImg)
#指数噪声
beta,e_per=50,0.5
expImg=ExponentialNoise(img,beta,e_per)
cv2.imshow("Exponential",expImg)
cv2.imwrite("./image/Exponential_beta{}_per{}_lenna.jpg".format(beta,e_per),expImg)
# 均匀噪声
a,b,u_per=50,150,0.5
uniImg=UniformNoise(img,a,b,u_per)
cv2.imshow("Uniform",uniImg)
cv2.imwrite("./image/UniformNoise_a{}_b{}_per{}_lenna.jpg".format(a,b,u_per),uniImg)
print(cal_SNR(img))
print(cal_SNR(gaussImg))
print(cal_PSNR(img,gaussImg))
print(cal_SSIM(img,gaussImg))
cv2.waitKey()
fig, ax = plt.subplots(2,3,figsize = (40,30))
ax[0][0].imshow(gaussImg,cmap='gray')
ax[0][0].set_title('高斯噪声',fontsize=40)
ax[0][1].imshow(spImg,cmap='gray')
ax[0][1].set_title('椒盐噪声',fontsize=40)
ax[0][2].imshow(rayImg,cmap='gray')
ax[0][2].set_title('瑞利噪声',fontsize=40)
ax[1][0].imshow(gammaImg,cmap='gray')
ax[1][0].set_title('伽马噪声',fontsize=40)
ax[1][1].imshow(expImg,cmap='gray')
ax[1][1].set_title('指数噪声',fontsize=40)
ax[1][2].imshow(uniImg,cmap='gray')
ax[1][2].set_title('均匀噪声',fontsize=40)
2.5921675411422913
1.882286386646585
14.599118975174203
0.13775556598303823