各向异性扩散滤波(Anisotropic Filter)原理与C++实现

本文详细介绍了各向异性扩散滤波(Anisotropic Filter)的原理与应用,包括其在图像平滑中的优势,如何保留图像边缘,以及与高斯滤波的对比。通过迭代方程和散度公式,解释了滤波过程,并提供了C++实现代码。

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

各向异性扩散滤波(Anisotropic Filter,又称 Perona-Malik Filter),主要是用来平滑图像,克服了高斯滤波模糊的缺陷,各向异性扩散在平滑图像的同时又能保留图像边缘;此外,Perona-Malik Filter 在地学影像处理中也得到了相应的应用,如平滑DEM数据河道提取 等。
将图像看作热量场,每个像元看作热流,根据当前像元和周围像元的关系,来确定是否需要向周围扩散。如果某个邻域像元和当前像元差别较大,那么这个邻域像元可能是边界,当前像元就不向这个方向扩散了,该边界也就得到保留。
主要迭代方程如下:
I t + 1 = I t + λ ( c N x , y ∇ N ( I t ) + c S x , y ∇ S ( I t ) + c E x , y ∇ E ( I t ) + c W x , y ∇ W ( I t ) ) I_{t+1}=I_t+\lambda(cN_{x,y}\nabla_N(I_t)+cS_{x,y}\nabla_S(I_t)+cE_{x,y}\nabla_E(I_t)+cW_{x,y}\nabla_W(I_t)) It+1=It+λ(cNx,yN(It)+cSx,yS(It)+cEx,yE(It)+cWx,yW(It))其中, I I I 为图像, t t t 为迭代次数。
四个散度公式是在四个方向上对当前像素求偏导,公式如下:
∇ N ( I x , y ) = I x , y − 1 − I x , y ∇ S ( I x , y ) = I x , y + 1 − I x , y ∇ E ( I x , y ) = I x − 1 , y − I x , y ∇ W ( I x , y ) = I x + 1 , y − I x , y \begin{array}{lcl} \nabla_N(I_{x,y})=I_{x,y-1}-I_{x,y} \\ \nabla_S(I_{x,y})=I_{x,y+1}-I_{x,y} \\ \nabla_E(I_{x,y})=I_{x-1,y}-I_{x,y} \\ \nabla_W(I_{x,y})=I_{x+1,y}-I_{x,y} \end{array} N(Ix,y)=Ix,y1Ix,yS(Ix,y)=Ix,y+1Ix,yE(Ix,y)=Ix1,yIx,yW(Ix,y)=Ix+1,yIx,y
c N cN cN c S cS cS c E cE cE c W cW cW 代表四个方向上的导热系数,公式如下:
c N x , y = e − ∥ ∇ N ( I ) ∥ 2 k 2 c S x , y = e − ∥ ∇ S ( I ) ∥ 2 k 2 c E x , y = e − ∥ ∇ E ( I ) ∥ 2 k 2 c W x , y = e − ∥ ∇ W ( I ) ∥ 2 k 2 \begin{array}{lcl} cN_{x,y}=e^{-\frac{\rVert\nabla_N(I)\rVert^2}{k^2}} \\ cS_{x,y}=e^{-\frac{\rVert\nabla_S(I)\rVert^2}{k^2}} \\ cE_{x,y}=e^{-\frac{\rVert\nabla_E(I)\rVert^2}{k^2}} \\ cW_{x,y}=e^{-\frac{\rVert\nabla_W(I)\rVert^2}{k^2}} \end{array} cNx,y=ek2N(I)2cSx,y=ek2S(I)2cEx,y=ek2E(I)2cWx,y=ek2W(I)2
整个公式需要设置的参数主要有三个,迭代次数 t t t,根据情况设置;导热系数相关的 k k k,取值越大,结果越平滑,越不易保留边缘; λ \lambda λ 取值越大,结果越平滑。
C++实现(未使用opencv):

void AnisotropicFilter(float *ppafScan, float *outppafScan, int nImgWidth, int nImgHeight, int iterationSum, float k, float lambda)
{
	//ppafScan	输入数据
	//outppafScan	输出数据
	//nImgWidth, nImgHeight	数据的宽和高
	//iterationSum	迭代总次数
	//k	导热系数,控制平滑
	//lambda	控制平滑
	
	for(int iter = 0; iter < iterationSum; ++iter)
	{
		for(int i = 0; i < nImgHeight; ++i)
		{
			for (int j = 0; j < nImgWidth; ++j)
			{
				if(i == 0 || i == nImgHeight - 1 || j == 0 || j == nImgWidth - 1)
				{
					outppafScan[i * nImgWidth + j] = ppafScan[i * nImgWidth + j];
					continue;
				}

				float NI = ppafScan[i * nImgWidth + (j - 1)] - ppafScan[i * nImgWidth + j];
				float EI = ppafScan[(i - 1) * nImgWidth + j] - ppafScan[i * nImgWidth + j];
				float WI = ppafScan[(i + 1) * nImgWidth + j] - ppafScan[i * nImgWidth + j];
				float SI = ppafScan[i * nImgWidth + (j + 1)] - ppafScan[i * nImgWidth + j];

				float cN = exp(-NI * NI / (k * k));
				float cE = exp(-EI * EI / (k * k));
				float cW = exp(-WI * WI / (k * k));
				float cS = exp(-SI * SI / (k * k));

				outppafScan[i * nImgWidth + j] = ppafScan[i * nImgWidth + j] + lambda * (cN * NI + cS * SI + cE * EI + cW * WI);
			}
		}
	}
	
	return;
}

t = 20 t=20 t=20 k = 30 k=30 k=30 λ = 0.20 \lambda=0.20 λ=0.20 时,结果如下图所示:

在这里插入图片描述左:原始图像,右:滤波后的影像

在这里插入图片描述高斯滤波(线性)和Perona-Malik滤波(非线性)的比较:(a)原始影像;(b) Gaussian filtering (the kernels = 7 m);© Perona-Malik filter (t = 50);(d) Gaussian filtering (the kernels = 14 m);(e) Perona-Malik filter (t = 200) [原图链接]

欢迎大家批评指正。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A-Chin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值