一、实验目的和要求
- 理解邻域运算的实现原理。
- 理解图像平滑滤波的用途与实现方法。
- 理解图像锐化滤波的用途与实现方法。
二、实验内容和步骤
1. 图像加噪声函数列举如下,选择调用相关函数,编写Python程序完成下列图像处理要求:
(1)train1.jpg图像加入高斯噪声,然后分别采用3╳3滤波核和7╳7滤波核进行均值滤波,将原图像、添加噪声的图像、不同滤波核滤波后的图像放置在同一绘图区域并保存。
(2)train1.jpg图像加入高斯噪声,分别采用5╳5滤波核的高斯滤波和均值滤波,将原图像、添加噪声的图像、不同滤波算法滤波后的图像放置在同一绘图区域并保存。
(3)lena.jpg图像添加椒盐噪声,变换阈值邻域平滑滤波的阈值参数,比较均值滤波和阈值邻域平滑滤波的效果,结果显示在同一绘图区域。
(4)为train1.jpg图像加入椒盐噪声,分别采用5╳5滤波核的中值滤波和均值滤波,将原图像、添加噪声的图像、不同滤波算法滤波后的图像放置在同一绘图区域并保存。
定义高斯噪声函数
def addGaussianNoise(src,mu,sigma): NoiseImg=src.copy() NoiseImg=NoiseImg/NoiseImg.max() rows,cols=NoiseImg.shape[:2] for i in range(rows): for j in range(cols): #python里使用random.gauss函数加高斯噪声 NoiseImg[i,j]=NoiseImg[i,j]+random.gauss(mu,sigma) if NoiseImg[i,j]< 0: NoiseImg[i,j]=0 elif NoiseImg[i,j]>1: NoiseImg[i,j]=1 NoiseImg=np.uint8(NoiseImg*255) return NoiseImg
- src.copy() :在图像处理中,src.copy() 通常用于创建一个原始图像 src 的副本,并将其存储在另一个变量中,以便在不改变原始图像的情况下对其进行修改或添加噪声。
- NoiseImg = NoiseImg / NoiseImg.max() :在图像处理中,对图像进行归一化处理是一种常见的预处理步骤。NoiseImg = NoiseImg / NoiseImg.max() 这行代码就是对图像 NoiseImg 进行归一化,将图像的像素值缩放到 0 到 1 的范围内。具体来说,NoiseImg.max() 计算了图像中所有像素值的最大值。然后,通过将每个像素值除以这个最大值,你确保了图像中所有像素的新值都在 0 到 1 之间。
- rows, cols = NoiseImg.shape[:2] :NoiseImg.shape[:2] 是一个切片操作,它获取 NoiseImg.shape 元组的前两个元素,即 rows 和 cols。这样,rows 和 cols 分别被赋值为图像的行数和列数。
- NoiseImg[i, j] = NoiseImg[i, j] + random.gauss(mu, sigma):将一个符合高斯分布的随机数加到 NoiseImg 图像在坐标 (i, j) 处的像素值上。
- if NoiseImg[i,j]< 0:
NoiseImg[i,j]=0
elif NoiseImg[i,j]>1:
NoiseImg[i,j]=1
如果添加噪声后,像素值小于0,那么将这个像素值设置为0。这是为了确保像素值不会低于有效范围的下限。
如果像素值在添加噪声后大于1,那么将这个像素值设置为1。这是为了确保像素值不会高于有效范围的上限。
- NoiseImg = np.uint8(NoiseImg * 255) :在图像处理中,当你有一个归一化后的图像数组,其像素值范围在0到1之间,并且你想要将这个数组转换回一个常见的8位无符号整数(uint8)格式,以便能够直接显示或保存为图像文件时,你需要将像素值重新缩放回0到255的范围。这是因为大多数图像处理和显示系统都使用8位来表示每个像素的强度(对于灰度图像)或颜色分量(对于彩色图像)。代码 NoiseImg = np.uint8(NoiseImg * 255) 完成了这个转换。这里,NoiseImg * 255 将每个像素值乘以255,将其从0-1的范围转换到0-255的范围。然后,np.uint8 函数将这个缩放后的浮点数数组转换为8位无符号整数数组。
定义图像添加椒盐噪声
def addSaltAndPepper(src, percentage): NoiseImg = src.copy() #在此要使用copy函数,否则src和主程序中的img都会跟着改变 NoiseNum = int(percentage * src.shape[0] * src.shape[1]) #NoiseNum代表了基于给定percentage的图像中的随机像素数 for i in range(NoiseNum): randX = random.randint(0, src.shape[0] - 1) #产生[0, src.shape[0] - 1]之间随机整数 randY = random.randint(0, src.shape[1] - 1) if random.randint(0, 1) == 0: NoiseImg[randX, randY] = 0 else: NoiseImg[randX, randY] = 255 return NoiseImg
- randX = random.randint(0, src.shape[0] - 1) 和 randY = random.randint(0, src.shape[1] - 1):这两行代码分别生成两个随机整数randX和randY,它们分别代表图像src中的随机行(高度)和列(宽度)索引。注意,索引是从0开始的,并且需要减去1以确保随机坐标不会超出图像的边界。
- if random.randint(0, 1) == 0: NoiseImg[randX, randY] = 0:这两行代码检查另一个随机生成的整数(只能是0或1)是否为0。如果是0,则将NoiseImg图像在(randX, randY)位置的像素值设置为0(黑色)。
- else: NoiseImg[randX, randY] = 255:如果上面的随机整数不是0(即为1),则将NoiseImg图像在(randX, randY)位置的像素值设置为255(白色)。
定义阈值均值平滑滤波
目的:是通过比较原始噪声图像和其模糊版本来创建一个阈值化图像,以突出显示那些与周围像素显著不同的像素
#阈值均值平滑滤波 def threshAverFilter(imgNoise,T): imgAver=cv2.blur(imgNoise,(5,5))#blur函数对imgNoise进行模糊处理 row,col=imgNoise.shape imgThresh=np.zeros((row,col)) for i in range(row): for j in range(col): if np.abs(imgNoise[i,j]-imgAver[i,j])>T: imgThresh[i,j]=imgAver[i,j] else: imgThresh[i,j]=imgNoise[i,j] return imgThresh
(1)train1.jpg图像加入高斯噪声,然后分别采用3╳3滤波核和7╳7滤波核进行均值滤波,将原图像、添加噪声的图像、不同滤波核滤波后的图像放置在同一绘图区域并保存。
# 均值滤波处理高斯噪声 import matplotlib.pyplot as plt import cv2 import numpy as np import random # from ImageAddNoise import * plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签 plt.rcParams['axes.unicode_minus']=False #用来正常显示负 img = cv2.imread(r"C:\Users\Administrator\Desktop\photo\train1.jpg",0) ImgGuassNoise = addGaussianNoise(img,0,0.1) #添加0均值,0.1标准差的高斯分布噪声 imgAver3=cv2.blur(ImgGuassNoise,(3,3)) imgAver7=cv2.blur(ImgGuassNoise,(7,7)) plt.figure(figsize=(8,5)) plt.subplot(221) plt.imshow(img,cmap='gray')# 使用灰度颜色映射显示图像 plt.title("原图") plt.axis('off') #不显示坐标轴 plt.subplot(222) plt.imshow(ImgGuassNoise,cmap='gray') plt.title("加高斯噪声图像") plt.axis('off') #不显示坐标轴 plt.subplot(223) plt.imshow(imgAver3,cmap='gray')# 使用灰度颜色映射显示图像 plt.title("3x3均值滤波") plt.axis('off') #不显示坐标轴 plt.subplot(224) plt.imshow(imgAver7,cmap='gray')# 使用灰度颜色映射显示图像 plt.title("7x7均值滤波") plt.axis('off') #不显示坐标轴 plt.savefig("sy3-1-1-blur.jpg") plt.show()
运行结果:
(2)train1.jpg图像加入高斯噪声,分别采用5╳5滤波核的高斯滤波和均值滤波,将原图像、添加噪声的图像、不同滤波算法滤波后的图像放置在同一绘图区域并保存。
# 高斯滤波处理高斯噪声 import matplotlib.pyplot as plt import cv2 import numpy as np import random # from ImageAddNoise import * plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签 plt.rcParams['axes.unicode_minus']=False #用来正常显示负 img = cv2.imread(r"C:\Users\Administrator\Desktop\图像素材\train1.jpg",0) ImgGuassNoise = addGaussianNoise(img,0,0.1) #添加0均值,0.1标准差的高斯分布噪声 imgAverG=cv2.GaussianBlur(ImgGuassNoise,(5,5),1) imgAver5=cv2.blur(ImgGuassNoise,(5,5)) plt.figure(figsize=(12,5)) plt.subplot(221) plt.imshow(img,cmap='gray') plt.title("原图") plt.axis('off') #不显示坐标轴 plt.subplot(222) plt.imshow(ImgGuassNoise,cmap='gray') plt.title("加高斯噪声图像") plt.axis('off') #不显示坐标轴 plt.subplot(223) plt.imshow(imgAverG,cmap='gray') plt.title("5x5高斯滤波") plt.axis('off') #不显示坐标轴 plt.subplot(224) plt.imshow(imgAver5,cmap='gray') plt.title("5x5均值滤波") plt.axis('off') #不显示坐标轴 plt.show() plt.savefig(r"C:\Users\Administrator\Desktop\sy3-1-2-gaussianBlur.jpg")
运行结果:
(3)lena.jpg图像添加椒盐噪声,变换阈值邻域平滑滤波的阈值参数,比较均值滤波和阈值邻域平滑滤波的效果,结果显示在同一绘图区域。
img = cv2.imread(r"C:\Users\Administrator\Desktop\photo\lena.jpg",0) imgNoise=addSaltAndPepper(img, 0.1) imgAver=cv2.blur(imgNoise,(5,5)) imgThresh1=threshAverFilter(imgNoise,0) imgThresh2=threshAverFilter(imgNoise,30) imgThresh3=threshAverFilter(imgNoise,255) plt.figure(figsize=(12,7)) plt.subplot(231) plt.imshow(img,cmap='gray') plt.title("原图") plt.axis('off') #不显示坐标轴 plt.subplot(232) plt.imshow(imgNoise,cmap='gray') plt.title("加椒盐噪声图像") plt.axis('off') #不显示坐标轴 plt.subplot(233) plt.imshow(imgAver,cmap='gray') plt.title("5x5均值滤波") plt.axis('off') #不显示坐标轴 plt.subplot(234) plt.imshow(imgThresh1,cmap='gray') plt.title("T=0的阈值邻域平滑滤波") plt.axis('off') #不显示坐标轴 plt.subplot(235) plt.imshow(imgThresh2,cmap='gray') plt.title("T=30的阈值邻域平滑滤波") plt.axis('off') #不显示坐标轴 plt.subplot(236) plt.imshow(imgThresh3,cmap='gray') plt.title("T=255的阈值邻域平滑滤波") plt.axis('off') #不显示坐标轴 plt.savefig(r"C:\Users\Administrator\Desktopsy3-1-3-Thresh.jpg") plt.show()
运行结果:
(4)为train1.jpg图像加入椒盐噪声,分别采用5╳5滤波核的中值滤波和均值滤波,将原图像、添加噪声的图像、不同滤波算法滤波后的图像放置在同一绘图区域并保存。
# 中值滤波处理高斯噪声 img = cv2.imread(r"C:\Users\Administrator\Desktop\photo\train1.jpg",0) imgNoise = addSaltAndPepper(img, 0.1) #添加10%比例的椒盐噪声 imgAver=cv2.blur(imgNoise,(5,5)) #对加入噪声的图像使用5X5大小滤波核的均值滤波 imgMedian=cv2.medianBlur(imgNoise,5) plt.figure(figsize=(10,6)) plt.subplot(221) plt.imshow(img,cmap='gray') plt.title("原图像") plt.axis('off') #不显示坐标轴 plt.subplot(222) plt.imshow(imgNoise,cmap='gray') plt.title("加椒盐噪声图像") plt.axis('off') #不显示坐标轴 plt.subplot(223) plt.imshow(imgAver,cmap='gray') plt.title("5x5均值滤波") plt.axis('off') #不显示坐标轴 plt.subplot(224) plt.imshow(imgMedian,cmap='gray') plt.title("5x5中值滤波") plt.axis('off') #不显示坐标轴 plt.savefig(r"C:\Users\Administrator\Desktop\sy3-1-4Median.jpg") plt.show()
运行结果:
2.对图像moon.jpg调用函数cv2.filter2D( ),分别添加Laplacian锐化算子和增强算子,在同一绘图区域显示原图像和锐化、增强后的图像,并保存。
import matplotlib.pyplot as plt import cv2 import numpy as np #get_ipython().run_line_magic('matplotlib', 'inline') plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签 plt.rcParams['axes.unicode_minus']=False #用来正常显示负 img=cv2.imread(r"C:\Users\Administrator\Desktop\photo\moon.jpg",0) #拉普拉斯锐化: fi1=np.array([[0,1,0],[1,-4,1],[0,1,0]]) fi2=np.array([[0,-1,0],[-1,5,-1],[0,-1,0]]) #使用opencv的卷积函数 滤波去噪声 img1 = cv2.filter2D(img,-1,fi1,borderType=cv2.BORDER_DEFAULT) #-1 表示图像输出类型和输入相同 img2 = cv2.filter2D(img,-1,fi2,borderType=cv2.BORDER_DEFAULT) #输出对应的图片 plt.figure(figsize=(12,6)) plt.subplot(131) plt.imshow(img,vmin=0,vmax=255,cmap=plt.cm.gray)#设置内部的坐标,以及灰度的最大值和最小值 plt.title("原图像") plt.axis('off') plt.subplot(132) plt.imshow(img1,vmin=0,vmax=255,cmap=plt.cm.gray) plt.title("拉普拉斯滤波图像") plt.axis('off') plt.subplot(133) plt.imshow(img2,vmin=0,vmax=255,cmap=plt.cm.gray) plt.title("拉普拉斯锐化增强图像") plt.axis('off') plt.savefig(r"C:\Users\Administrator\Desktop\sy3-2-Laplacian.jpg") plt.show()
运行结果:
3. 对图像line.tif使用函数cv2.copyMakeBorder(),变换边界扩展方式,包括常量法(BORDER_CONSTANT),复制法(BORDER_REFLICATE),反射法(BORDER_REFLECT),外包装法(BORDER_WRAP)。将原图像和不同方式扩展后的图像展示在同一绘图区域。
import matplotlib.pyplot as plt import cv2 import numpy as np #get_ipython().run_line_magic('matplotlib', 'inline') plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签 plt.rcParams['axes.unicode_minus']=False #用来正常显示负 def border_fill(src,type=cv2.BORDER_DEFAULT,size=10): borderImg = cv2.copyMakeBorder(src, size, size, size, size, borderType=type) return borderImg img=cv2.imread(r"C:\Users\Administrator\Desktop\photo\line.tif",0) img1=border_fill(img,cv2.BORDER_CONSTANT,size=10) img2=border_fill(img,cv2.BORDER_REPLICATE,size=10) img3=border_fill(img,cv2.BORDER_REFLECT,size=10) img4=border_fill(img,cv2.BORDER_REFLECT_101,size=10) img5=border_fill(img,cv2.BORDER_WRAP,size=10) #输出对应的图片 plt.figure(figsize=(12,6)) plt.subplot(161) plt.imshow(img,vmin=0,vmax=255,cmap=plt.cm.gray)#设置内部的坐标,以及灰度的最大值和最小值 plt.title("原图像") plt.axis('off') plt.subplot(162) plt.imshow(img1,vmin=0,vmax=255,cmap=plt.cm.gray) plt.title("BORDER_CONSTANT") plt.axis('off') plt.subplot(163) plt.imshow(img2,vmin=0,vmax=255,cmap=plt.cm.gray) plt.title("BORDER_REPLICATE") plt.axis('off') plt.subplot(164) plt.imshow(img3,vmin=0,vmax=255,cmap=plt.cm.gray) plt.title("BORDER_REFLECT") plt.axis('off') plt.subplot(165) plt.imshow(img4,vmin=0,vmax=255,cmap=plt.cm.gray) plt.title("BORDER_REFLECT_101") plt.axis('off') plt.subplot(166) plt.imshow(img5,vmin=0,vmax=255,cmap=plt.cm.gray) plt.title("BORDER_WRAP") plt.axis('off') plt.savefig(r"C:\Users\Administrator\Desktop\sy3-3Border.jpg") plt.show()
运行结果:
遇到的问题:
AttributeError: ‘NoneType‘ object has no attribute ‘copy‘的解决办法
个人原因:文件路径的问题,检查文件路径以及 ‘_’, 文件路径不要中文,具体路径要写明测试图像名称。