使用visual Studio MFC 平台实现对灰度图添加椒盐噪声,并进行均值滤波与中值滤波
平滑处理–滤波
本文使用visual Studio MFC 平台实现对灰度图添加椒盐噪声,并进行均值滤波与中值滤波
关于其他MFC单文档工程可参考
01-Visual Studio 使用MFC 单文档工程绘制单一颜色直线和绘制渐变颜色的直线02-visual Studio MFC 绘制单一颜色三角形、渐变颜色边框三角形、渐变填充三角形、边框渐变的正方形与填充渐变的正方形实例
文章目录
- 平滑处理--滤波
- 一、添加椒盐噪声
- 1.1 添加椒盐噪声的原理
- 1.2 添加椒盐噪声的代码实现
- 1.3 添加椒盐噪声后的效果
- 二、均值滤波
- 2.1 均值滤波的原理
- 2.2 均值滤波的代码实现
- 2.3 均值滤波的实验效果
- 三、 中值滤波
- 3.1 中值滤波的原理
- 3.2 中值滤波的C++实现
- 3.3中值滤波后的效果图
一、添加椒盐噪声
1.1 添加椒盐噪声的原理
添加椒盐噪声是一种常见的图像噪声引入方式,其原理是在图像中随机选择一些像素点,并将这些像素点的灰度值设置为最大或最小值,通常是白色(最大值)或黑色(最小值)。这样的噪声模拟了图像中出现的随机强烈亮或暗的噪声点,类似于椒盐的颗粒,因此得名。
具体步骤如下:
-
选择噪声点: 在图像中随机选择一些像素点作为噪声点。
-
设定噪声值: 对于每个选定的噪声点,将其灰度值设定为最大值(白色)或最小值(黑色)。
这样就在图像中引入了椒盐噪声,这种噪声形式使图像中的某些区域变得非常亮或非常暗,从而增加了图像的复杂性和难度。
椒盐噪声主要用于模拟一些特殊环境下的图像问题,例如图像采集中的传感器错误、传输中的丢包等情况。在图像处理中,去除或减轻椒盐噪声的方法通常包括滤波技术,例如中值滤波。
1.2 添加椒盐噪声的代码实现
//添加椒盐噪声
void CMFCApplication1View::OnAddsaltpeppernoise()
{// TODO: 在此添加命令处理程序代码if (gray_data != nullptr) {// 获取绘图设备CClientDC dc(this);CDC* pDC = &dc;// 创建临时数组用于保存添加噪声后的数据noisy_data = new unsigned char[bmpWidth * bmpHeight];// 复制原始数据到临时数组std::copy(gray_data, gray_data + bmpWidth * bmpHeight, noisy_data);// 添加椒盐噪声srand(static_cast<unsigned int>(time(nullptr))); // 初始化随机数种子const double saltPepperRatio = 0.01; // 椒盐噪声比例for (int i = 0; i < bmpWidth * bmpHeight; ++i) {double randomValue = static_cast<double>(rand()) / RAND_MAX;if (randomValue < saltPepperRatio / 2) {noisy_data[i] = 0; // 添加椒噪声}else if (randomValue < saltPepperRatio) {noisy_data[i] = 255; // 添加盐噪声}}// 绘制带有椒盐噪声的图像m_pBmp->drawGrayBmp(pDC, noisy_data, bmpWidth, bmpHeight, offset_left+2*bmpWidth, offset_top + 3 * bmpHeight);
关于上面将原来灰度图的数据
复制
到新的数组noisy_data中的目的是为了保留添加椒盐噪声后的灰度图的数据,以便后面的平滑操作
1.3 添加椒盐噪声后的效果
二、均值滤波
2.1 均值滤波的原理
均值滤波是一种常见的图像平滑处理方法,其原理基于对图像的像素值进行平均运算。这种滤波方法主要用于去除图像中的噪声或细小的细节,以产生更平滑的图像。
具体步骤如下:
-
定义卷积核: 选择一个固定大小的卷积核,通常是一个正方形的矩阵。卷积核的大小取决于应用场景和对平滑度的需求。
-
卷积操作: 将卷积核应用于图像的每个像素。对于每个像素,将其与卷积核中对应位置的像素相乘,然后将所有乘积的和除以卷积核的总权重。这个和的结果就是卷积核中心像素的新值。
-
更新图像: 将卷积操作得到的新值赋予原始图像相应位置的像素,形成平滑后的图像。
均值滤波的效果在平滑图像的同时,会导致图像失真,特别是对边缘和细节的处理较为粗糙。这是因为平均操作会模糊图像,擦除图像中的高频信息。
公式表示如下,其中 M 为卷积核的大小,f(x, y) 为原始图像,h(i, j) 为卷积核中的权重:
g ( x , y ) = 1 M ∑ i = 1 M ∑ j = 1 M h ( i , j ) ⋅ f ( x + i , y + j ) g(x, y) = \frac{1}{M} \sum_{i=1}^{M} \sum_{j=1}^{M} h(i, j) \cdot f(x+i, y+j) g(x,y)=M1i=1∑Mj=1∑Mh(i,j)⋅f(x+i,y+j)
其中,g(x, y)是滤波后的像素值。
2.2 均值滤波的代码实现
//均值滤波
void CMFCApplication1View::OnMeanfilter()
{// TODO: 在此添加命令处理程序代码if (noisy_data != nullptr) {// 获取绘图设备CClientDC dc(this);CDC* pDC = &dc;// 创建临时数组用于保存均值滤波后的数据unsigned char* filtered_data = new unsigned char[bmpWidth * bmpHeight];// 设置均值滤波的卷积核大小(3x3)const int kernelSize = 3;const int kernelHalfSize = kernelSize / 2;// 应用均值滤波for (int y = kernelHalfSize; y < bmpHeight - kernelHalfSize; ++y) {for (int x = kernelHalfSize; x < bmpWidth - kernelHalfSize; ++x) {int sum = 0;// 计算卷积核内的像素值之和for (int ky = -kernelHalfSize; ky <= kernelHalfSize; ++ky) {for (int kx = -kernelHalfSize; kx <= kernelHalfSize; ++kx) {int pixelValue = noisy_data[(y + ky) * bmpWidth + (x + kx)];sum += pixelValue;}}// 计算均值并赋值给滤波后的像素filtered_data[y * bmpWidth + x] = static_cast<unsigned char>(sum / (kernelSize * kernelSize));}}// 绘制均值滤波后的图像m_pBmp->drawGrayBmp(pDC, filtered_data, bmpWidth, bmpHeight, offset_left + 3 * bmpWidth, offset_top + 3 * bmpHeight);// 在图片下方添加文字GdiplusStartupInput gdiplusStartupInput;ULONG_PTR gdiplusToken;GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);{Graphics graphics(pDC->m_hDC);Gdiplus::Font font(L"Arial", 12);SolidBrush brush(Color(255, 128, 0, 128)); // 文字颜色为紫色// 文字的位置PointF point(offset_left +3* bmpWidth, offset_top + 4 * bmpHeight);// 绘制文字graphics.DrawString(L"均值滤波后的图像", -1, &font, point, &brush);}// 释放临时变量的内存delete[] filtered_data;GdiplusShutdown(gdiplusToken);}else {// 处理图像未加载的情况AfxMessageBox(_T("未加载图片"));}
}
2.3 均值滤波的实验效果
三、 中值滤波
3.1 中值滤波的原理
中值滤波是一种非线性滤波方法,它的原理是用像素点邻域灰度值的中值来代替该像素点的灰度值。中值滤波不会改变图像的灰度平均值,但可以有效地去除图像中的椒盐噪声等离群点,对于保持图像边缘细节方面也有一定的优势。
中值滤波的步骤如下:
-
选择滤波模板大小: 中值滤波通常采用3×3、5×5等奇数大小的模板。选择模板的大小会影响滤波效果。
-
将模板覆盖在图像的每个像素点上: 以当前像素为中心,取模板中所有像素的灰度值。
-
对模板中的灰度值进行排序: 将模板中的灰度值按升序或降序排列。
-
取排序后的中值: 选取排序后的中间值作为当前像素的新灰度值。
-
重复该过程: 将模板在整个图像上滑动,对每个像素应用相同的操作。
中值滤波的优点在于能够有效地去除椒盐噪声,但在一些情况下可能会导致图像细节模糊。它特别适用于去除局部性较强的噪声。
3.2 中值滤波的C++实现
//中值滤波
void CMFCApplication1View::OnMedianfilter()
{// TODO: 在此添加命令处理程序代码if (noisy_data != nullptr) {// 获取绘图设备CClientDC dc(this);CDC* pDC = &dc;// 创建临时数组用于中值滤波处理unsigned char* median_filtered_data = new unsigned char[bmpWidth * bmpHeight];// 中值滤波的处理代码int filter_size = 3; // 中值滤波的邻域大小,可以根据实际情况调整int filter_radius = filter_size / 2;for (int y = filter_radius; y < bmpHeight - filter_radius; ++y) {for (int x = filter_radius; x < bmpWidth - filter_radius; ++x) {// 获取邻域内的像素值std::vector<unsigned char> neighborhood;for (int j = -filter_radius; j <= filter_radius; ++j) {for (int i = -filter_radius; i <= filter_radius; ++i) {neighborhood.push_back(noisy_data[(y + j) * bmpWidth + (x + i)]);}}// 对邻域内的像素值进行排序std::sort(neighborhood.begin(), neighborhood.end());// 计算中值并赋值给当前像素median_filtered_data[y * bmpWidth + x] = neighborhood[filter_size * filter_size / 2];}}// 绘制中值滤波后的图像m_pBmp->drawGrayBmp(pDC, median_filtered_data, bmpWidth, bmpHeight, offset_left + 4 * bmpWidth, offset_top + 3 * bmpHeight);// 在图片下方添加文字GdiplusStartupInput gdiplusStartupInput;ULONG_PTR gdiplusToken;GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);{Graphics graphics(pDC->m_hDC);Gdiplus::Font font(L"Arial", 12);SolidBrush brush(Color(255, 128, 0, 128)); // 文字颜色为紫色// 文字的位置PointF point(offset_left + 4 * bmpWidth, offset_top + 4 * bmpHeight);// 绘制文字graphics.DrawString(L"中值滤波", -1, &font, point, &brush);}// 释放临时数组的内存delete[] median_filtered_data;GdiplusShutdown(gdiplusToken);}else {// 处理图像未加载的情况AfxMessageBox(_T("未加载图片"));}
}
3.3中值滤波后的效果图
相关文章:

使用visual Studio MFC 平台实现对灰度图添加椒盐噪声,并进行均值滤波与中值滤波
平滑处理–滤波 本文使用visual Studio MFC 平台实现对灰度图添加椒盐噪声,并进行均值滤波与中值滤波 关于其他MFC单文档工程可参考 01-Visual Studio 使用MFC 单文档工程绘制单一颜色直线和绘制渐变颜色的直线 02-visual Studio MFC 绘制单一颜色三角形、渐变颜色边…...

Django HMAC 请求签名校验与 Vue.js 实现安全通信
概要 在 Web 应用的开发过程中,确保数据传输的安全性和完整性是一个不容忽视的问题。使用 HMAC(Hash-based Message Authentication Code)算法对请求内容进行签名校验,是一种常见且有效的安全策略。本文将详细介绍如何在 Django …...

深度学习之循环神经网络
视频链接:6 循环神经网络_哔哩哔哩_bilibili 给神经网络增加记忆能力 对全连接层而言,输入输出的维数固定,因此无法处理序列信息 对卷积层而言,因为卷积核的参数是共享的,所以卷积操作与序列的长度无关。但是因为卷积…...

与原有视频会议系统对接
要实现与原有视频会议系统对接,需要确保通信协议的一致性。连通宝视频会议系统可与第三方视频会议系统对接。实现与第三方会议系统对接还可以使用会议室连接器,可以确保不同系统之间的数据传输和交互。 具体对接流程可能因不同品牌和类型的视频会议系统而…...

C# Serilog--可记录异常完整路径
1.Serilog安装 2.控制台代码 --设置日志记录器的最小级别为 Debug,即只记录 Debug 级别及以上的日志信息 --.WriteTo.File("logs\\log.txt", rollingInterval: RollingInterval.Day):将日志信息写入到指定路径的文件中(这里的路径…...

鉴源实验室 | 汽车网络安全攻击实例解析(三)
作者 | 张璇 上海控安可信软件创新研究院工控网络安全组 来源 | 鉴源实验室 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 引言:随着现代汽车技术的迅速发展,车辆的进入和启动方式经历了显著的演变。传统的物理钥匙逐渐被无钥匙进…...

php 中生成订单号
字母日期。。。。。。。 function setOrderNo($year 2011) {$yCode array(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);$orderSn $yCode[intval(date(Y)) - $year] . strtoupper(dechex(date(m))) . date(d) . substr(time(), -5) . s…...

Jmeter工具+ant+jenkins实现持续集成
jmeterantjenkins持续集成 一、下载并配置jmeter 首先下载jmeter工具,并配置好环境变量;参考: jmeter默认保存的是.jtl格式的文件,要设置一下bin/jmeter.properties,文件内容,保存jmeter.save.saveservice.output_f…...

基于SSM的经典电影推荐网站设计与实现
末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…...

JavaScript中使用JSON的基本操作示例
简介 JSON(JavaScript Object Notation)是一种数据交换格式,也是JavaScript中处理数据的常见方式之一。JSON是一种轻量级的数据交换格式,易于阅读和编写,同时也易于解析和生成。在JavaScript中,可以使用内…...

上拉、下拉电阻的作用
上拉、下拉电阻的作用 (1)一般作为单键触发使用,如果芯片本身没有内接电阻,为了使单键维持在不被触发的状态或触发后回到原状态,必须在芯片外部接一个电阻,即保持芯片引脚高电平(或低电平)输入,这样单击按键…...

docker部署elasticsearch+kibana+head
前言 最近,项目需要使用elasticsearch,所以就想快速安装一个使用,最开始是docker安装了7.10.1版本。 后面计划使用Java开发,发现有 RestHighLevelClient 和 Elasticsearch Java API Client两种客户端连接方式。 然后网上查阅了一…...

Linux:vim的简单使用
个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》《C》《Linux》 文章目录 前言一、vim的基本概念二、vim的基本操作三、vim正常模式命令集四、vim底行模式命令集五、.xxx.swp的解决总结 前言 本文是对Linux中vim使用的总结 一、vim的基本概念 …...

Python---文件和文件夹操作
os模块 在Python中文件和文件夹的操作要借助os模块里面的相关功能,具体步骤如下: 第一步:导入os模块 import os 第二步:调用os模块中的相关方法 os.函数名() 与文件操作相关方法 编号函数功能1os.rename(目标文件名称&…...

electron-vue运用及案例代码
前言 Electron是一个使用JavaScript, HTML和CSS构建跨平台桌面应用程序的开源库。它允许开发者使用纯web技术创建原生应用程序,这使得web开发者能够利用他们已经掌握的web技术来构建桌面应用。 以下是一个简单的Electron应用程序的代码示例: // 引入Electron的主模块 co…...

视频字幕处理+AI绘画,Runway 全功能超详细使用教程(4)
runway的视频字幕处理、AI绘图功能介绍,感觉完全就是为了做电影而布局,一整套功能都上线了!想系统学习的必收藏! 在深度研究Runway各个功能后,无论是AI视频生成及后期处理技术,还是AI图像生成技术ÿ…...

令人疑惑的Promise相关问题
令人疑惑的Promise相关问题 问题1 const promise new Promise((resolve, reject) > {reject(Error(Error occurred)); });promise.catch(error > console.log(error.message)); promise.catch(error > console.log(error.message));输出: Error occurr…...

Spring 多数据源搭建
目录 前言 正文 1.Druid 介绍和使用 2.其他多数据源解决方案 总结 前言 对于复杂的业务和项目,可能在一个单体项目中存在需要连接多个数据库的情况。这时,就会使用到多数据源,实际中遇到的可能性比较大。 正文 如果一个项目中需要连…...

【二分查找】LeetCode1970:你能穿过矩阵的最后一天
本文涉及的基础知识点 二分查找算法合集 作者推荐 动态规划LeetCode2552:优化了6版的1324模式 题目 给你一个下标从 1 开始的二进制矩阵,其中 0 表示陆地,1 表示水域。同时给你 row 和 col 分别表示矩阵中行和列的数目。 一开始在第 0 …...

利用python连接MySQL数据库并执行相关sql操作
一、新建MySQL数据库 1.启动MySQL服务 打开phpstudy,开启MySQL服务。如果开启失败的话,可以打开任务管理器,把正在运行的mysqld服务的进程进行关闭,再次打开MySQL服务即可启动。 2.新建MySQL数据库 选择数据库,点击…...

jenkins配置
branch: "dev" 切换分支 $WORKSPACE: /var/lib/jenkins/workspace/jenkins任务名 dest_passwd服务器密码 变量 sudo sshpass -p $dest_passwd ssh root192.168.211.319 -tt rm -rf /data/patent/*:删除文件/data/patent/* sudo sshpa…...

LeNet对MNIST 数据集中的图像进行分类--keras实现
我们将训练一个卷积神经网络来对 MNIST 数据库中的图像进行分类,可以与前面所提到的CNN实现对比CNN对 MNIST 数据库中的图像进行分类-CSDN博客 加载 MNIST 数据库 MNIST 是机器学习领域最著名的数据集之一。 它有 70,000 张手写数字图像 - 下载非常简单 - 图像尺…...

Django的回顾的第4天
1.模型层 1.1简介 你可能已经注意到我们在例子视图中返回文本的方式有点特别。 也就是说,HTML被直接硬编码在 Python代码之中。 def current_datetime(request):now datetime.datetime.now()html "<html><body>It is now %s.</body><…...

点云从入门到精通技术详解100篇-基于三维点云的工件曲面轮廓检测与机器人打磨轨迹规划(中)
目录 2.2.2 散乱点云滤波去噪 2.2.3 海量点云数据压缩 2.3 点云采集与预处理实验...

Mapper文件夹在resource目录下但是网页报错找不到productMapper.xml文件的解决
报错如下: 我的Mapper文件夹在resourse目录下但是网页报错找不到productMapper.xml。 结构如下:代码如下:<mappers><mapper resource"com/dhu/mapper/productMapper.xml" /> </mappers> 这段代码是在mybatis-co…...

22.Oracle中的临时表空间
Oracle中的临时表空间 一、临时表空间概述1、什么是临时表空间2、临时表空间的作用 二、临时表空间相关语法三、具体使用案例1、具体使用场景示例2、具体使用场景代码示例 点击此处跳转下一节:23.Oracle11g的UNDO表空间点击此处跳转上一节:21.Oracle的程…...

附录A 指令集基本原理
1. 引言 本书主要关注指令集体系结构4个主题: 1. 提出对指令集进行分类的方法,并对各种方法的优缺点进行定性评估; 2. 提出并分析一些在很大程度上独立于特定指令集的指令集评估数据。 3. 讨论语言与编译器议题以及…...

Unittest单元测试之unittest用例执行顺序
unittest用例执行顺序 当在一个测试类或多个测试模块下,用例数量较多时,unittest在执行用例 (test_xxx)时,并不是按从上到下的顺序执行,有特定的顺序。 unittest框架默认根据ACSII码的顺序加载测试用例&a…...

海云安谢朝海:开发安全领域大模型新实践 人工智能助力高效安全左移
2023年11月29日,2023中国(深圳)金融科技大会成功举行,该会议是深圳连续举办的第七届金融科技主题年度会议,也是2023深圳国际金融科技节重要活动之一。做好金融工作,需要兼顾创新与安全,当智能体…...

Postman接口测试工具完整教程
前言 作为软件开发过程中一个非常重要的环节,软件测试越来越成为软件开发商和用户关注的焦点。完善的测试是软件质量的保证,因此软件测试就成了一项重要而艰巨的工作。要做好这项工作当然也绝非易事。 第一部分:基础篇 postman:4.5.1 1.安…...