目录
1. 介绍
2. 代码实现
3. code
1. 介绍
邻域均值滤波器又可以称为算术平均滤波器,其特点是核需要进行归一化处理。
这里我们介绍一个新的滤波器-------几何均值滤波器
数学表达式为:
和之前的均值滤波器不同的是,这里需要将滤波器框住的区域内所有像素的积再开1/mn 次幂。所有这里的kernel其实是没有值的,只是帮我们确认子区域而已。
几何均值滤波器和算术平均滤波器的平滑效果类似,但是损失的图像细节更少
2. 代码实现
这次我们将几何均值滤波器的代码封装到了函数里面,让我们一起逐行理解一下代码
因为没有相关的库函数,并且几何均值滤波器已经不能算是一个常规的滤波器了。像之前介绍的高斯核、邻域均值滤波都是一种加权求和的过程,这种的方法opencv库里面很多。
而几何均值滤波器是一种元素求积的过程,所有我们需要实现完整的卷积过程
首先,先获取图像的height 和 width ,为后面的卷积做准备。这里kernel_size 设置了3,我们使用的是m = n 的方阵的核。因为几何均值滤波器不需要kernel里面的值,只是需要kernel的size帮助我们框住子区域,所以不需要创建卷积核
接下来介绍一下pad,填充的大小
这里in 是输入图像的size,out是输出图像的sizef 代表滤波器的sizep 代表填充的大小s 代表步幅注:这只是一个通用的公式,例如如果图像行列不相等的话,就把对应的行列带入这个公式,就能得到对应图像输出的行列
因为这里我们需要保证图像的size 输出 = 输入,也就是in = out,s步幅设置成1
这样公式就变成了f = 2p + 1,也就是p = (f - 1) / 2,也就是代码里面的那一段
公式里面2p的意思是图像的上下或者左右填充相同的行或者列
滤波器的使用习惯是奇数,为了保证kernel有中心,所以一般公式都是可以除尽的
接下来是对图像进行pad填充,需要使用np.pad函数,这里不作重点介绍,只看一个例子
a = np.arange(0,9).reshape(3,3)pad = 1 a_pad = np.pad(a,pad,mode = 'edge')
填充的结果为:
pad 本来要填((上,下),(左,右))这样的数组,因为这里我们填充的上下左右的个数都是一样的,所以只要一个pad值就可以了。mode = 'edge' 是按照边缘进行填充
为什么pad上下左右填充的个数一样?
观察我们的公式可知:
因为我们要保证图像的高度核宽度一样,那么无论我们带入的是图像的height还是width,in和out都会被消掉。
就变成了 f = 2p + 1,而我们的 f 滤波器的大小又是方形的,因此无论图像是不是方形的,填充p上下或者左右都应该是一样的。所以说p的值是固定不变的,也就是 2p = (f - 1) ,而2p代表的又是上下或者左右填充,我们让他上下或者左右均匀填充一样的就好了
接下来就开始进行实现类似卷积的操作了,不过不同的地方是,我们不是加权求和,而是各个元素相乘
这里要注意尺寸的问题,我们的目标是将kernel 去对填充过的图像img_pad 做卷积然后赋值到原图像img 的过程,所以两幅图像的下标是不一样的
其实,kernel一直都是再原图像进行操作,而pad的目的就是防止再对边缘卷积的时候,kernel会越界。
所以kernel中心点两侧的大小应该等于pad的大小
这里我们让i , j再原图上进行遍历,所以i ,j的范围如图所示,
而img_pad 索引kernel 区域图像的时候,记得是左闭右开的,所以右边需要 + 1
np.prod 计算里面数组的所有元素乘积
3. code
import cv2import numpy as npdef geometric_mean_filter(img,kernel_size = 3):height ,width = img.shape[:2] # 获取图像的sizeksize = kernel_size # 滤波器的大小order = 1 / pow(ksize,2) # 阶次pad = int((ksize - 1) / 2) # 填充的大小img_pad = np.pad(img,pad,mode='edge') # 边缘paddingfor i in range(pad,pad+height):for j in range(pad,pad+width):ret = np.prod(img_pad[i - pad:i + pad + 1, j - pad:j + pad + 1],dtype=np.float32) # 计算kernel里面的乘积img[i - pad][j - pad] = pow(ret, order)return img.astype(np.uint8)img = cv2.imread("./img.png", 0)img_copy = img.copy() # 图像备份dst =geometric_mean_filter(img_copy) # 几何均值滤波器cv2.imshow('img',np.hstack((img,dst)))cv2.waitKey()cv2.destroyAllWindows()
运行结果为:
如果觉得《空间滤波-几何均值滤波器》对你有帮助,请点赞、收藏,并留下你的观点哦!