使用VC++设计程序使用邻域平均平滑算法、中值滤波算法、K近邻均值滤波器(KNNF)进行滤波

VC++实现若干种图像滤波技术

文章目录

  • VC++实现若干种图像滤波技术
    • 实验内容
    • 邻域平均平滑算法
      • 1. 原理
      • 2. 实验代码
      • 3. 实验现象
    • 中值滤波算法
      • 1. 原理
      • 2. 实验代码
      • 3.实验现象
    • K近邻均值滤波算法(KNNF)
      • 1. 原理
      • 2. 实验代码
      • 实验现象

实验内容

实验要求:
A部分:
(1)使用VC++设计程序:对一幅256级灰度图像,使用邻域平均平滑算法进行滤波。
(2)使用VC++设计程序:对一幅256级灰度图像,使用中值滤波算法进行滤波。
(3)使用VC++设计程序:对一幅256级灰度图像,使用K近邻均值滤波器(KNNF)进行滤波。

邻域平均平滑算法

1. 原理

邻域平均平滑算法是一种简单的图像平滑处理方法,它通过将每个像素的灰度值替换为其邻域内像素灰度值的平均值来实现。对于256级灰度图像,以下是一种简单的邻域平均平滑算法的步骤:
1.选择滤波器的大小: 确定邻域的大小,例如选择3x3或5x5的滤波器。
2.遍历图像像素: 对于图像中的每个像素,将其与邻域内的像素进行平均。
3.计算邻域平均值: 对于每个像素,计算邻域内像素的平均值。邻域可以是以该像素为中心的正方形区域,根据滤波器大小确定。
4.更新像素值: 将该像素的值替换为邻域平均值。

2. 实验代码

void CImageProcessingView::OnEnhanceDenoiseAverage()
{
 // 实验 图像平滑 256级灰度图像 邻域平均滤波
 
 // 获得当前文档对象
    CImageProcessingDoc* pDoc = GetDocument();
 if( pDoc->m_pDibInit->IsEmpty() )
 {
  MessageBox("图像未加载");
  return;
 }

 // 获得图像的基本信息
 int width = pDoc->m_pDibInit->GetWidth();
 int height = pDoc->m_pDibInit->GetHeight();
 int bitCount = pDoc->m_pDibInit->GetBitCount();
 // 程序只支持处理灰度图像
 if( bitCount!=8 )
 {
  MessageBox("目前只支持256级灰度图像");
  return;
 }
 // 将图像信息复制至 m_pDibTest
 pDoc->m_pDibTest->CloneDib(pDoc->m_pDibInit);
 // 设置去噪模板,这里使用一个3×3的去噪模板
 double templateDenoise[100] = 
  {1, 1, 1,
   1, 2, 1,
   1, 1, 1};
 int templateWidth = 3;
 int templateHeight = 3;
 int templateElementCnt = templateWidth*templateHeight;
 double sum1 = 0;
 
 // 归一化模板元素的值
 int i;
 for(i=0; i<templateElementCnt; i++)
  sum1 += templateDenoise[i];
 for(i=0; i<templateElementCnt; i++)
  templateDenoise[i] = templateDenoise[i]/sum1;

 // 定义临时变量 
 int j,m,n;
 BYTE gray;
 double value1;

 // 对图像里面的每一个像素进行 邻域
 // 为了方便,这里没有处理边界点
 for(i=templateWidth/2; i<pDoc->m_pDibInit->m_lpBMIH->biWidth-templateWidth/2; i++)
 {
  for(j=templateHeight/2; j<pDoc->m_pDibInit->m_lpBMIH->biWidth-templateHeight/2; j++)
  {
   // 当前的像素点是 (i, j) 。
   // 计算以 (i, j) 为中心,templateWidth为宽度,templateHeight为高度的矩形区域内,个个像素点颜色值的加权和。
   // 因为现在处理的是256色灰度图像,所以在 RGBQUAD结构中,Red、Green、Blue三个分量的值都肯定是相等的,
   // 所以只要处理Red分量,算出的结果也适用于Green分量和Blue分量
   value1 = 0;

   for(m=0; m<templateWidth; m++)
   {
    for(n=0; n<templateHeight; n++)
    {     
     gray = pDoc->m_pDibInit->GetPixelGray(i-templateWidth/2+m, j-templateHeight/2+n);
     
     value1 += gray * templateDenoise[n*templateWidth+m];
    }
   }
   pDoc->m_pDibTest->SetPixelGray(i, j, value1);
  }
 } 
 // 交换指针
 CDib* pTmpDib = pDoc->m_pDibTest;
 pDoc->m_pDibTest = pDoc->m_pDibInit;
 pDoc->m_pDibInit = pTmpDib;
 // 设置脏标记
 pDoc->SetModifiedFlag(TRUE);
 // 更新视图
 pDoc->UpdateAllViews(NULL);
}

