【学习图像处理】空域滤波增强

图像处理与识别学习小结 阅读详情

一、空域滤波增强

1、原理介绍

空域滤波,即在空间上对图像进行滤波处理,其目的往往在于消除图像噪声,锐化突出边缘部分等,总之使得处理后的图像在某些方面比原图像更适合当前应用。
相比于频域滤波,空域滤波的原理很简单。我们取一个 m ∗ n m*n m∗n的空域模板(多数情况下,我们用 n ∗ n n*n n∗n的正方形模板,n为奇数)作为图像的处理依据,一般也称作空域滤波器。下图右侧即为一个模板,左侧为原图与模板等大的一部分:
空域滤波器
模板每一个小格内的数值表示权值或者出现次数(出现次数仅对于中值滤波)。对于平滑滤波,我们将原图像的像素值与模板权值相乘,并对所有对应位置求得的乘积进行加和,即:
R = ∑ s = − a a ∑ t = − b b w ( s , t ) f ( x + s , y + t ) R=\sum_{s=-a}^a\sum_{t=-b}^bw(s,t)f(x+s,y+t) R=s=−a∑a​t=−b∑b​w(s,t)f(x+s,y+t)
其中 a = ( m − 1 ) 2 a=\frac{(m-1)}{2} a=2(m−1)​, b = ( n − 1 ) 2 b=\frac{(n-1)}{2} b=2(n−1)​
R值,即为模板正中央那个像素点在结果图像中的像素值(需要转换为0-255之间的值)。我们逐点平移模板,确定结果图像中所有像素点的值。
当然你可能也发现了,这样求得的新图,相比原图来说最外围一圈的像素值都丢失了。为了解决这个问题,我们可以在滤波之前适当的进行边界延拓。比如一个3*3的模板,那么我们可以将最外围一圈的像素值向外复制一层,这样滤波之后的图像就不会有像素缺失。不过由于现今我们图像的分辨率都很高,而损失的像素占比太少,因此下面的代码中不涉及这一步操作。

2、代码实现

从前面空域滤波的原理来看,其实现并不复杂,我们只需要找到图像与模板对应的位置做乘积后求和即可。这里需要注意将R值转化到0-255之间的问题即可。

void Spatialfilter(BMPFILE &src, BMPFILE &des, float *w, int m, int n)
//空域滤波,src为原图像,des为输出图像,w为模板(一维数组保存,下标取值为m*i+j),m、n分别为模板的长与宽(一般为3*3,7*7这样的)
{
	//没有做边界延拓
	int i, j, s, t;
	int A = (m - 1) / 2, B = (n - 1) / 2;	//模板下标的边界值
	float r = 0, g = 0, b = 0;
	for (i = A; i <= src.imagew - A; i++)
		for (j = B; j <= src.imageh - B; j++)	//对目标图像的每个像素
		{
			r = 0, g = 0, b = 0;	//目标图像当前位置像素值,置零
			if (src.iYRGBnum == 1)	//如果是灰度图
			{
				for (s = -A; s <= A; s++)
					for (t = -B; t <= B; t++)	//对模板范围内的"像素值*模板权值"求和
					{
						r += (float)src.pDataAt(i + s)[j + t] * w[(s + A)*m + (t + B)];
					}
				if (r < 0)	//注意r应在0-255之间
					r = 0;
				r = (int)r % 256;
				des.pDataAt(i)[j] = (BYTE)r;
			}
			else	//如果是彩图
			{
				for (s = -A; s <= A; s++)
					for (t = -B; t <= B; t++)	//对模板范围内的"像素值*模板权值"求和
					{
						r += (float)src.pDataAt(i + s, 0)[j + t] * w[(s + A)*m + (t + B)];
						g += (float)src.pDataAt(i + s, 1)[j + t] * w[(s + A)*m + (t + B)];
						b += (float)src.pDataAt(i + s, 2)[j + t] * w[(s + A)*m + (t + B)];
					}
				if (r < 0)
					r = 0;
				if (g < 0)
					g = 0;
				if (b < 0)
					b = 0;
				r = (int)r % 256;
				g = (int)g % 256;
				b = (int)b % 256;
				des.pDataAt(i, 0)[j] = (BYTE)r;
				des.pDataAt(i, 1)[j] = (BYTE)g;
				des.pDataAt(i, 2)[j] = (BYTE)b;
			}
		}
	des.SaveBMPFILE("FiltedImage.bmp");
}

