技术标签: 个人笔记|数字图像处理(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();
}
看看结果
可以发现,黑的地方更黑了。
二. 灰度级膨胀运算
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();
}
看看结果
可以看到,黑的变细了,白圈变大了。
三. 灰度开运算
先腐蚀,再膨胀。可以去除相对于结构元素较小的明亮细节,保持整体的灰度和较大的明亮区域不变
四. 灰度闭运算
先膨胀,再腐蚀。可以去除相对于结构元素较小的暗细节,保持整体的灰度和较大的暗区域不变
五. 顶帽变换和底帽运算
顶帽变换通俗的讲就是原图减去开运算(先腐蚀,后膨胀,去白变黑)后的结果。而底帽运算闭运算(先膨胀,再腐蚀,去黑变白)减去原图的结果
文章浏览阅读1w次,点赞13次,收藏97次。整理5个优秀的微信小程序开源项目。收集了微信小程序开发过程中会使用到的资料、问题以及第三方组件库。_微信小程序开源模板
文章浏览阅读2.4k次。课程介绍云解析(Domain Name System,简称DNS)是一种高可用性、高可扩展的权威DNS服务和DNS管理服务。它的目的是为企业和开发者提供稳定、安全、智能的把网站域名或应用资源转换为计算机用于互连的数字 IP地址,从而将最终用户的访问路由到相应的网站或应用资源上同时提供DNS的管理服务。产品详情:https://wanwang.aliyun.com/domain/dns/_aiyun的云解析dns服务是什么
文章浏览阅读1.1k次。2020版本,也许其它安装类型的脚本也可以用同样的方式清理删除""文件夹,注意里面是配置文件,删除前记得备份。同时清理注册表。_mmd文件导入3ds max
文章浏览阅读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次。许愿墙 许下你的愿望_编程实现许愿墙的页面结构,效果图如下:
文章浏览阅读1.9w次,点赞2次,收藏3次。A公司准备对他下面的N个产品评选最差奖,评选的方式是首先对每个产品进行评分,然后根据评分区间计算相邻几个产品中最差的产品。评选的标准是依次找到从当前产品开始前M个产品中最差的产品,请给出最差产品的评分序列。_最差产品奖
文章浏览阅读1.3k次。首先,问题是如何出现的?晚上复查代码,发现一个activity没有调用自己的ondestroy方法我表示非常的费解,于是我检查了下代码。发现再finish代码之后接了如下代码finish();System.exit(0);//这就是罪魁祸首为什么这样写会出现问题System.exit(0);////看一下函数的原型public static void exit (int code)//Added ..._android 手动杀死app,activity不执行ondestroy
文章浏览阅读894次。Q: SylixOS 版权是什么形式, 是否分为<开发版税>和<运行时版税>.A: SylixOS 是开源并免费的操作系统, 支持 BSD/GPL 协议(GPL 版本暂未确定). 没有任何的运行时版税. 您可以用她来做任何 您喜欢做的项目. 也可以修改 SylixOS 的源代码, 不需要支付任何费用. 当然笔者希望您可以将使用 SylixOS 开发的项目 (不需要开源)或对 SylixOS 源码的修改及时告知笔者.需要指出: SylixOS 本身仅是笔者用来提升自己水平而开发的_select函数 导致堆栈溢出 sylixos
文章浏览阅读135次。我们要通过实现三个类,来实现一个web后端的全局异常管理功能,捕获controller层异常,封装成map集合,进行返回1.实现异常处理的工具类实现一个imooc.naga.core.exception,异常处理的包,定义两个类分别是:1.系统返回状态标识码实体类,2:封装了异常状态值,和异常信息内容的实体类1.系统返回状态标识码实体类package imooc.naga.core.exception;/** * 定义我们系统返回值的状态标志 */public class ErrorCo_naga数据分析平台
文章浏览阅读394次,点赞8次,收藏9次。fileFolder=fullfile('G:\气象数据\sitedata\day_temperature1951_2017');%将从该文件夹中提取的数据并入到上一个文件夹中的数据,;%如果该文件夹里有该站点的数据,则min_line不是空。_读取气象a文件
文章浏览阅读2.2k次。2016年0..._c#获取此电脑的便携设备信息
文章浏览阅读2.2k次,点赞5次,收藏9次。乐观锁是一种并发控制的策略,它假设多个线程在操作共享数据时,不会发生冲突,因此不需要加锁,而是在更新数据时,通过比较当前状态和上一次的状态,来判断是否有其他线程修改了数据。版本号控制的思想是,在数据表中增加一个版本号字段(或者时间戳字段),每次更新数据时,都将版本号加一(或者更新时间戳),并且在更新时,检查当前的版本号是否和数据库中的一致,如果一致,就执行更新操作;ABA问题是指,在一个线程执行CAS操作时,发现内存中的值没有变化(仍然为A),就认为没有其他线程修改过这个值,然后执行更新操作。_乐观锁