3. 实验现象

左:灰度图原图
中:图片加入椒盐噪声
右:邻域平均平滑
在这里插入图片描述

中值滤波算法

1. 原理

中值滤波是一种非线性滤波算法,其原理是用窗口中像素的中值替代窗口中心像素的灰度值。这种方法对去除椒盐噪声(Salt-and-Pepper Noise)等脉冲性噪声效果较好。

中值滤波的基本步骤如下:

  1. 选择滤波器大小: 定义一个窗口,通常是正方形,大小为 n × n n \times n n×n,其中 n n n 为奇数,例如 3x3 或 5x5。

  2. 遍历图像像素: 对于图像中的每个像素,以其为中心取一个 n × n n \times n n×n的窗口。

  3. 排序窗口内像素值: 将窗口内的像素值按灰度值进行排序,找到中间值

  4. 更新像素值: 将该像素的值替换为窗口内像素值的中值。

这样,通过用窗口内像素的中值替代中心像素,可以有效地去除椒盐噪声等离群值,同时保留图像的边缘信息。

中值滤波相对于线性滤波,尤其是在存在脉冲性噪声的情况下,具有更好的去噪效果。然而,中值滤波也会导致图像细节的模糊,因此在应用中需要权衡滤波效果和细节保留。

2. 实验代码

void CImageProcessingView::OnEnhanceDenoiseMedian()
{
 // 实验 图像平滑 256级灰度图像 中值滤波
 // 参考 CImageProcessingView::OnEnhanceDenoiseAverage()
 //MessageBox("请在这里设计 256级灰度图像 中值滤波 算法");
 
 // 获得当前文档对象
    CImageProcessingDoc* pDoc = GetDocument();
 if( pDoc->m_pDibInit->IsEmpty() )
 {
  MessageBox("图像未加载");
  return;
 }

 // 获得图像的基本信息
 int width = pDoc->m_pDibInit->GetWidth();
 int height = pDoc->m_pDibInit->GetHeight();
 int bitCount = pDoc->m_pDibInit->GetBitCount();

 // 程序只支持处理灰度图像
 if( bitCount!=8 )
 {
  MessageBox("目前只支持256级灰度图像");
  return;
 }

 // 将图像信息复制至 m_pDibTest
 pDoc->m_pDibTest->CloneDib(pDoc->m_pDibInit);

 int i,j,m,n;
 BYTE grays[100];
 int graysSize = 100;
 int templateWidth = 3;
 int templateHeight = 3;
 int templateElementCnt = templateWidth*templateHeight;
 BYTE tempByte1;


 for(i=templateWidth/2; i<pDoc->m_pDibInit->m_lpBMIH->biWidth-templateWidth/2; i++)
 {
  for(j=templateHeight/2; j<pDoc->m_pDibInit->m_lpBMIH->biWidth-templateHeight/2; j++)
  {
   memset(grays, 0, graysSize*sizeof(BYTE));

   for(n=0; n<templateHeight; n++)
   {
    for(m=0; m<templateWidth; m++)
    {     
     grays[n*templateWidth+m] = pDoc->m_pDibInit->GetPixelGray(i-templateWidth/2+m, j-templateHeight/2+n);
    }
   }

   for(m=0; m<templateElementCnt-1; m++)
   {
    for(n=m+1; n<templateElementCnt; n++)
    {
     if( grays[m]>grays[n] )
     {
      tempByte1 = grays[m];
      grays[m] = grays[n];
      grays[n] = tempByte1;
     }
    }
   }

   pDoc->m_pDibTest->SetPixelGray(i, j, grays[templateElementCnt/2]);
  }
 }

 // 交换指针
 CDib* pTmpDib = pDoc->m_pDibTest;
 pDoc->m_pDibTest = pDoc->m_pDibInit;
 pDoc->m_pDibInit = pTmpDib; 
 
 // 设置脏标记
 pDoc->SetModifiedFlag(TRUE);
 
 // 更新视图
 pDoc->UpdateAllViews(NULL);
}