二、平滑滤波

1、滤波器特点

平滑滤波是一种低通滤波,对于灰度图像而言就是过滤掉图像中灰度变化较快的部分。平滑滤波的滤波器其主要特征是权值加和为1,如下图(注意每小块权值是 1 9 \frac{1}{9} 91​):
平滑滤波器

2、代码实现

这里所谓的代码实现其实就是给我们的空域滤波函数传入正确的参数。一些辅助函数的实现见文末的gitee传送门,或者你可以自己实现。

int main(int argc, char* argv[])
{
	//准备工作:读入图像
	BMPFILE bmpfile, bf,result;
	int i, j;
	if (!bmpfile.LoadBMPFILE("./srcImage/lena.bmp"))	//载入原始图像
		exit(1);	//不成功则退出

	//空域滤波主函数
	img_Clone(bmpfile, bf);	//复制信息头、文件头、数据域

	addSaltNoise(bf, 3000);	//给图像添加椒盐噪声

	img_Clone(bf, result);

	float w[9] = { 1,1,1,1,1,1,1,1,1 };

	for (i = 0; i < 9; i++)	//平滑滤波应当保证w和为1。锐化则和为0
	{
		w[i] /= (float)9;	//这里记得要强制类型转换
	}

	Spatialfilter(bf, result, w, 3, 3);

	return 0;
}
3、效果展示

彩图(左图为滤波结果,下同):

lena平滑滤波
灰度图:

平滑滤波pepper

三、锐化滤波

1、滤波器特点

上面的平滑滤波一般会使得图像变得模糊,从而让一些过于突出的细节(比如椒盐噪声)变得不明显。锐化滤波则相反,我们想要让图像中一些物体的轮廓、边缘等变得更加明显,实现的方法就是让“原本的边缘更加边缘”。其滤波器的特征为权值加和为0,如下是Sobel算子的权值(左侧为水平模板,加强的是垂直方向的边缘;右侧为垂直模板,加强的是水平方向的边缘):

在这里插入图片描述

2、代码实现

这里我们还是用正确的参数调用前面的空域滤波函数。但是要注意,这样的调用方式只能做到对水平或垂直单方向锐化,如果你需要同时对水平和垂直方向进行锐化,那么请自行修改上面的空域滤波函数(加入第二个方向的模板参数,分别对x、y方向乘积求和,将x、y的模值作为像素值)

int main(int argc, char* argv[])
{
	//准备工作:读入图像
	BMPFILE bmpfile, bf;
	int i, j;
	if (!bmpfile.LoadBMPFILE("./srcImage/cameraman.bmp"))	//载入原始图像
		exit(1);	//不成功则退出

	//空域滤波主函数
	img_Clone(bmpfile, bf);	//复制信息头、文件头、数据域

	float w[9] = { 1,2,1,0,0,0,-1,-2,-1 };	//Sobel水平模板

	Spatialfilter(bmpfile, bf, w, 3, 3);

	return 0;
}
3、效果展示

彩图:

在这里插入图片描述

灰度图:

在这里插入图片描述

四、中值滤波

1、滤波器特点

中值滤波其实在算法上是不同于上述两种滤波方式的。中值滤波器中的数值表示的是该像素在中值数组中的出现次数,举例来说,我们根据下面这个中值滤波器,应该能够得到数组M:
在这里插入图片描述
M = [ f 00 , f 01 , f 02 , f 10 , f 11 , f 11 , f 11 , f 12 , f 20 , f 21 , f 22 ] M=[f00,f01,f02,f10,f11,f11,f11,f12,f20,f21,f22] M=[f00,f01,f02,f10,f11,f11,f11,f12,f20,f21,f22]
我们将数组M内的像素值从小到大排序后,以居中位置的像素值作为结果图像在模板中心位置的像素值。

