数字图像处理(八)形态学处理之灰度级腐蚀、膨胀、开运算、闭运算、顶帽变换和底帽变换_图像预处理 开运算 闭运算 膨胀 腐蚀 顶帽 底帽-程序员宅基地

技术标签: 个人笔记|数字图像处理(c++)  

本篇所有代码都是基于24位BMP图像

一. 灰度级腐蚀运算

灰度级腐蚀运算可以看成一种特殊的二维卷积运算,只不过用最小值运算代替了相关运算,用减法运算代替了相关运算的卷积操作。

灰度腐蚀运算时逐点进行的,计算该点局部范围内各点与结构元素对应点的灰度差,并选取差的最小值,作为该点的腐蚀结果。(先赋值255,再赋值差的最小值)

1.如果结构元素都是正的,则输出图像会比输入图像暗。

我们设结构元素3*3,且值都是0,看看代码

MFC中添加Menu,添加类向导

void CImageProcessingView::OnXtxHdfs()
{
	// TODO: 在此添加命令处理程序代码
	if (numPicture == 0)
	{
		AfxMessageBox("请输入一张图像", MB_OK, 0);
		return;
	}

	if (m_nBitCount != 24)
	{
		AfxMessageBox("输入图片不是24位", MB_OK, 0);
		return;
	}
	AfxMessageBox("灰度图像腐蚀!", MB_OK, 0);


	int num;//记录每一行需要填充的字节
	if (m_nWidth * 3 % 4 != 0)
	{
		num = 4 - m_nWidth * 3 % 4;
	}
	else
	{
		num = 0;
	}

	//打开临时的图片  
	FILE *fpo = fopen(BmpName, "rb");
	FILE *fpw = fopen(BmpNameLin, "wb+");
	fread(&bfh, sizeof(BITMAPFILEHEADER), 1, fpo);
	fread(&bih, sizeof(BITMAPINFOHEADER), 1, fpo);
	fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, fpw);
	fwrite(&bih, sizeof(BITMAPINFOHEADER), 1, fpw);
	fread(m_pImage, m_nImage, 1, fpo);
	unsigned char *ImageSize;
	ImageSize = new unsigned char[m_nImage];
	int x, y, val,xx,yy,temp;
	for (y = 1; y < m_nHeight - 1; y++)
	{
		for (x = 1; x < m_nWidth - 1; x++)
			//由于使用3*3的结构元素,防止越界,不处理最左边和最右边的的像素
		{
			val = 255;
			for (int j = 0; j < 3; j++)
			{
				yy = y + j - 1;
				for (int i = 0; i < 3; i++)
				{
					xx = x + i - 1;
					if (m_pImage[(xx + yy*m_nWidth) * 3 + yy * num] < val)//因为结构元素都是0,所以原图像中各点与对应结构元素想减还是原图像本身,
																		  //找想减后差的最小值作为点(x,y)的灰度
					{
						val = m_pImage[(xx + yy*m_nWidth) * 3 + yy * num];
					}
				}
			}
			ImageSize[(x + y*m_nWidth) * 3 + y*num] = unsigned char(val);
			ImageSize[(x + y*m_nWidth) * 3 + y*num + 1] = unsigned char(val);
			ImageSize[(x + y*m_nWidth) * 3 + y*num + 2] = unsigned char(val);
		}
	}

	fwrite(ImageSize, m_nImage, 1, fpw);

	fclose(fpo);
	fclose(fpw);
	numPicture = 2;
	level = 400;
	Invalidate();
}

看看结果


可以发现,黑的地方更黑了。

二. 灰度级膨胀运算

灰度级膨胀运算和腐蚀相反,是将原图像各点与对应结构元素中各相加,把相加后的最大值作为目标图像中当前点的灰度值

(先赋值0,再赋值最大值)

MFC中添加Menu,添加类向导,代码如下