3.实验现象

左:添加椒盐噪声的灰度图像
右:使用中值滤波后
在这里插入图片描述

K近邻均值滤波算法(KNNF)

1. 原理

K近邻均值滤波(KNNF)是一种非线性滤波算法,它通过计算像素点周围的K个邻居的平均值来实现图像平滑。相比于传统的平均滤波,KNNF更加灵活,能够在一定程度上保留图像的边缘信息。

KNNF的基本步骤如下:

  1. 选择邻居数量 K K K 和滤波器大小: 确定每个像素点周围邻居的数量 K K K,同时选择一个滤波器的大小,通常是一个 n × n n \times n n×n 的窗口,其中 n n n 为奇数。

  2. 遍历图像像素: 对于图像中的每个像素,以其为中心取一个 n × n n \times n n×n 的窗口。

  3. 计算邻居的平均值: 计算窗口内邻居的平均值。

  4. 更新像素值: 将该像素的值替换为邻居的平均值。

这种滤波方法能够在一定程度上去除图像中的噪声,同时保留图像的整体结构和边缘信息。

在实现中,可以通过计算像素点间的距离来确定邻居,选择距离最近的K个像素进行平均。这个方法在一定程度上能够提高滤波的效果。

2. 实验代码

int i,j,m,n;
 BYTE grays[100];
 int graysSize = 100;
 int templateWidth = 3;
 int templateHeight = 3;
 int templateElementCnt = templateWidth*templateHeight;
 BYTE tempByte1;
 int kNN = 3;

 for(i=templateWidth/2; i<pDoc->m_pDibInit->m_lpBMIH->biWidth-templateWidth/2; i++)
 {
  for(j=templateHeight/2; j<pDoc->m_pDibInit->m_lpBMIH->biWidth-templateHeight/2; j++)
  {    
   memset(grays, 0, graysSize*sizeof(BYTE));

   for(n=0; n<templateHeight; n++)
   {
    for(m=0; m<templateWidth; m++)
    {    
     grays[n*templateWidth+m] = pDoc->m_pDibInit->GetPixelGray(i-templateWidth/2+m, j-templateHeight/2+n);
    }
   }
   
   BYTE centerGray = pDoc->m_pDibInit->GetPixelGray(i, j);

   for(m=0; m<templateElementCnt-1; m++)
   {
    for(n=m+1; n<templateElementCnt; n++)
    {
     if( abs(grays[m]-centerGray) > abs(grays[n]-centerGray) )
     {
      tempByte1 = grays[m];
      grays[m] = grays[n];
      grays[n] = tempByte1;
     }
    }
   }

   double avgGray = 0;
   for(m=0; m<kNN; m++)
   {
    avgGray += grays[m];
   }
   avgGray /= kNN; 

   pDoc->m_pDibTest->SetPixelGray(i, j, avgGray);
  }
 }

实验现象

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/152184.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习】 特征工程:特征预处理,归一化、标准化、处理缺失值