2、代码实现

同样的,从原理上看中值滤波的实现不是很难,我们只需要想办法得到中值数组即可。这里我用了三个数组分别去保存r、g、b的中值数组,一开始我犯了一个错误,在动态分配内存时误写为:

r = g = b = (float*)malloc(num * sizeof(float));

这样实际上将R、G、B指向了同一个地址,从而导致最终彩图的中值滤波结果为灰度图(因为R=G=B)。

void Medianfilter(BMPFILE &src, BMPFILE &des, float *w, int m, int n) //中值滤波函数
{
	int i, j, s, t;
	int A = (m - 1) / 2, B = (n - 1) / 2;	//模板下标的边界值
	int num = 0;	//计算求中值的数组中有多少元素
	for (i = 0; i < m*n; i++)
		num += w[i];
	float *r, *g, *b;
	r = (float*)malloc(num * sizeof(float));	//中值数组
	b = (float*)malloc(num * sizeof(float));
	g = (float*)malloc(num * sizeof(float));
	for (i = A; i < src.imagew - A; i++)
		for (j = B; j < src.imageh - B; j++)	//对目标图像的每个像素
		{
			memset(r, 0, num);	//中值数组置零
			memset(g, 0, num);
			memset(b, 0, num);
			if (src.iYRGBnum == 1)	//对于灰度图像只需要排序取中值
			{
				int index = 0;	//中值数组下标
				for (s = -A; s <= A; s++)
					for (t = -B; t <= B; t++)	//按照模板取像素值,保存到中值数组中
					{
						if (w[(s + A)*m + (t + B)] == 1)	//如果该像素只出现一次
						{
							r[index] = (float)src.pDataAt(i + s)[j + t];
							index++;
						}
						else
						{
							for (int n = 0; n < w[(s + A)*m + (t + B)]; n++)
							{
								r[index] = (float)src.pDataAt(i + s)[j + t];
								index++;
							}
						}
					}
				des.pDataAt(i)[j] = (BYTE)find_mid(r, m, n);
			}
			else //对于彩图我们分别对RGB求中值
			{

				int index = 0;
				for (s = -A; s <= A; s++)
					for (t = -B; t <= B; t++)	//按照模板取像素值,保存到中值数组中
					{
						if (w[(s + A)*m + (t + B)] == 1)	//如果该像素只出现一次
						{
							r[index] = (float)src.pDataAt(i + s, 0)[j + t];
							g[index] = (float)src.pDataAt(i + s, 1)[j + t];
							b[index] = (float)src.pDataAt(i + s, 2)[j + t];
							index++;
						}
						else
						{
							for (int n = 0; n < w[(s + A)*m + (t + B)]; n++)
							{
								r[index] = (float)src.pDataAt(i + s, 0)[j + t];
								g[index] = (float)src.pDataAt(i + s, 1)[j + t];
								b[index] = (float)src.pDataAt(i + s, 2)[j + t];
								index++;
							}
						}
					}
				des.pDataAt(i, 0)[j] = (BYTE)find_mid(r, m, n);
				des.pDataAt(i, 1)[j] = (BYTE)find_mid(g, m, n);
				des.pDataAt(i, 2)[j] = (BYTE)find_mid(b, m, n);
			}
		}
	des.SaveBMPFILE("Medianfilter.bmp");
	free(r);
	free(g);
	free(b);
}

int main(int argc, char* argv[])
{	
	//准备工作:读入图像
	BMPFILE bmpfile, bf, result;
	int i, j;
	if (!bmpfile.LoadBMPFILE("./srcImage/1.bmp"))	//载入原始图像
		exit(1);	//不成功则退出

	//中值滤波
	
	img_Clone(bmpfile, bf);

	addSaltNoise(bf, 3000);

	img_Clone(bf, result);

	float w[9] = { 1,1,1,1,3,1,1,1,1 };	//出现次数w	

	Medianfilter(bf, result, w, 3, 3);

	return 0;
}
3、效果展示

