失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 曲率高斯滤波去噪python实现(附代码详解)

曲率高斯滤波去噪python实现(附代码详解)

时间:2024-03-25 11:51:53

相关推荐

曲率高斯滤波去噪python实现(附代码详解)

曲率高斯滤波去噪python实现(附代码详解)

曲率滤波的理论基础可以参考下曲率滤波的理论基础和应用,这篇博客介绍的思想完美的避开了一大堆数学公式,简直是我的福音,但还是要细看的,不然很容易忽略重点,我这里就简单的做个总结,所有图片(除了我最后画的那个丑丑的图片)均来源于前面这篇博客。

曲率滤波基本原理

1、曲率

曲面上的一点有一切平面,此点处会有各个方向上的曲率,但是必然会有最大主曲率和最小主曲率,k1是最小主曲率,k2是最大主曲率,则平均曲率和高斯曲率的定义如下:

2、可展曲面

可展曲面可由其切平面局部估计而得。

前面我们已知,二维图像中的高斯曲率定义为两个主曲率的乘积,定理1告诉我们的是,任何可展曲面(虽然只有3个可展曲面)其任意点处的高斯曲率为零。因此,最小化其中任意一个主曲率,就相当于最小化高斯曲率!

以上结论即是高斯曲率滤波器的理论基础(我们即可实现高斯曲率的最小化而无需进行高斯曲率的显式计算):

切点的领域上必有一点也在切平面上,高斯滤波的作用是把不在这个切平面上的点可展到切平面上。

3、域分解方法

局部最小化主曲率绝对值的较小者,受限于相邻像素之间的关联性,因此,提出了一种域分解方法,以去除相邻像素之间的依赖性。(这里其实是保证在3*3的模块里相邻点没有相同的元素。)

4、切平面

选取的是三角构型用于表示曲面的切平面,下面以红色点x与其3×3邻域N(x)为例,如图6所示:

这是在此局部窗口中的一个三角切平面,得到此切平面之后,我们将红色点,即当前点拉长到绿色切平面上,就可以得到当前点到切平面的距离di,如图7所示:

实际上,以黑色圆形点为中心点,切平面过白色点的三角构型切平面还有3种,也就是说图8(a)中的切平面共有4种,如图9所示:

在一个3*3的模块中,三角构型切平面共有12种情况,但是仔细看图6和图7可以看出,到切平面的距离di的实际情况没有12种。以图10(a)为例说明一下,黑色圆点到切平面的距离实际上就是黑色圆点到 ”白色圆-黑色圆-白色圆” 线段的距离。

5、求di

当前点到切平面的投影总共有8种,即当前点到切平面的距离共有8种,{di, i=1,2,…,8},这里使用8种投影距离的最小值作为投影算子。

代码如下

先贴一段曲率滤波的程序,这个函数主要是实现求最小投影算子