特征预处理采用的是特定的统计方法&#xff08;数学方法&#xff09;将数据转化为算法要求的数字 1. 数值型数据 归一化&#xff0c;将原始数据变换到[0,1]之间 标准化&#xff0c;数据转化到均值为0&#xff0c;方差为1的范围内 缺失值&#xff0c;缺失值处理成均值、中…

PDF处理控件Aspose.PDF功能演示:使用C#查找和替换PDF文件中的文本

使用“查找并替换”选项可以一次性替换文档中的特定文本。这样&#xff0c;您不必手动定位和更新整个文档中每次出现的文本。本文甚至更进一步&#xff0c;介绍了如何在PDF文档中自动查找和替换文本功能。特别是&#xff0c;将学习如何使用C&#xff03;在整个PDF&#xff0c;特…

外汇天眼:失败的投资者经常陷入两个误区!

一、价格与价值的混淆 在金融领域&#xff0c;价格和价值往往被错误视为同义词。然而&#xff0c;审视市场时&#xff0c;我们会逐渐发现一个“安全差”的重要概念&#xff0c;这是由巴菲特的导师本杰明格雷厄姆提出的。 安全差是指股票的内在价值与市场价格之间的差异。内在…

WMS仓储管理系统与TMS系统整合后的优势

随着全球化的加速和供应链网络的日益复杂&#xff0c;仓库和运输成为企业运营中的两个关键环节。为了更高效地管理这两个环节&#xff0c;许多企业开始探索将WMS仓储管理系统和TMS运输管理系统整合的可能性。这种整合不仅可以提升仓库流程的可见性&#xff0c;还有助于改善调度…

1、24 个常见的 Docker 疑难杂症处理技巧(一)

1Docker 迁移存储目录 默认情况系统会将 Docker 容器存放在 /var/lib/docker 目录下 [问题起因] 今天通过监控系统&#xff0c;发现公司其中一台服务器的磁盘快慢&#xff0c;随即上去看了下&#xff0c;发现 /var/lib/docker 这个目录特别大。由上述原因&#xff0c;我们都知…

配置 ssh 免密登录

背景 从机器 A 使用 ssh 免密登录到机器 B&#xff0c;两台机器的 OS 都是 CentOS。其中机器 B 用作了一台 nodejs 的服务器&#xff0c;已经安装并运行了 sshd 服务&#xff0c;其用户名是 jmmem 我们想要实现在机器 A 上键入 ssh nodejs 就能免密登录到机器 B 的效果 机器…

python 最快多长时间学完?

以下是一个为零基础学员制作Python速成学习计划。这个计划包括了一些基本的Python概念和技能&#xff0c;以及一些实用的学习技巧。 第1周&#xff1a;基础入门 Python简介&#xff1a;了解Python的历史、特点、应用领域。 安装Python&#xff1a;在你的电脑上安装Python&am…

一个 不用充钱 也能让你变强的 VSCode 插件

今天给大家推荐一款不用充钱也能让你变强的 vscode 插件 通义灵码&#xff08;TONGYI Lingma&#xff09;&#xff0c;可以称之为 copilot 的替代甜品 &#x1f4aa; 什么是 通义灵码&#xff08;TONGYI Lingma&#xff09; 通义灵码&#xff08;TONGYI Lingma&#xff09;&am…

Martins 用法-利用现有的数学公式来绘制三相电机电流相位之间的关系

你可能会对这个主题很感兴趣。这背后的原因是我想分享一种我在花了大量时间研究诊断三相电机的方式时发现到的技术。我发现有一种非常简单的方式可以做到这一点&#xff0c;与Pico团队分享后&#xff0c;Steve Smith将它命名为Martins用法。 那么&#xff0c;让我们开始吧。 Ma…

Pinia 及其数据持久化 Vue新一代状态管理插件

