图形算法与实战:1.滤波专题 (4)各向异性扩散滤波

本文介绍了一种图像处理技术——各向异性扩散滤波,它是一种有效的滤除图像噪音方法,尤其适用于边缘检测前的预处理。文章详细阐述了其原理,包括各向异性、各向异性扩散的概念,以及如何通过选择性平滑过程,在去除噪声的同时保持图像边缘特征。此外,还提供了具体的代码实现。

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

4. 各向异性扩散滤波

本文作者:进击的CV 转载请注明

目录

4. 各向异性扩散滤波

4.1 处理效果展示

图像处理前后对比

4.2 各向异性扩散滤波原理

4.2.1 概念

4.2.2 原理

4.3 代码展示


4.1 处理效果展示

图像处理前后对比

处理前 

处理后

4.2 各向异性扩散滤波原理

4.2.1 概念

各向异性扩散滤波(Anisotropic Filter),同中值滤波、高斯滤波一样,也是一种滤除图像噪音的方法。可以用于边缘检测或提取之前的预处理,去除无关噪声,增加边缘的有效性。某些基于各向异性滤波的边缘提取算法,在滤波的同时还能兼顾边缘保持。要了解各向异性扩散滤波,先来了解几个概念:各向异性,各向异性扩散。

各向异性,指物体的全部或者部分物理、化学性质随方向的不同而有所变化的特性。例如石墨单晶的电导率在不同方向的差异可达数千倍,又如天文学上,宇宙微波背景辐射亦拥有些微的各向异性。许多的物理量都具有各向异性,如弹性模量、电导率、在酸中的溶解速度等。

各向异性扩散,是有选择性的平滑(扩散)过程,这种选择是指方向选择的非均匀性,这种平滑过程在均匀的区域不受限制,而在跨越边界部分被抑制,因此在平滑噪声的同时保持图像的边缘特征。

4.2.2 原理

假设图像为I,滤波公式如下:

        I{_{t+1}}= I{​{_{t}}^{}}+\lambda (cN{​{_{x,y}}\triangledown {​{_{N}}^{}}(I{​{_{t}}^{}}) }+cS{​{_{x,y}}\triangledown {​{_{s}}^{}}(I{​{_{t}}^{}}) }+cE{​{_{x,y}}\triangledown {​{_{E}}^{}}(I{​{_{t}}^{}}) }+cW{​{_{x,y}}\triangledown {​{_{W}}^{}}(I{​{_{t}}^{}}) } )

从上式可以看出,各向异性扩散滤波依然是求出核窗口内邻域权值,再进行加权相加,作为当前点的灰度值。其中,t代表迭代次数;△表示梯度算子,四个方向的梯度公式如下:

由上式可以看出,在灰度值变化不大的区域,等号左边的数值可正可负,也变化不大。但是,若在一个方向上出现了边界,即灰度值变化较大,等号左边会出现绝对值较大的数值。

c表示扩散系数,四个方向上的扩散系数计算如下:

           

由上式可以看出,在灰度值变化不大的区域,等号左边的数值接近或等于1,但是在灰度值变化较大的区域,比如边界,等号左边的数值就会接近或逼近0。

注意:在这里热传导系数K越大,图像越平滑;整个公式需要设置的参数主要有三个,迭代次数 t,根据情况设置;导热系数相关的 k,取值越大,结果越平滑,越不易保留边缘;λ 取值越大,结果越平滑。

讲到这里,我们可以看出各向异性扩散滤波与其他方法的不同。(1)应用方面,该方法滤除噪声时,保边效果好(2)原理方面,将图像看做热量场,所进行的操作完全依照热量场内热的传播原理;(3)核窗口为十字形,而非N×N的矩阵。

4.3 代码展示

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

float k = 15;
float lambda = 0.25;
int N = 5;

void anisotropy_demo(Mat &image, Mat &result);

int main(int argc, char** argv) 
{
	Mat src = imread("C:\\Users\\SYYSP\\Desktop\\BLOG\\imageMaterial\\GaoQueenOri.jpg");
	if (src.empty()) 
	{
		printf("could not load image...\n");
		return -1;
	}
	namedWindow("input image", CV_WINDOW_AUTOSIZE);
	imshow("input image", src);
	vector<Mat> mv;
	vector<Mat> results;
	split(src, mv);
	for (int n = 0; n < mv.size(); n++) 
	{
		Mat m = Mat::zeros(src.size(), CV_32FC1);
		mv[n].convertTo(m, CV_32FC1);
		results.push_back(m);
	}

	int w = src.cols;
	int h = src.rows;
	Mat copy = Mat::zeros(src.size(), CV_32FC1);
	for (int i = 0; i < N; i++) 
	{
		anisotropy_demo(results[0], copy);
		copy.copyTo(results[0]);

		anisotropy_demo(results[1], copy);
		copy.copyTo(results[1]);

		anisotropy_demo(results[2], copy);
		copy.copyTo(results[2]);
	}
	Mat output;
	normalize(results[0], results[0], 0, 255, NORM_MINMAX);
	normalize(results[1], results[1], 0, 255, NORM_MINMAX);
	normalize(results[2], results[2], 0, 255, NORM_MINMAX);

	results[0].convertTo(mv[0], CV_8UC1);
	results[1].convertTo(mv[1], CV_8UC1);
	results[2].convertTo(mv[2], CV_8UC1);

	Mat dst;
	merge(mv, dst);

	imshow("result", dst);
	imwrite("C:\\Users\\SYYSP\\Desktop\\BLOG\\imageMaterial\\GaoQueenOri_AnisotropicDiffusionFilter.jpg", dst);
	waitKey(0);
	return 0;
}

void anisotropy_demo(Mat &image, Mat &result) 
{
	int width = image.cols;
	int height = image.rows;

	// 四邻域梯度
	float n = 0, s = 0, e = 0, w = 0;
	// 四邻域系数
	float nc = 0, sc = 0, ec = 0, wc = 0;
	float k2 = k * k;
	for (int row = 1; row < height - 1; row++) 
	{
		for (int col = 1; col < width - 1; col++) 
		{
			// gradient
			n = image.at<float>(row - 1, col) - image.at<float>(row, col);
			s = image.at<float>(row + 1, col) - image.at<float>(row, col);
			e = image.at<float>(row, col - 1) - image.at<float>(row, col);
			w = image.at<float>(row, col + 1) - image.at<float>(row, col);
			nc = exp(-n * n / k2);
			sc = exp(-s * s / k2);
			ec = exp(-e * e / k2);
			wc = exp(-w * w / k2);
			result.at<float>(row, col) = image.at<float>(row, col) + lambda * (n*nc + s * sc + e * ec + w * wc);
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值