中值滤波的效果出奇的好,比前面的平滑滤波要好多了。

彩图:

中值滤波lena
灰度图:

在这里插入图片描述

结语

五一期间,没有新的实验任务(我猜下次实验可能是与图像压缩编码有关的),就把这周上课讲的滤波函数做一下。其实频域滤波我也尝试做了,但是我写的傅里叶变换是最原始的公式,运行相当之慢。在我弄明白快速傅里叶变换之前应该是不会更新频域滤波的。
本次实验完整的项目文件与代码可见我的gitee。

【数字图像处理】经典空域滤波算法 对于数字图像的处理,通常会用到各种的滤波操作,谈及滤波这个词,总会让人联想到信号处理中那一系列繁琐的转换计算公式,顿时觉得头昏脑胀。其实,若仅仅从空域来理解数字图像的滤波操作,便能够更加直观地理解整个滤波运算的过程。故此,整理了一些常用的空域滤波算法,分享给大家。 阅读详情

相关推荐

计算机视觉空域处理完整版——超详细图文解

在泛函分析中,卷积、旋积或褶积(英语:Convolution)是通过两个函数f和g生成第三个函数的一种数学算子,表征函数f与g经过翻转和平移的重叠部分函数值乘积对重叠长度的积分。信号与系统:卷积(convolution)

m0_64146991的博客 2005

空间域滤波、频率域滤波及其关系

空间域滤波、频率域滤波实现,以及使用傅里叶变换和卷积定理说明其等价性。 观察不同空间域卷积核对应的频谱图,从不同的角度理解其原理。

幻世 8891

空域图像增强-图像滤波处理

本文主要介绍了如何给数字图像添加高斯噪声和椒盐噪声, 如何使用MATLAB对含噪图像进行平滑滤波处理、中值滤波处理, 以及对含高斯噪声的图像用多幅图像取平均的方法降噪.

weixin_42048463的博客 2171

图像的空域滤波与频域滤波

总而言之,空域滤波和频域滤波是两种不同的图像处理方法。而频域滤波则通过转换到频率域进行操作,可以更灵活地处理图像频谱信息,适用于一些特定的图像处理问题。空域滤波(Spatial domain filtering)是一种直接在图像的像素空间进行操作的滤波方法。频域滤波的优势在于可以更灵活地调整滤波器的频率响应,以实现不同的滤波效果。在空域滤波中,滤波器的大小和形状是决定滤波效果的关键因素。图像的空域滤波和频域滤波是两种常用的图像处理方法,它们采用不同的处理思路和技术。

2573

从信号处理到深度学习:PyTorch中傅里叶变换的跨领域应用

本文探讨了PyTorch中傅里叶变换的跨领域应用,从信号处理到深度学习的创新实践。通过详细介绍傅里叶变换的数学原理、PyTorch实现及在图像处理、音频信号处理等领域的实际案例,展示了这一经典数学工具在现代AI技术中的强大潜力。

weixin_29075633的博客 369

【Matlab图像去噪】空域+频域滤波图像去噪【含GUI源码 914期】

一、代码运行视频(哔哩哔哩) 【Matlab图像去噪】空域+频域滤波图像去噪【含GUI源码 914期】 二、matlab版本及参考文献 1 matlab版本 2014a 2 参考文献 [1] 蔡利梅.MATLAB图像处理——理论、算法与实例分析[M].清华大学出版社,2020. [2]杨丹,赵海滨,龙哲.MATLAB图像处理实例详解[M].清华大学出版社,2013. [3]周品.MATLAB图像处理与图形用户界面设计[M].清华大学出版社,2013. [4]刘成龙.精通MATLAB图像处理[M].清华大学出

订阅付费专栏Matlab(奶茶价版),可赠送奶茶价版付费专栏指定代码1份; 363