黑马前端Vue新一代状态管理插件Pinia快速入门视频教程 Pinia主页 超级简单&#xff0c;不需要耐心 pinia &#xff1a;新一代的VueX 1. 安装 npm install pinia2. 在main.js中引入 import { createPinia } from pinia app.use(createPinia())3. 新建stores目录&#xff0c…

Camtasia2024喀秋莎微课制作神器新版本功能介绍

最近无论是b站&#xff0c;抖音&#xff0c;快手等视频软件中都有不少微课视频、电视剧解说横空出世&#xff0c;通过这些“热度”带来的收益也是无法估量的&#xff0c;很多自媒体博主月入上万惹人羡慕。 不少朋友也想在这股短视频洪流中分一碗羹&#xff0c;但又苦于技术跟不…

areadetector ADURL模块应用在面探测控制的初步应用

本章中讨论了使用ADURL控制面探测器Lambda的过程&#xff1a; ADURL的使用请见&#xff1a; EPICS -- areaDetector URL驱动程序-CSDN博客 需要启动一个ADURL的IOC程序&#xff0c;并且设置相关的插件中参数的值&#xff1a; # st.cm < envPaths < st_base.cmddbpf 1…

mysql操作 sql语句中的完整性约束有哪些,主键约束、外键约束、引用完整性约束,主键外键、唯一性

什么是约束&#xff1a;约束&#xff1a;就是约定哪些东西能填、怎么填&#xff1f;哪些东西不能填&#xff1f; 文章目录 前言&#xff1a;建表正文一、实体完整性约束1. 主键约束2. 唯一性约束3. 自增长约束4. 联合主键约束 二、域完整性约束三、引用完整性约束1. 外键约束 讲…

【kerberos】使用 curl 访问受 Kerberos HTTP SPNEGO 保护的 URL

前言&#xff1a; 大数据集群集成 Kerberos 后&#xff0c;很多 WEBUI 打开都会提示输入用户名和密码。由于我想获取 flink 任务的详情&#xff0c;且KNOX 并不支持Flink api&#xff0c;查看KNOX 直接的列表&#xff1a;https://docs.cloudera.com/cdp-private-cloud-base/7.…

算法实战:亲自写红黑树之二 完整代码

此文承接&#xff1a;算法实战&#xff1a;亲自写红黑树之一-CSDN博客 目录 一、项目结构 二、辅助代码a.h 三、红黑树代码rbtree.h 四、测试代码main.cpp 五、运行效果 六、代码详解 一、项目结构 这里给出的代码是实际可以运行的代码。 运行环境&#xff1a;VS2022&am…

波束形成中的主瓣宽度

阵列信号处理相关基础知识及主瓣宽度 导向矢量阵列方向图确知波束形成普通波束形成主瓣宽度确知波束形成主瓣宽度普通波束形成主瓣宽度 在讨论主瓣宽度之前&#xff0c;首先得了解导向矢量、波束形成、阵列方向图的概念&#xff0c;这些是阵列信号处理中最基础的知识。 导向矢量…

编译智能合约以及前端交互工具库(Web3项目一实战之三)

我们已然在上一篇 Web3项目灵魂所在之智能合约编写(Web3项目一实战之二) ,为项目写好了智能合约代码。 但身为开发人员的我们,深知高级编程语言所编写出来的代码,都是需要经过编译,而后外部方能正常调用。很显然,使用solidity这门新的高级编程语言编写出来的智能合约,也…

【机器学习】线性回归算法:原理、公式推导、损失函数、似然函数、梯度下降

1. 概念简述 线性回归是通过一个或多个自变量与因变量之间进行建模的回归分析&#xff0c;其特点为一个或多个称为回归系数的模型参数的线性组合。如下图所示&#xff0c;样本点为历史数据&#xff0c;回归曲线要能最贴切的模拟样本点的趋势&#xff0c;将误差降到最小。 2. 线…

基于旗鱼算法优化概率神经网络PNN的分类预测 - 附代码

基于旗鱼算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于旗鱼算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于旗鱼优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…