一.噪声和平滑处理
1.增加噪声
def add_peppersalt(image,n=10000): result = image.copy() h,w = image.shape[:2] # 获取图片的高和宽 for i in range(n): # 生成n个椒盐噪声 x = np.random.randint(0,h) y = np.random.randint(0,w) if np.random.randint(0,2) == 0: # 百分之五十的概率 result[x,y] = 0 else: result[x,y] = 255 return result定义噪声函数 add_peppersalt,传入参数:图像数据(image),生成椒盐噪声的个数(n),默认值为10000。result复制一份图像数据,h,w获取图像的高和宽。进入循环,生成n个椒盐噪声。
x,y在图像的高宽范围内随机选取一点,百分之50的概率添加黑色噪声,百分之50的概率添加白色噪声。返回处理后的图像。
image = cv2.imread("./03.jpg") image = cv2.resize(image,(400,400)) cv2.imshow("yuantu",image) cv2.waitKey(0)读入原始图像,展示图像,设置停留时间。
noise = add_peppersalt(image) cv2.imshow("noise",noise) cv2.waitKey(0)调用噪声函数,对原图进行添加噪声的操作,返回noise噪声图像,然后展示图像,设置停留时间。
结果图如下:
2.平滑处理
1.均值滤波(blur)
原理:
它的核心原理可以概括为八个字:“邻域平均,中心替换”。在图像上选定一个目标像素点,以它为中心,划定一个固定大小的正方形区域,这个区域被称为卷积核或模板。常见的大小有 3x3、5x5 等(通常为奇数,以便有唯一的中心点)。将邻域内所有像素点的灰度值相加,然后除以像素的总个数(即求算术平均值)。用计算出的这个平均值,替换掉原始中心像素的灰度值。然后,将这个滑窗在整张图片上从左到右、从上到下依次滑动,对每个像素执行相同的操作,直到整张图都被遍历一遍。
优缺点:算法极其简单,计算速度快,对抵抗高斯噪声(分布较均匀的噪声)效果不错。
破坏边缘细节。因为图像的边缘往往是灰度剧烈变化的地方,均值滤波会把这些“突变”拉平,导致边缘、纹理等细节变得模糊不清。卷积核越大,去噪能力越强,但图像也越模糊。
边界处理:当滑窗移动到图像边缘时,窗口会超出图像边界。常见的处理方式有忽略边界,零填充。
忽略边界就是最外围的边界像素不去管它,只处理内部像数值,但这样每处理一次图像就会缩小一圈;零填充就是在最外围补上一圈0 。
# 均值滤波 blur blur_1 = cv2.blur(noise,ksize=(3,3)) #卷积核为3,3效果一般,清晰度一般 cv2.imshow("blur_1",blur_1) cv2.waitKey(0)简单实现均值滤波,dst=cv2.blur(src,ksize,anchor,borderType),参数如下:
- dst是返回值
- src是需要处理的图像
- ksize是滤波核(卷积核)的大小
- anchor是锚点,默认值是(-1,-1)一般无需更改
- borderType是边界样式,一般无需更改
一般情况下,使用dst=cv2.blur(src,ksize)即可。
运行结果:可以看到对抗椒盐噪声很一般,略微除去了一点噪声。
2.方框滤波(boxFilter)
原理:
与均值滤波类似,只不过 ,它是用正方形区域内所有像素值的和或平均来替换中间的像素值,也就是非归一化和归一化,当使用归一化时,它就是均值滤波;当使用非归一化,它就主要用于特征计算或亮度统计,并不关心平均值,只关心局部区域的总能量。
优缺点:过于突出的亮点会被周围的暗点“拉低”,过于暗的点会被拉亮,整张图就变得“平滑”。但会严重模糊边缘。
dst=cv2.boxFilter (src,ddepth,ksize,anchor,normalize,borderType)式中参数如下:
● dst是返回值,表示进行方框滤波后得到的处理结果。
● src 是需要处理的图像,即原始图像。
● ddepth是处理结果图像的图像深度,一般使用-1表示与原始图像使用相同的图像深度。(可以理解为数据类型)
● ksize 是滤波核的大小。滤波核大小是指在滤波处理过程中所选择的邻域图像的高 度和宽度。
● anchor 是锚点,(指对应哪个区域)
● normalize 表示在滤波时是否进行归一化。
1.当值为True时,归一化,用邻域像素值的和除以面积。此时方框滤波与 均值滤波 效果相同。
2.当值为False时,不归一化,直接使用邻域像素值的和。和>255时使用255
boxFilter_1 = cv2.boxFilter(noise,-1,(3,3),normalize=True) # 方框滤波 cv2.imshow("boxFilter_1",boxFilter_1) cv2.waitKey(0)运行结果如下:
3.高斯滤波(GaussianBlur)
原理:
也是用卷积核扫过图像进行处理,卷积核内是各个像素所占的权重。利用高斯函数计算邻域内每个像素的权重,离中心越近的像素影响力越大,离得越远影响力越小。高斯滤波的权重不是人为设定的,而是严格遵循二维高斯分布(正态分布)
二维高斯函数的数学表达式为:
其中:
- G(x, y):在坐标 (x, y) 处的高斯核权重值
- σ:标准差,控制高斯分布的宽度(平滑程度)
- x, y:相对于卷积核中心的坐标位置
将邻域内每个像素的坐标代入公式,算出权重值,组成卷积核。
计算完所有权重后,必须将整个核的权重总和归一化为 1(除以总和)。这是为了保证滤波前后图像的整体亮度不变。
cv2.GaussianBlur(src, ksize[, sigmaX[, sigmaY[, dst]]]) 高斯滤波
参数说明:
- src:输入图像,通常是一个 NumPy 数组。
- ksize:滤波器的大小,它是一个元组,表示在水平和垂直方向上的像素数量。例如,(5, 5) 表示一个 5×5 的滤波器。
- sigmaX和sigmaY:分别表示在 X 轴和 Y 轴方向上的标准差。这些值与滤波器大小相同。默认情况下,它们都等于 0,这意味着没有高斯模糊。
- dst:输出图像,通常是一个 NumPy 数组。如果为 None,则会创建一个新的数组来存储结果。
高斯滤波通过高斯函数计算卷积核中每个像素的权重,离中心越近的像素权重越大,离中心越远的像素权重越小。这种权重分布使得高斯滤波在平滑图像的同时,能更好地保留边缘信息。
使用示例
GaussianB = cv2.GaussianBlur(noise,(3,3),1) #标准差为1,标准正太分布。 3、高斯滤波 cv2.imshow("GaussianBlur",GaussianB) cv2.waitKey(0)运行结果图:
4.中值滤波(medianBlur)
:原理:
用卷积核扫过图像进行处理,把卷积核扫到的邻域内的像素按灰度值排序,取中间那个值来替换中心像素。
优缺点:椒盐噪声(随机出现的全黑或全白点)在排序后,极值(0 或 255)会天然地被排到数组的两端,永远不会被选中为中值。因此,中值滤波在去除这种孤立的异常点时,效果远优于线性滤波。但对高斯噪声效果一般,高斯噪声是均匀分布、服从正态分布的细小灰度波动,它们没有极端值。对一大堆数值接近的像素排序取中值,和平滑取平均效果差别不大,且不如高斯滤波来得平滑自然。
cv2.medianBlur(src, ksize[, dst]) 中值滤波
参数说明:
- src:输入图像。
- ksize:滤波器的大小,它是一个整数,表示在水平和垂直方向上的像素数量。例如,5 表示一个 5×5 的滤波器。
- dst:输出图像,通常是一个 NumPy 数组。如果为 None,则会创建一个新的数组来存储结果。
中值滤波是一种非线性滤波方法,特别适合去除椒盐噪声。它的核心思想是用邻域内像素值的中值来替代中心像素值,这样能有效消除孤立的噪声点。
使用示例:
medianB = cv2.medianBlur(noise,3) cv2.imshow("medianBlur",medianB) cv2.waitKey(0) cv2.destroyAllWindows()运行结果:可以看到中值滤波对椒盐噪声的处理效果非常好。
二.图像形态学腐蚀和膨胀
1.图像腐蚀
原理:
图像腐蚀(Erosion)是形态学基本操作之一,它的核心原理可以用一句话概括:"把高亮区域(前景)向内收缩,吃掉边缘的一层像素。"
与方框滤波不同,腐蚀不是计算权重和,而是设定一个结构元素——通常是一个小矩形、十字形或椭圆形,这个结构元素有一个锚点(通常为中心点)。
运算规则(以二值图为例,前景为白色1,背景为黑色0):
- 将结构元素在图像上滑动,判断结构元素覆盖下的所有像素点。
- 如果结构元素覆盖的区域全部都是白色(1),那么锚点对应的中心像素保留为白色(1)。
- 只要覆盖区域内有一个像素是黑色(0),那么锚点对应的中心像素立刻变为黑色(0)。
通俗理解:结构元素就像一个"缩小滤镜"。只有窗口内的像素"全部符合条件"时,中心点才能幸存;只要有一点"杂质",这个点就会被腐蚀掉。
效果:
- 前景(白色)区域会缩小,边缘会向内收缩。
- 细小的白色噪点、毛刺会被消除。
- 两个相邻但未连通的白色区域可能会断开。
- 白色区域的边界变得更加平滑。
应用场景:
- 去除图像中的细小噪声点。
- 分离两个粘连的物体。
- 消除物体边缘的毛刺。
- 为后续的形态学操作(如开运算、闭运算)做准备。
参数说明:cv2.erode(src,kernel,iterations)
- src:输入图像,可以是二值图或灰度图。
- kernel:结构元素,决定了腐蚀的形状和大小。
- iterations:腐蚀次数,次数越多,腐蚀效果越明显。
读入原图:
image_sun = cv2.imread("./sun.png") cv2.imshow("sun",image_sun) cv2.waitKey(0)使用示例:
# 腐蚀元件 kernel = np.ones((3,3),np.uint8) # 设置kenenel大小,核改为5*5试试 # 腐蚀 erosion = cv2.erode(image_sun,kernel,iterations=2) # iterations改为5试试 cv2.imshow("erosion",erosion) cv2.waitKey(0)kernel为腐蚀原件,这里是(3,3)的大小,使用cv2.erode函数,传入原图,腐蚀次数为2,展示运行结果图:分别为原图,腐蚀后的图
可以看到腐蚀效果不错。
2.图像膨胀
原理:
图像膨胀(Dilation)是形态学基本操作之一,它的核心原理可以用一句话概括:"把高亮区域(前景)向外'长胖'一圈,吞并周围的背景像素。"
与腐蚀类似,膨胀也使用结构元素(通常是小矩形、十字形或椭圆形)在图像上滑动,但运算规则与腐蚀正好相反。
运算规则(以二值图为例,前景为白色1,背景为黑色0):
- 将结构元素(Kernel)在图像上滑动,判断结构元素覆盖下的所有像素点。
- 只要覆盖区域内有一个像素是白色(1),那么锚点对应的中心像素就设为白色(1)。
- 只有覆盖区域内所有像素全是黑色(0),锚点对应的中心像素才会被设为黑色(0)。
通俗对比:
- 腐蚀:要求窗口内"全部是白"才留白(极严格,导致边界向内缩)。
- 膨胀:只要窗口内"有一丁点白"就变白(极宽松,导致边界向外涨)。
效果:
- 前景(白色)区域会扩大,边缘会向外扩张。
- 细小的黑色孔洞、裂缝会被填充。
- 两个相邻但未连通的白色区域可能会连接起来。
- 白色区域的边界变得更加饱满。
应用场景:
- 填充图像中的小孔洞和裂缝。
- 连接相邻但断开的物体。
- 扩大前景区域,增强目标特征。
- 为后续的形态学操作(如开运算、闭运算)做准备。
参数说明:cv2.dilate(src,kernel,iterations)
- src:输入图像,可以是二值图或灰度图。
- kernel:结构元素,决定了膨胀的形状和大小。
- iterations:膨胀次数,次数越多,膨胀效果越明显。
使用示例:
wenzi = cv2.imread("wenzi.png") cv2.imshow("wenzi",wenzi) cv2.waitKey(0)读入原图
kernel = np.ones((3,3),np.uint8) # 设置kenenel大小 dilation = cv2.dilate(wenzi,kernel,iterations=2) cv2.imshow("dilation",dilation) cv2.waitKey(0) cv2.destroyAllWindows()kernel为膨胀元件,这里是(3,3)的大小,使用cv2.dilate函数,传入原图,膨胀次数为2,展示运行结果图:分别为原图,膨胀后的图
运行结果:可以看到膨胀效果使文字图案向外扩张,填充了内部的小间隙。
三.图像的开,闭,梯度,顶帽与黑帽
1.图像的开运算
原理:先腐蚀后膨胀
作用:平滑物体的轮廓、断开较窄的狭颈并消除细的突出物。
参数说明:cv2.morphologyEx(src, op, kernel, iterations)
- src:输入图像,可以是二值图或灰度图。
- op:形态学操作类型。对于开运算,应设置为
cv2.MORPH_OPEN。 - kernel:结构元素(卷积核),决定了形态学操作的形状和大小。通常使用
np.ones((n,n), np.uint8)创建矩形核,或使用cv2.getStructuringElement()创建其他形状(如椭圆形、十字形)。 - iterations:迭代次数,即执行开运算的次数。次数越多,效果越明显。
使用示例:
kernel = np.ones((3,3),np.uint8) zhiwen_open = cv2.morphologyEx(zhiwen,cv2.MORPH_OPEN,kernel) cv2.imshow("zhiwen_open",zhiwen_open) cv2.waitKey(0)效果解释:开运算先通过腐蚀去除图像中细小的噪声点或突出物,再通过膨胀恢复主体区域的大致形状。因此,它能有效消除小的白色噪点,同时保持主体区域的大小和形状基本不变。
运行效果:
2.图像的闭运算
原理:先膨胀后腐蚀
作用:弥合较窄的间断和细长的沟壑,消除小的孔洞,填补轮廓线。
参数说明:cv2.morphologyEx(src, op, kernel, iterations)
- src:输入图像,可以是二值图或灰度图。
- op:形态学操作类型。对于闭运算,应设置为
cv2.MORPH_CLOSE。 - kernel:结构元素(卷积核),决定了形态学操作的形状和大小。通常使用
np.ones((n,n), np.uint8)创建矩形核,或使用cv2.getStructuringElement()创建其他形状(如椭圆形、十字形)。 - iterations:迭代次数,即执行闭运算的次数。次数越多,效果越明显。
使用示例:
原图,指纹段
zhiwen_duan = cv2.imread("./zhiwen_duan.png") cv2.imshow("zhiwen_duan",zhiwen_duan) cv2.waitKey(0)闭运算操作:
kernel = np.ones((4,4),np.uint8) zhiwen_duan_close = cv2.morphologyEx(zhiwen_duan,cv2.MORPH_CLOSE,kernel) cv2.imshow("zhiwen_duan_close",zhiwen_duan_close) cv2.waitKey(0) cv2.destroyAllWindows()效果解释:闭运算先通过膨胀扩大前景区域,填充物体内部的小孔洞和连接狭窄的断裂,再通过腐蚀恢复物体的大致原始大小。因此,它能有效闭合前景物体中的小洞,连接相邻的物体,并平滑物体的轮廓,同时基本保持物体原有面积。
运行效果:原图,闭运算操作
3.图像的梯度运算
原理:膨胀-腐蚀
作用:突出显示图像中强度变化剧烈的地方,即图像的边缘轮廓。
参数说明:cv2.morphologyEx(src, op, kernel, dst=None, anchor=(-1, -1), iterations=1, borderType=None, borderValue=None)
- src:输入图像,可以是二值图或灰度图。
- op:形态学操作类型。对于梯度运算,应设置为
cv2.MORPH_GRADIENT。 - kernel:结构元素(卷积核),决定了形态学操作的形状和大小。通常使用
np.ones((n,n), np.uint8)创建矩形核,或使用cv2.getStructuringElement()创建其他形状(如椭圆形、十字形)。 - iterations(可选):迭代次数,即执行梯度运算的次数。默认为1。
使用示例:
wenzi = cv2.imread("wenzi.png") cv2.imshow("wenzi",wenzi) cv2.waitKey(0)# 膨胀 kernel = np.ones((3,3),np.uint8) wenzi_dilation = cv2.dilate(wenzi,kernel,iterations=1) cv2.imshow("wenzi_dilation",wenzi_dilation) cv2.waitKey(0)# 腐蚀 wenzi_erosion = cv2.erode(wenzi,kernel,iterations=1) cv2.imshow("wenzi_erosion",wenzi_erosion) cv2.waitKey(0)# 膨胀-腐蚀 gradient = cv2.morphologyEx(wenzi,cv2.MORPH_GRADIENT,kernel) cv2.imshow("gradient",gradient) cv2.waitKey(0) cv2.destroyAllWindows()效果解释:梯度运算通过计算图像膨胀结果与腐蚀结果之间的差值来提取边缘。膨胀操作会使前景区域向外扩张,腐蚀操作会使前景区域向内收缩。两者相减后,得到的是原始物体轮廓的边界区域。因此,梯度运算特别适合用于突出显示物体的边缘轮廓,在图像分割、边缘检测和特征提取中非常有用。
运行效果:梯度运算后的图像会突出显示原图中物体的边缘,边缘部分通常显示为亮色,而内部和背景区域则较暗。
4.图像的顶帽运算
原理:顶帽运算 = 原始图像 - 开运算结果(先腐蚀后膨胀)
作用:用于提取比周围区域亮的细节(如背景均匀的亮斑、细线、文字等)。
参数说明:cv2.morphologyEx(src, op, kernel, iterations=1)
- src:输入图像,可以是二值图或灰度图。
- op:形态学操作类型。对于顶帽运算,应设置为
cv2.MORPH_TOPHAT。 - kernel:结构元素(卷积核),决定了形态学操作的形状和大小。通常使用
np.ones((n,n), np.uint8)创建矩形核,或使用cv2.getStructuringElement()创建其他形状(如椭圆形、十字形)。 - iterations(可选):迭代次数,即执行顶帽运算的次数。默认为1。
使用示例:
sun_tophat = cv2.morphologyEx(sun,cv2.MORPH_TOPHAT,kernel) cv2.imshow("sun_tophat",sun_tophat) cv2.waitKey(0)效果解释:顶帽运算通过从原始图像中减去开运算结果,能够突出显示那些比背景亮且尺寸小于结构元素的细节。开运算会消除小的亮区域,因此原始图像减去开运算结果后,剩下的就是这些被消除的小亮区域。这在图像增强、背景不均匀校正和特征提取中非常有用。
运行效果:顶帽运算后的图像会突出显示原始图像中比周围亮的细小特征,如文本、划痕、亮斑等,同时抑制均匀的背景。
5.图像的黑帽运算
原理:黑帽运算 = 闭运算(先膨胀后腐蚀)- 原始图像
作用:用于提取比周围区域暗的细节(如背景均匀的暗斑、裂缝、孔洞等)。
参数说明:cv2.morphologyEx(src, op, kernel, iterations=1)
- src:输入图像,可以是二值图或灰度图。
- op:形态学操作类型。对于黑帽运算,应设置为
cv2.MORPH_BLACKHAT。 - kernel:结构元素(卷积核),决定了形态学操作的形状和大小。通常使用
np.ones((n,n), np.uint8)创建矩形核,或使用cv2.getStructuringElement()创建其他形状(如椭圆形、十字形)。 - iterations(可选):迭代次数,即执行黑帽运算的次数。默认为1。
使用示例:
sun_blackhat = cv2.morphologyEx(sun,cv2.MORPH_BLACKHAT,kernel) cv2.imshow("sun_blackhat",sun_blackhat) cv2.waitKey(0) cv2.destroyAllWindows()效果解释:黑帽运算通过从闭运算结果中减去原始图像,能够突出显示那些比背景暗且尺寸小于结构元素的细节。闭运算会填充小的暗区域,因此闭运算结果减去原始图像后,剩下的就是这些被填充的小暗区域。这在检测图像中的暗色缺陷、裂缝或孔洞时非常有用。
运行效果:黑帽运算后的图像会突出显示原始图像中比周围暗的细小特征,如暗斑、裂缝、孔洞等,同时抑制均匀的背景。