使用VC++设计程序实现K近邻中值滤波器(KNNMF)、最小均方差滤波器、矢量中值滤波算法进行滤波

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

获取源工程可访问gitee可在此工程的基础上进行学习。
该工程的其他文章:
01- 一元熵值、二维熵值
02- 图像平移变换,图像缩放、图像裁剪、图像对角线镜像以及图像的旋转
03-邻域平均平滑算法、中值滤波算法、K近邻均值滤波器
04-分段线性变换,直方图均衡化、锐化处理
05-基于拉普拉斯算子、Canny的边缘检测功能、实现Otsu分割方法
06-最近邻插值,双线性插值,立方卷积插值
07-全局固定阈值分割、自适应阈值分割

文章目录

  • VC++实现若干种图像滤波技术2
    • 实验要求
    • 一、K近邻中值滤波器(KNNMF)
      • 1. K近邻中值滤波器(KNNMF)原理
      • 2. K近邻中值滤波器(KNNMF)实验代码
      • 3. K近邻中值滤波器(KNNMF)实验现象
    • 二、 最小均方差滤波器
      • 1. 最小均方差滤波器原理
      • 2. 最小均方差滤波器实验代码
      • 3. 最小均方差滤波器实验现象
    • 彩色图像矢量中值滤波算法
      • 1. 矢量中值滤波算法原理
      • 2. 矢量中值滤波算法实验代码
      • 3. 矢量中值滤波算法实验现象

实验要求

B部分:
(1)包括A部分全部要求。
(2)使用VC++设计程序:对一幅256级灰度图像,分别使用K近邻中值滤波器(KNNMF)、最小均方差滤波器进行滤波。
(3)使用VC++设计程序:对一幅24位彩色图像,使用矢量中值滤波算法进行滤波。

一、K近邻中值滤波器(KNNMF)

1. K近邻中值滤波器(KNNMF)原理

KNNMF(K-Nearest Neighbors Mean Filter)是一种非线性滤波算法,它利用每个像素点周围的 K 个最近邻居的平均值进行图像平滑。与传统的平均滤波器不同,KNNMF选择最相似的像素进行平均,这有助于在滤波的同时更好地保留图像的细节。

以下是KNNMF的基本步骤:

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

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

  3. 计算邻居的相似度: 计算窗口内每个像素与中心像素的相似度,可以使用像素值之间的距离来衡量相似度。

  4. 选择相似度最高的 K 个邻居: 选择相似度最高的 K 个邻居进行平均。

  5. 更新像素值: 将该像素的值替换为相似度最高的 K 个邻居的平均值。

KNNMF算法相对于传统的平均滤波器,更注重选择相似度高的邻居进行平均,这有助于更好地保留图像的特征。在实际应用中,相似度的计算可以采用不同的度量方式,例如欧氏距离、余弦相似度等,具体取决于图像的特点和应用场景。

2. K近邻中值滤波器(KNNMF)实验代码

void CImageProcessingView::OnEnhanceDenoiseKNNMF()
{// 实验 图像平滑 256级灰度图像 KNNMF滤波// 参考 CImageProcessingView::OnEnhanceDenoiseAverage()//MessageBox("请在这里设计 256级灰度图像 KNNMF滤波 算法");// 获得当前文档对象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_pDibTestpDoc->m_pDibTest->CloneDib(pDoc->m_pDibInit);//**********KNNMF滤波 算法**************//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;}}}int midgray = 0;//中值for (m = 1; m <= kNN/2 ; m++)midgray = grays[m];pDoc->m_pDibTest->SetPixelGray(i, j, midgray);}}// 交换指针CDib* pTmpDib = pDoc->m_pDibTest;pDoc->m_pDibTest = pDoc->m_pDibInit;pDoc->m_pDibInit = pTmpDib; // 设置脏标记pDoc->SetModifiedFlag(TRUE);// 更新视图pDoc->UpdateAllViews(NULL);
}

3. K近邻中值滤波器(KNNMF)实验现象

在这里插入图片描述

二、 最小均方差滤波器

1. 最小均方差滤波器原理

最小均方差滤波是一种图像处理中常用的滤波方法,其目标是通过在像素邻域内选择合适的权重,使得滤波后的像素值与邻域内的像素值之间的均方差最小。

滤波过程中,对于每个像素,通过选取邻域内的像素进行加权平均,其中每个像素的权重由该像素与中心像素之间的差异以及一个权重函数决定。权重函数通常是关于像素差异的一个单调递减函数,以便更重视与中心像素相似的像素。

最小均方差滤波的目标函数可以表示为:

E ( u , v ) = ∑ i = − N N ∑ j = − N N w [ i , j ] ( I ( u + i , v + j ) − T ( u , v ) ) 2 E(u,v) = \sum_{i=-N}^{N} \sum_{j=-N}^{N} w[i,j](I(u+i,v+j) - T(u,v))^2 E(u,v)=i=NNj=NNw[i,j](I(u+i,v+j)T(u,v))2