void CImageProcessingView::OnXtxHdpz()
{
	// TODO: 在此添加命令处理程序代码
	if (numPicture == 0)
	{
		AfxMessageBox("请输入一张图像", MB_OK, 0);
		return;
	}

	if (m_nBitCount != 24)
	{
		AfxMessageBox("输入图片不是24位", MB_OK, 0);
		return;
	}
	AfxMessageBox("灰度图像膨胀!", MB_OK, 0);


	int num;//记录每一行需要填充的字节
	if (m_nWidth * 3 % 4 != 0)
	{
		num = 4 - m_nWidth * 3 % 4;
	}
	else
	{
		num = 0;
	}

	//打开临时的图片  
	FILE *fpo = fopen(BmpName, "rb");
	FILE *fpw = fopen(BmpNameLin, "wb+");
	fread(&bfh, sizeof(BITMAPFILEHEADER), 1, fpo);
	fread(&bih, sizeof(BITMAPINFOHEADER), 1, fpo);
	fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, fpw);
	fwrite(&bih, sizeof(BITMAPINFOHEADER), 1, fpw);
	fread(m_pImage, m_nImage, 1, fpo);
	unsigned char *ImageSize;
	ImageSize = new unsigned char[m_nImage];
	int x, y, val, xx, yy, temp;
	for (y = 1; y < m_nHeight - 1; y++)
	{
		for (x = 1; x < m_nWidth - 1; x++)
			//由于使用3*3的结构元素,防止越界,不处理最左边和最右边的的像素
		{
			val = 0;
			for (int j = 0; j < 3; j++)
			{
				yy = y + j - 1;
				for (int i = 0; i < 3; i++)
				{
					xx = x + i - 1;
					if (m_pImage[(xx + yy*m_nWidth) * 3 + yy * num] > val)//因为结构元素都是0,所以原图像中各点与对应结构元素想加还是原图像本身,
																		  //找和的最大值作为点(x,y)的灰度
					{
						val = m_pImage[(xx + yy*m_nWidth) * 3 + yy * num];
					}
				}
			}
			ImageSize[(x + y*m_nWidth) * 3 + y*num] = unsigned char(val);
			ImageSize[(x + y*m_nWidth) * 3 + y*num + 1] = unsigned char(val);
			ImageSize[(x + y*m_nWidth) * 3 + y*num + 2] = unsigned char(val);
		}
	}

	fwrite(ImageSize, m_nImage, 1, fpw);

	fclose(fpo);
	fclose(fpw);
	numPicture = 2;
	level = 400;
	Invalidate();
}

看看结果


可以看到,黑的变细了,白圈变大了。

三. 灰度开运算

先腐蚀,再膨胀。可以去除相对于结构元素较小的明亮细节,保持整体的灰度和较大的明亮区域不变

四. 灰度闭运算

先膨胀,再腐蚀。可以去除相对于结构元素较小的细节,保持整体的灰度和较大的暗区域不变

五. 顶帽变换和底帽运算

顶帽变换通俗的讲就是原图减去开运算(先腐蚀,后膨胀,去白变黑)后的结果。而底帽运算闭运算(先膨胀,再腐蚀,去黑变白)减去原图的结果


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hjxu2016/article/details/80738290

智能推荐

整理5个优秀的微信小程序开源项目_微信小程序开源模板-程序员宅基地

文章浏览阅读1w次,点赞13次,收藏97次。整理5个优秀的微信小程序开源项目。收集了微信小程序开发过程中会使用到的资料、问题以及第三方组件库。_微信小程序开源模板

云解析DNS使用教程_aiyun的云解析dns服务是什么-程序员宅基地

文章浏览阅读2.4k次。课程介绍云解析(Domain Name System,简称DNS)是一种高可用性、高可扩展的权威DNS服务和DNS管理服务。它的目的是为企业和开发者提供稳定、安全、智能的把网站域名或应用资源转换为计算机用于互连的数字 IP地址,从而将最终用户的访问路由到相应的网站或应用资源上同时提供DNS的管理服务。产品详情:https://wanwang.aliyun.com/domain/dns/_aiyun的云解析dns服务是什么

3dmax 使用中的遇到的问题_mmd文件导入3ds max-程序员宅基地

文章浏览阅读1.1k次。2020版本,也许其它安装类型的脚本也可以用同样的方式清理删除""文件夹,注意里面是配置文件,删除前记得备份。同时清理注册表。_mmd文件导入3ds max

页面跳转并数据传递-不同页面的传递数据_cshtml 跳转页面并传整行数据-程序员宅基地