《DIP数字图像处理》复习笔记--2.灰度变换与空间滤波(图像运算,图像增强,直方图修改技术,空域滤波-图像平滑、中值滤波、线性滤波,什么是卷积,图像边界处理策略,图像锐化-梯度算子、拉普拉斯算子)

根据“冈萨雷斯《数字图像处理》(第四版)”教材,系统介绍了图像增强、滤波、编码和分割等基础知识,图像增强技术通过灰度变换、锐化和滤波等手段,提升图像质量,利于识别和分析。空域与频域处理结合逻辑、算术运算,用于噪声抑制与细节增强,广泛用于医学、遥感等领域。

zhuai.blog.youkuaiyun.com 2166

MATLAB图像空域增强技术指南:从基础到实践

本文还有配套的精品资源,点击获取 简介:本教程为图像处理新手提供了一个系统的学习路径,通过介绍MATLAB基础和空域增强技术,帮助学生掌握图像增强的操作和原理。教程详细讲述了线性变换、非线性变换、直方图均衡化和图像滤波等关键概念,并通过实例教学加深理解。内容涵盖从简单的读取、显示、保存图像到复杂的图像处理操作,旨在为学习者提供实操经验,增强图像处理能力。 MATLAB(Matrix Laboratory的缩写)最初由Cleve Moler教授在1980

weixin_42601547的博客 482

MATLAB数字图像处理初步

图像的代数运算函数使用以下截取规则使运算结果符合数据范围的要求:超出数据范围的整型数据将被截取为数据范围的极值,分数结果将被四舍五入。图像的代数运算函数使用以下截取规则使运算结果符合数据范围的要求:超出数据范围的整型数据将被截取为数据范围的极值,分数结果将被四舍五入。两幅图像的像素值相加时产生的结果很可能超过图像数据类型所支持的最大值,尤其对于uint8类型的图像,溢出情况最为常见。两幅图像的像素值相加时产生的结果很可能超过图像数据类型所支持的最大值,尤其对于uint8类型的图像,溢出情况最为常见。

m0_75211241的博客 1383

流媒体协议-RTMP简介

与rtsp 不同,RTSP(Real-Time Streaming Protocol)是一个控制协议,负责控制媒体流的传输,但不传输媒体数据本身。RTSP 可以通过 TCP 或 UDP 传输 RTP 包来传输音视频数据。 RTMP(Real-Time Messaging Protocol)是一个综合性的协议,不仅可以传输音视频数据,还可以传输信令控制指令。RTMP 使用 TCP 作为传输协议,可以直接在 TCP 连接上传输音视频数据,也可以传输控制指令,实现了音视频流的实时传输和控制

xiaoshuaijinniu的博客 4548

华为海思2026届数字IC秋招笔试真题解析与实战技巧(2025最新版)

本文深度解析华为海思2026届数字IC秋招笔试真题,涵盖高频考点如后端设计、低功耗设计、SystemVerilog语法等核心内容。提供时序违例修复、时钟树综合等实战技巧,帮助考生高效备考。特别关注UPF低功耗设计规范等最新考点,助力考生在秋招笔试中脱颖而出。

lg888的博客 1088

数字图像处理完整指南:西北工业大学Python实现教程

想要掌握**数字图像处理**的核心技术吗?西北工业大学(NWPU)的nwpu-cram项目为你提供了完整的**数字图像处理**学习资源,从基础理论到Python实战代码,帮助初学者快速入门!🎯 **数字图像处理**是现代计算机视觉和人工智能的基础,广泛应用于医疗影像、自动驾驶、安防监控等领域。通过nwpu-cram项目,你可以获得西北工业大学计算机视觉课程的完整学习资料,包括理论讲解、实验代码

gitblog_00421的博客 307

NX工程图避坑指南:唐康林老师视频里没细说的10个实用技巧与隐藏设置