其中:

  • $ (u,v) $ 是滤波后图像中的像素位置。
  • $ (i,j) $ 是邻域内像素的偏移。
  • $ I(u+i,v+j) $ 是邻域内某个像素的灰度值。
  • $ T(u,v) $ 是中心像素的灰度值。
  • $ w(i,j) $ 是权重函数。

最小均方差滤波的目标是找到使得目标函数 ( E(u,v) ) 最小的滤波器系数。这通常通过最小化目标函数的导数为零来实现。

具体实现最小均方差滤波需要对权重函数、邻域大小等进行合理的选择,以适应不同的图像处理任务。

2. 最小均方差滤波器实验代码

//**********最小均方差滤波算法**************//
int templateWidth = 3;
int templateHeight = 3;for (int i = templateWidth / 2; i < width - templateWidth / 2; i++)
{for (int j = templateHeight / 2; j < height - templateHeight / 2; j++){double minMSE = DBL_MAX; // 最小均方差初始化为最大值int optimalGray = 0;// 尝试所有可能的灰度值for (int k = 0; k <= 255; k++){double mse = 0.0;// 计算邻域内所有像素与当前灰度值的均方差for (int n = 0; n < templateHeight; n++){for (int m = 0; m < templateWidth; m++){BYTE pixelValue = pDoc->m_pDibInit->GetPixelGray(i - templateWidth / 2 + m, j - templateHeight / 2 + n);mse += pow(pixelValue - k, 2);}}mse /= (templateWidth * templateHeight); // 均方差// 更新最小均方差和对应的灰度值if (mse < minMSE){minMSE = mse;optimalGray = k;}}// 将最小均方差对应的灰度值设置为新的像素值pDoc->m_pDibTest->SetPixelGray(i, j, optimalGray);}
}

3. 最小均方差滤波器实验现象

左:加入噪声的图像
右:进行滤波后的图像

在这里插入图片描述

彩色图像矢量中值滤波算法

1. 矢量中值滤波算法原理

矢量中值滤波算法是一种基于中值运算的图像平滑处理方法。其原理可以概括为以下几个步骤:

  1. 选择邻域: 对于图像中的每个像素,定义一个邻域,包含该像素及其周围的像素。邻域的大小由窗口大小确定。

  2. 构建邻域矩阵: 将邻域内的像素值按某种顺序排列,形成一个矢量。这个矢量包含了邻域内所有像素的灰度值。

  3. 中值运算: 对构建的矢量进行中值运算,即找到矢量中的中间值。这可以通过对矢量进行排序,然后选择排序后的中间值来实现。

  4. 更新像素值: 将中值作为原始像素的新值,用于替代原始像素的灰度值。这样,经过矢量中值滤波处理后,图像中的每个像素都会得到一个中值平滑的结果。

矢量中值滤波的优点在于对图像进行平滑处理的同时能有效抑制噪声,特别适用于去除图像中的椒盐噪声等离群点。这种滤波方法在一些图像处理任务中取得了较好的效果,但也需要根据具体应用场景选择合适的窗口大小和滤波算法。

举个例子说明一下
假设我们有一个3x3的邻域矩阵,其像素值如下:

[ 10 20 15 30 25 40 35 15 20 ] \begin{bmatrix} 10 & 20 & 15 \\ 30 & 25 & 40 \\ 35 & 15 & 20 \\ \end{bmatrix} 103035202515154020

现在我们要进行矢量中值滤波,按照步骤来进行处理:

  1. 选择邻域: 我们选择一个3x3的邻域,以中心像素25为例。

  2. 构建邻域矩阵: 将邻域内的像素值按顺序排列成矢量:

$ \text{矢量} = [10, 20, 15, 30, 25, 40, 35, 15, 20] $

  1. 中值运算: 对矢量进行排序,得到:
    $\text{矢量} = [10, 15, 15, 20, 20, 25, 30, 35, 40] $

中值是排序后的中间值,即 $\text{中值} = 20 $。

  1. 更新像素值: 将中值20作为原始像素25的新值。

这样,经过矢量中值滤波处理后,中心像素的值由原来的25变为20。这个过程对图像中的每个像素都进行,以达到平滑图像的目的。这种方法在处理一些椒盐噪声等离群点时具有较好的效果。

2. 矢量中值滤波算法实验代码

//**********矢量中值滤波算法**************//int templateWidth = 3;int templateHeight = 3;int templateElementCnt = templateWidth * templateHeight;int color_r[100][100] = { 0 };int color_g[100][100] = { 0 };int color_b[100][100] = { 0 };for (int i = templateWidth / 2; i < pDoc->m_pDibInit->m_lpBMIH->biWidth - templateWidth / 2; i++){for (int j = templateHeight / 2; j < pDoc->m_pDibInit->m_lpBMIH->biWidth - templateHeight / 2; j++){// 获取当前像素点邻域的颜色信息for ( n = 0; n < templateHeight; n++)for ( m = 0; m < templateWidth; m++){RGBQUAD quad;quad = pDoc->m_pDibInit->GetPixelColor(i - templateWidth / 2 + m, j - templateHeight / 2 + n);color_r[n][m] = quad.rgbRed;color_g[n][m] = quad.rgbGreen;color_b[n][m] = quad.rgbBlue;}int sum_r = 0, sum_g = 0, sum_b = 0;for ( n = 0; n < templateHeight; n++)for ( m = 0; m < templateWidth; m++){sum_r += color_r[n][m];sum_g += color_g[n][m];sum_b += color_b[n][m];}int avl_r = sum_r / templateElementCnt;int avl_g = sum_g / templateElementCnt;int avl_b = sum_b / templateElementCnt;float min = 255;  //最小的rRGBQUAD Quad;for ( n = 0; n < templateHeight; n++)for ( m = 0; m < templateWidth; m++){// 计算中值float temp = (pow((color_r[n][m] - avl_r), 2) + pow((color_g[n][m] - avl_g), 2) + pow((color_b[n][m] - avl_b), 2)) / 2;if (temp < min){Quad.rgbRed = color_r[n][m];Quad.rgbGreen = color_g[n][m];Quad.rgbBlue = color_b[n][m];min = temp;}}pDoc->m_pDibTest->SetPixelColor(i, j, &Quad);}}

3. 矢量中值滤波算法实验现象

在这里插入图片描述

左:添加噪声的灰度图
右:使用矢量中值滤波算法后

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

瑞云科技参与《数字孪生世界白皮书》编写,实时云渲染助力数字孪生

为了促进数字孪生技术的发展和应用&#xff0c;易知微与数字孪生世界企业联盟联合众多行业专家以及多家业内企业共同编写了《数字孪生世界白皮书&#xff08;2023&#xff09;》。该白皮书从数字孪生的综述、应用架构、核心技术、新型技术成果和重点行业应用等方面&#xff0c;…

图论|并查集理论基础 1971. 寻找图中是否存在路径

什么是并查集 并查集是一种数据结构&#xff0c;用于处理一些不交集的合并及查询问题。它支持两种操作&#xff1a; 查找&#xff08;Find&#xff09;&#xff1a;确定某个元素属于哪个子集。它可以用来判断两个元素是否属于同一个子集。 合并&#xff08;Union&#xff09;&…

WebGL笔记:矩阵旋转运算的原理和实现

矩阵 矩阵&#xff08;Matrix&#xff09;是一个按照矩形纵横排列的复数集合 矩阵就像一个矩形的阵盘&#xff0c;通过其中纵横排列的元素我们可以摆出不同功能的阵法&#xff0c;比如位移矩阵、旋转矩阵、缩放矩阵 …在矩阵中的每一行&#xff0c;或者每一列数字构成的集合&a…

Flutter开发type ‘Future<int>‘ is not a subtype of type ‘int‘ in type cast错误

文章目录 问题描述错误源码 问题分析解决方法修改后的代码 问题描述 今天有个同事调试flutter程序时报错&#xff0c;问我怎么解决&#xff0c;程序运行时报如下错误&#xff1a; type ‘Future’ is not a subtype of type ‘int’ in type cast 错误源码 int order Databas…

2015年五一杯数学建模C题生态文明建设评价问题解题全过程文档及程序

2015年五一杯数学建模 C题 生态文明建设评价问题 原题再现 随着我国经济的迅速发展&#xff0c;生态文明越来越重要&#xff0c;生态文明建设被提到了一个前所未有的高度。党的十八大报告明确提出要大力推进生态文明建设&#xff0c;报告指出“建设生态文明&#xff0c;是关系…

探索意义的深度:自然语言处理中的语义相似性

一、说明 语义相似度&#xff0c;反应出计算机对相同内容&#xff0c;不同表达的识别能力。因而识别范围至少是个句子&#xff0c;最大范围就是文章&#xff0c;其研究方法有所区别。本文将按照目前高手的研究成绩&#xff0c;作为谈资介绍给诸位。 二、语义相似度简介 自然语言…

团队怎么高效制作问卷?

制作调查问卷时并不是一个人就能单独完成&#xff0c;通常情况下&#xff0c;完成一份调查问卷往往需要一个团队的成员参与&#xff0c;相互协作&#xff0c;共同完成。不过&#xff0c;多人协作经常会遇到协作壁垒&#xff0c;导致效率低下&#xff0c;那团队怎么才能高效协作…

【面试经典150 | 二分查找】搜索二维矩阵

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;二分查找 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等…

前端笔记(二):CSS 选择器与特性

CSS&#xff08;层叠样式表&#xff09;是一种样式表语言&#xff0c;用于描述HTML或XML文档的呈现方式。它定义了如何在屏幕、纸张或其他媒体上显示文档的样式、布局和外观。 里面的代码由 选择器 { } 组成 体验 CSS CSS 可以让我们界面变得更加美观&#xff0c;这是 CSS 的…

OpenSSH 漏洞修复升级最新版本

Centos7系统ssh默认版本一般是OpenSSH7.4左右&#xff0c;低版本是有漏洞的而且是高危漏洞&#xff0c;在软件交付和安全扫描上是过不了关的&#xff0c;一般情况需要升级OpenSSH的最新版本 今天详细说下升级最新版本的处理过程&#xff08;认真看会发现操作很简单&#xff0c…

k8s-daemonset、job、cronjob控制器 6

Daemonset控制器&#xff08;一个节点部署一个&#xff09; 、 创建Daemonset控制器 控制节点上不能进行部署&#xff0c;有污点 解决方式&#xff1a; 扩容节点&#xff0c;token值过期的解决方法&#xff1a; 回收pod job控制器 需要使用perl镜像&#xff0c;仓库没有&…

基于Springboot + vue的汽车资讯网站

qq&#xff08;2829419543&#xff09;获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;springboot 前端&#xff1a;采用vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xf…

阅读软件OmniReader Pro mac功能特色

OmniReader Pro mac是一款文字识别和阅读软件&#xff0c;它可以将印刷体和手写体的文字转换为数字文本&#xff0c;并将其朗读出来。该软件适用于视力受损、阅读困难、语言障碍等用户&#xff0c;可以帮助他们更加轻松地获取信息和阅读文本。 OmniReader Pro具有简洁直观的用户…

almalinux centos8系统zlmediakit编译安装

脚本 # 安装依赖 gcc-c.x86_64 这个不加的话会有问题&#xff0c; cmake需要在线安装 sudo yum -y install gcc gcc-c libssl-dev libsdl-dev libavcodec-dev libavutil-dev ffmpeg git openssl-devel gcc-c.x86_64 cmake mkdir -p /home/zenglg cd /home/zenglg git clon…

人工智能和网络安全:坏与好

人工智能似乎可以并且已经被用来帮助网络犯罪和网络攻击的各个方面。 人工智能可以用来令人信服地模仿真人的声音。人工智能工具可以帮助诈骗者制作更好、语法正确的网络钓鱼消息&#xff08;而糟糕的语法往往会暴露出漏洞&#xff09;&#xff0c;并将其翻译成多种语言&…

华为1+x网络系统建设与运维(中级)-练习题2

一.设备命令 LSW1 [Huawei]sys LSW1 同理可得&#xff0c;给所有设备改名 二.VLAN LSW1 [LSW1]vlan ba 10 20 [LSW1]int g0/0/1 [LSW1-GigabitEthernet0/0/1]port link-type trunk [LSW1-GigabitEthernet0/0/1]port trunk allow-pass vlan 10 20 [LSW1-GigabitEthernet0/0/1]in…

lxml 总结

xm 和 lxml库 哪个更好用点 1. 性能&#xff1a; lxml 通常比 xml.etree.ElementTree 更快。lxml 使用了 C 编写的底层解析器&#xff0c;因此在处理大型 XML 文档时可能更高效。 如果性能对你的应用很重要&#xff0c;特别是在处理大型 XML 文件时&#xff0c;选择 lxml 可能…

【web安全】CSRF漏洞攻击与防御

前言 总结&#xff0c;仅供学习。 csrf的理解 我们了解一个网站有修改信息&#xff0c;密码&#xff0c;添加删除管理&#xff0c;支付转账的功能之后。 通过抓包抓取对方修改操作的数据包样式&#xff0c; 然后在自己网站搭建一个指令。 当别人来访时&#xff0c; 如果…

C++基础 -30- 双目运算符重载

c的运算符如&#xff0c;只能实现标准的加法&#xff0c;无法让两个类的参数相加 通过运算符重载可以实现更高级的运算&#xff08;此处为类外重载&#xff09; 运算符重载(类内重载) #include "iostream"using namespace std;class data1 {public :int a;data1…

Go语言实现大模型分词器tokenizer

文章目录 前言核心结构体定义构造函数文本初始处理组词构建词组索引训练数据编码解码打印状态信息运行效果总结 前言 大模型的tokenizer用于将原始文本输入转化为模型可处理的输入形式。tokenizer将文本分割成单词、子词或字符&#xff0c;并将其编码为数字表示。大模型的toke…