文章浏览阅读4.6k次,点赞2次,收藏19次。1、第一个登录页面,里面有提交表单,action提交到index页面2、第二个页面,可以使用第一个页面的参数,实现一个数据不同页面之间的传递效果3、第二个页面之所以可以使用第一个页面的数据,就是利用了URL里面的location.search参数4、第二个页面提取参数5、去掉?6、分隔符分开表单form:可以将内容提交到另外一个页面上输入页面:<!DOCTYPE html><html lang="en"><head> ._cshtml 跳转页面并传整行数据

许愿墙 许下你的愿望_编程实现许愿墙的页面结构,效果图如下:-程序员宅基地

文章浏览阅读829次,点赞2次,收藏17次。许愿墙 许下你的愿望_编程实现许愿墙的页面结构,效果图如下:

【100%通过率】华为OD机试真题 Python 实现【最差产品奖】【2022.11 Q4 新题】-程序员宅基地

文章浏览阅读1.9w次,点赞2次,收藏3次。A公司准备对他下面的N个产品评选最差奖,评选的方式是首先对每个产品进行评分,然后根据评分区间计算相邻几个产品中最差的产品。评选的标准是依次找到从当前产品开始前M个产品中最差的产品,请给出最差产品的评分序列。_最差产品奖

随便推点

android 退出应用没有走ondestory方法,[Android基础论]为何Activity退出之后,系统没有调用onDestroy方法?...-程序员宅基地

文章浏览阅读1.3k次。首先,问题是如何出现的?晚上复查代码,发现一个activity没有调用自己的ondestroy方法我表示非常的费解,于是我检查了下代码。发现再finish代码之后接了如下代码finish();System.exit(0);//这就是罪魁祸首为什么这样写会出现问题System.exit(0);////看一下函数的原型public static void exit (int code)//Added ..._android 手动杀死app,activity不执行ondestroy

SylixOS快问快答_select函数 导致堆栈溢出 sylixos-程序员宅基地

文章浏览阅读894次。Q: SylixOS 版权是什么形式, 是否分为<开发版税>和<运行时版税>.A: SylixOS 是开源并免费的操作系统, 支持 BSD/GPL 协议(GPL 版本暂未确定). 没有任何的运行时版税. 您可以用她来做任何 您喜欢做的项目. 也可以修改 SylixOS 的源代码, 不需要支付任何费用. 当然笔者希望您可以将使用 SylixOS 开发的项目 (不需要开源)或对 SylixOS 源码的修改及时告知笔者.需要指出: SylixOS 本身仅是笔者用来提升自己水平而开发的_select函数 导致堆栈溢出 sylixos

企业级数据分析平台/springBoot-controller全局异常管理_naga数据分析平台-程序员宅基地

文章浏览阅读135次。我们要通过实现三个类,来实现一个web后端的全局异常管理功能,捕获controller层异常,封装成map集合,进行返回1.实现异常处理的工具类实现一个imooc.naga.core.exception,异常处理的包,定义两个类分别是:1.系统返回状态标识码实体类,2:封装了异常状态值,和异常信息内容的实体类1.系统返回状态标识码实体类package imooc.naga.core.exception;/** * 定义我们系统返回值的状态标志 */public class ErrorCo_naga数据分析平台

Matlab 读取批量txt格式的气象数据_读取气象a文件-程序员宅基地

文章浏览阅读394次,点赞8次,收藏9次。fileFolder=fullfile('G:\气象数据\sitedata\day_temperature1951_2017');%将从该文件夹中提取的数据并入到上一个文件夹中的数据,;%如果该文件夹里有该站点的数据,则min_line不是空。_读取气象a文件

Java乐观锁-程序员宅基地

文章浏览阅读2.2k次,点赞5次,收藏9次。乐观锁是一种并发控制的策略,它假设多个线程在操作共享数据时,不会发生冲突,因此不需要加锁,而是在更新数据时,通过比较当前状态和上一次的状态,来判断是否有其他线程修改了数据。版本号控制的思想是,在数据表中增加一个版本号字段(或者时间戳字段),每次更新数据时,都将版本号加一(或者更新时间戳),并且在更新时,检查当前的版本号是否和数据库中的一致,如果一致,就执行更新操作;ABA问题是指,在一个线程执行CAS操作时,发现内存中的值没有变化(仍然为A),就认为没有其他线程修改过这个值,然后执行更新操作。_乐观锁

推荐文章

热门文章

相关标签