本文深入解析NX工程图中10个易被忽视的实用技巧与隐藏设置,涵盖视图更新、剖面线自定义、标注样式统一等核心问题。特别针对UG/NX8.5/NX10用户,提供从首选项设置到打印优化的完整解决方案,帮助工程师避开常见陷阱,提升制图效率与规范性。

weixin_28683689的博客 575

【图像处理】噪声模型和降噪附Matlab代码

图像在获取、传输和处理过程中不可避免地会受到各种噪声的干扰,这些噪声会严重影响图像的视觉质量和后续处理(如特征提取、目标识别)的准确性。本文系统地阐述了图像中常见的噪声模型,包括高斯噪声、椒盐噪声、瑞利噪声、指数噪声、伽马噪声、均匀噪声以及周期噪声,并深入分析了它们的产生机理和统计特性。在此基础上,本文详细介绍了多种图像降噪技术,涵盖了空域滤波方法(如均值滤波、中值滤波、高斯滤波、双边滤波、非局部均值滤波)和频域滤波方法(如傅里叶变换滤波),并对各种方法的原理、优缺点及其适用场景进行了比较分析。

j_jinger的博客 365

强化学习 reward 曲线可视化:从基础绘制到顶刊级对比分析

本文详细介绍了强化学习reward曲线的可视化方法,从基础绘制到顶刊级对比分析。通过matplotlib和seaborn的实战示例,展示了如何优化曲线图的视觉效果,包括多实验对比、置信区间添加和分面图应用。文章还分享了顶刊级图表的进阶技巧,如字体排版、颜色选择和关键标注,帮助研究者提升论文图表质量。

weixin_29096377的博客 268

Ubuntu零基础入门到精通【3.10讲】:旧版本 Ubuntu 升级与迁移路线:从 20.04 到 24.04 的完整实战指南

🏆 本文收录于 《滚雪球学 Ubuntu》 专栏。 本专栏面向有一定计算机基础,但尚未系统学习 Linux / Ubuntu 的读者,采用“滚雪球式学习法”:先装好、再会用、再理解、再优化、再实战,带你从第一次进入 Ubuntu 桌面 / 终端开始,逐步掌握 Ubuntu 的日常使用、命令操作、软件安装、系统配置、开发环境搭建与服务器部署能力。

**My Coding Family** 1239

数字图像处理:从像素矩阵到视觉智能的实践指南

本文系统阐述了数字图像处理的核心原理与实践方法。从图像的像素矩阵表示、采样量化等基础概念出发,详细讲解了空间域增强、彩色与形态学处理、频率域分析及图像压缩等关键技术。文章不仅覆盖了传统图像处理算法,还探讨了其与深度学习(如CNN)结合的现代应用,为读者提供了从基础到前沿的完整实践指南。

qqq44的博客 542

数字图像处理期末总结

captaincoke的博客 671

Open3D 计算点云模型的表面积和体积【2025最新版】

python编程实现 计算点云模型的表面积和体积,博客长期更新,本文最近一次更新时间为:2025年4月4日。

点云侠的博客 13万+

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

漫谈《数字图像处理》之经典空域边缘检测Canny与LOG

本文对比分析了数字图像处理中两种经典边缘检测算法:Canny和LOG(高斯拉普拉斯)。Canny算法通过高斯滤波降噪、计算梯度、非极大值抑制和双阈值判断等步骤,实现精准、连续的边缘检测,但实现较复杂且依赖人工调参。LOG算法则采用高斯平滑结合拉普拉斯算子计算零交叉点的方式,原理简单但对噪声敏感且边缘定位精度低。两者都基于“灰度突变”原理,共享传统方法的局限性,如人工调参依赖和抗噪声能力不足。实际应用中,Canny更适用于需要高精度边缘的工程场景,而LOG适合教学演示和对弱边缘检测要求不高的场景

YouJT2002的博客 954

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

上一篇: 【学习机器学习】线性模型相关方程求解
下一篇: 【学习图像处理】之实验三——图像编码之赫夫曼编码
Morphlng
博客等级 码龄8年 1157粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值