from __future__ import divisionimport numpy as np#曲率滤波def update_gc(inputimg, i, j):#对二维数组(图片)进行操作#数组不取到最后一个像素点的原因,可以参考我后面画的图,因为在步长为2的情况下是取不到最后一个点的inputimg_ij = inputimg[i:-1:2, j:-1:2]#求di(根据公式写程序,基点是[i:-1:2, j:-1:2])#d1中[i - 1:-2:2, j:-1:2] 也可以参考后面画的图,因为它是基点的左边一个点,是模块中心点正左方的点,所以取不到倒数第二个点d1 = (inputimg[i - 1:-2:2, j:-1:2] + inputimg[i + 1::2, j:-1:2])/2.0 - inputimg[i:-1:2, j:-1:2]d2 = (inputimg[i:-1:2, j - 1:-2:2] + inputimg[i:-1:2, j + 1::2])/2.0 - inputimg[i:-1:2, j:-1:2]d3 = (inputimg[i - 1:-2:2, j - 1:-2:2] + inputimg[i + 1::2, j + 1::2])/2.0 - inputimg[i:-1:2, j:-1:2]d4 = (inputimg[i - 1:-2:2, j + 1::2] + inputimg[i + 1::2, j - 1:-2:2])/2.0 - inputimg[i:-1:2, j:-1:2]d5 = (inputimg[i - 1:-2:2, j:-1:2] + inputimg[i:-1:2, j - 1:-2:2] -inputimg[i - 1:-2:2, j - 1:-2:2]) - inputimg[i:-1:2, j:-1:2]d6 = (inputimg[i - 1:-2:2, j:-1:2] + inputimg[i:-1:2, j + 1::2] - inputimg[i - 1:-2:2,j + 1::2])- inputimg[i:-1:2, j:-1:2]d7 = (inputimg[i:-1:2, j- 1:-2:2] + inputimg[i + 1::2, j:-1:2] - inputimg[i + 1::2, j - 1:-2:2])- inputimg[i:-1:2, j:-1:2]d8 = (inputimg[i:-1:2, j + 1::2] + inputimg[i + 1::2, j:-1:2] - inputimg[i + 1::2, j + 1::2])- inputimg[i:-1:2, j:-1:2]#找到di最小值并赋值给d#条件满足则赋1不满足赋0,若d2<d1,则np.abs(d2) < np.abs(d1)为1,np.abs(d1) <= np.abs(d2)为0,d=d2d = d1 * (np.abs(d1) <= np.abs(d2)) + d2 * (np.abs(d2) < np.abs(d1))d = d * (np.abs(d) <= np.abs(d3)) + d3 * (np.abs(d3) < np.abs(d))d = d * (np.abs(d) <= np.abs(d4)) + d4 * (np.abs(d4) < np.abs(d))d = d * (np.abs(d) <= np.abs(d5)) + d5 * (np.abs(d5) < np.abs(d))d = d * (np.abs(d) <= np.abs(d6)) + d6 * (np.abs(d6) < np.abs(d))d = d * (np.abs(d) <= np.abs(d7)) + d7 * (np.abs(d7) < np.abs(d))d = d * (np.abs(d) <= np.abs(d8)) + d8 * (np.abs(d8) < np.abs(d))#list.append(d)inputimg_ij[...] +=d

主程序代码

import scipy.miscimport numpy as np#cf_update文件是上面的代码from cf_update import update_gcfrom skimage.color.adapt_rgb import adapt_rgb, each_channelfrom PIL import Image#找函数名,相当于路由#字典类型 键值对 调用方法:updaterule.keys()调用键,updaterule.value()调用值updaterule = {'gc': update_gc}@adapt_rgb(each_channel)#定义一个带参数的函数#inputimg调用的初始图片,filtertype是指调用的滤波器类型,total_iter迭代次数def cf_filter(inputimg, filtertype, total_iter = 10, dtype = np.float32):#断言 如果不满足括号内条件系统报错并提示后一句assert(type(filtertype) is str), "input argument is not a string datatype!"#判断调用的滤波器是否在路由中assert(filtertype in updaterule.keys()), "filter type is not found!"#不对原图片进行修改 复制一份进行操作filteredimg = np.copy(inputimg.astype(dtype))#获取到函数名update = updaterule.get(filtertype)#遍历for iter_num in range(total_iter):update(filteredimg, 1, 1)update(filteredimg, 2, 2)update(filteredimg, 1, 2)update(filteredimg, 2, 1)return filteredimgim = Image.open('2.jpg').convert('L')im.show()#图片转数组对象arr=np.array(im)result=cf_filter(arr,'gc',total_iter = 3)#array 反操作pil_im = Image.fromarray(result)pil_im.show()

以下是关于这一段程序的解释

for iter_num in range(total_iter):update(filteredimg, 1, 1)update(filteredimg, 2, 2)update(filteredimg, 1, 2)update(filteredimg, 2, 1)return filteredimg

请先原谅我的作图能力为零,我会慢慢研究的,但是我现在没办法,只好这样画出来,以及我也知道我是小学生字体,emmm能看懂就行啦!

提到的模块就是上面那个3乘3的模块,这样可以遍历一张图片的每一个像素点,确保都能覆盖到(我这里是假设的像素为5乘5),从阴影部分也是能看出来每个像素块都被覆盖了。

运行结果

首先是原图(就是我上一篇博客中加了椒盐噪声的结果图):

然后是迭代3次后的结果图:

然后是迭代10次:

最后是迭代20次:

小结:

高斯滤波在实践中10次就能看到结果,其最重要性能是保存可展曲面,对于不可展曲面其减少了绝对高斯曲率,自动平滑图像并保持边缘。

下一篇预告:(我也不知道是什么系列,就酱!)

如果觉得《曲率高斯滤波去噪python实现(附代码详解)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。