使用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数据库 选择数据库,点击…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
快速排序算法改进:随机快排-荷兰国旗划分详解
随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...
麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...
java+webstock
maven依赖 <dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.3.5</version></dependency><dependency><groupId>org.apache.tomcat.websocket</groupId&…...
