各项异性扩散(Anisotropic diffusion)

各向异性扩散滤波是一种图像处理技术,旨在减少图像噪声同时保持边缘清晰。该技术模仿热传导过程,通过控制像素间的信息传递来实现平滑效果。与高斯模糊不同,各向异性扩散能有效避免模糊边缘,适用于图像去噪和增强。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.原理简介

各向异性扩散滤波主要是用来平滑图像的,克服了高斯模糊的缺陷,各向异性扩散在平滑图像时是保留图像边缘的,和双边滤波很像。各向异性扩散,也叫做P–M扩散,在图像处理和计算机视觉中广泛用于保持图像细节特征的同时减少噪声。

通常我们有将图像看作矩阵的,看作图的,看作随机过程的,记得过去还有看作力场的。这次新鲜,将图像看作热量场了。每个像素看作热流,根据当前像素和周围像素的关系,来确定是否要向周围扩散。比如某个邻域像素和当前像素差别较大,则代表这个邻域像素很可能是个边界,那么当前像素就不向这个方向扩散了,这个边界也就得到保留了。

具体的推导公式都是热学上的,自己也不太熟悉,感兴趣的可以去看原论文,引用量超7000吶。我这里只介绍一下最终结论用到的公式。
主要迭代方程如下:

I就是图像了,因为是个迭代公式,所以有迭代次数t。
四个散度公式是在四个方向上对当前像素求偏导,news就是东南西北嘛,公式如下:

而cN/cS/cE/cW则代表四个方向上的导热系数,边界的导热系数都是小的。公式如下:

最后整个公式需要先前设置的参数主要有三个,迭代次数t,根据情况设置;导热系数相关的k,取值越大越平滑,越不易保留边缘;lambda同样也是取值越大越平滑。

2.代码实现(python)

import cv2
import numpy as np
import math
class anisodiff2D(object):
 
    def __init__(self, num_iter=5, delta_t=1/7, kappa=30, option=2):
 
        super(anisodiff2D, self).__init__()
 
        self.num_iter = num_iter
        self.delta_t = delta_t
        self.kappa = kappa
        self.option = option
 
        self.hN = np.array([[0, 1, 0], [0, -1, 0], [0, 0, 0]])
        self.hS = np.array([[0, 0, 0], [0, -1, 0], [0, 1, 0]])
        self.hE = np.array([[0, 0, 0], [0, -1, 1], [0, 0, 0]])
        self.hW = np.array([[0, 0, 0], [1, -1, 0], [0, 0, 0]])
        self.hNE = np.array([[0, 0, 1], [0, -1, 0], [0, 0, 0]])
        self.hSE = np.array([[0, 0, 0], [0, -1, 0], [0, 0, 1]])
        self.hSW = np.array([[0, 0, 0], [0, -1, 0], [1, 0, 0]])
        self.hNW = np.array([[1, 0, 0], [0, -1, 0], [0, 0, 0]])
 
    def fit(self, img):
 
        diff_im = img.copy()
 
        dx = 1; dy = 1; dd = math.sqrt(2)
 
        for i in range(self.num_iter):
            nablaN = cv2.filter2D(diff_im, -1, self.hN)
            nablaS = cv2.filter2D(diff_im, -1, self.hS)
            nablaW = cv2.filter2D(diff_im, -1, self.hW)
            nablaE = cv2.filter2D(diff_im, -1, self.hE)
            nablaNE = cv2.filter2D(diff_im, -1, self.hNE)
            nablaSE = cv2.filter2D(diff_im, -1, self.hSE)
            nablaSW = cv2.filter2D(diff_im, -1, self.hSW)
            nablaNW = cv2.filter2D(diff_im, -1, self.hNW)
 
            cN = 0; cS = 0; cW = 0; cE = 0; cNE = 0; cSE = 0; cSW = 0; cNW = 0
 
            if self.option == 1:
                cN = np.exp(-(nablaN/self.kappa)**2)
                cS = np.exp(-(nablaS/self.kappa)**2)
                cW = np.exp(-(nablaW/self.kappa)**2)
                cE = np.exp(-(nablaE/self.kappa)**2)
                cNE = np.exp(-(nablaNE/self.kappa)**2)
                cSE = np.exp(-(nablaSE/self.kappa)**2)
                cSW = np.exp(-(nablaSW/self.kappa)**2)
                cNW = np.exp(-(nablaNW/self.kappa)**2)
            elif self.option == 2:
                cN = 1/(1+(nablaN/self.kappa)**2)
                cS = 1/(1+(nablaS/self.kappa)**2)
                cW = 1/(1+(nablaW/self.kappa)**2)
                cE = 1/(1+(nablaE/self.kappa)**2)
                cNE = 1/(1+(nablaNE/self.kappa)**2)
                cSE = 1/(1+(nablaSE/self.kappa)**2)
                cSW = 1/(1+(nablaSW/self.kappa)**2)
                cNW = 1/(1+(nablaNW/self.kappa)**2)
 
            diff_im = diff_im + self.delta_t * (
 
                (1/dy**2)*cN*nablaN +
                (1/dy**2)*cS*nablaS +
                (1/dx**2)*cW*nablaW +
                (1/dx**2)*cE*nablaE +
 
                (1/dd**2)*cNE*nablaNE +
                (1/dd**2)*cSE*nablaSE +
                (1/dd**2)*cSW*nablaSW +
                (1/dd**2)*cNW*nablaNW
            )
 
        return diff_im
这个是八向扩散的封装类
--------------------- 
作者:GlassySky0816 
来源:CSDN 
原文:https://blog.csdn.net/qq_38784098/article/details/81605963 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值