《opencv实用探索·九》中值滤波简单理解

1、引言
均值滤波、方框滤波、高斯滤波,都是线性滤波方式。由于线性滤波的结果是所有像素值的线性组合,因此含有噪声的像素也会被考虑进去,噪声不会被消除,而是以更柔和的方式存在。这时使用非线性滤波效果可能会更好。中值滤波是一种非线性滤波方式,不再采用加权求均值的方式计算滤波结果,基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。

优缺点:中值滤波可以有效的去除斑点和椒盐噪声。但是效率低,其运算时间 为均值滤波的五倍以上

2、中值滤波过程
首先我们先取一个nxn的滤波核,该核是一个空核,核中不在有权重等数字,把滤波核放在图像上滑动,每滑动到一个位置,就把核覆盖下的所有像素值进行排序,然后取排序后中间的像素值替换被核中心覆盖下的原图像像素值。下面演示下滤波过程。

先取一个3x3的空核:
在这里插入图片描述
把3x3的空核放在原图像上进行滑动:
在这里插入图片描述
计算被核覆盖下的像素中值,以上图核放在左上角为例:
先给所有像素进行排序,正序和逆序都可,这里使用正序
20,24,28,35,47,59,68,79,99

由排序可知中间值为:47
最后把中间值替换被核中心覆盖的像素值,即68会重新赋值为47,随着核滑动便可依次计算被核中心覆盖的像素值的中值,核中心滑动过的像素如下图阴影部分。
在这里插入图片描述

3、opencv中值滤波函数使用

void cv::medianBlur(InputArray   src,OutputArray dst,int  ksize
)

src:原图像,可以是单通道,三通道和四通道,数据类型与滤波器的尺寸相关,当滤波器尺寸为3或5时,图像可以是CV 8U,CV 16U或CV 32F类型,对于较大尺寸的滤波器,数据类型只能是CV 8U
dst:滤波后的图像
ksize:滤波核大小,必须是奇数,这样才有核中心

对原图分别执行3x3和9x9滤波,实现效果如下:
原图:
在这里插入图片描述
左边是3x3滤波,右边是9x9滤波
在这里插入图片描述

4、滤波核根据图像自适应调整大小
我们在调用medianBlur时需要手动传入一个滤波核大小,下面的一个demo介绍了核的大小根据局部邻域的均值和标准差进行自适应调整:

#include <opencv2/opencv.hpp>cv::Mat adaptiveMedianBlur(const cv::Mat& src, int maxWindowSize) {cv::Mat result = src.clone();int numChannels = src.channels();for (int y = maxWindowSize / 2; y < src.rows - maxWindowSize / 2; ++y) {for (int x = maxWindowSize / 2; x < src.cols - maxWindowSize / 2; ++x) {int windowSize = 3;  // 初始核大小while (windowSize <= maxWindowSize) {// 提取局部邻域cv::Mat region = src(cv::Range(y - windowSize / 2, y + windowSize / 2 + 1),cv::Range(x - windowSize / 2, x + windowSize / 2 + 1));// 计算标准差cv::Scalar mean, stddev;cv::meanStdDev(region, mean, stddev);// 中值滤波if (numChannels == 1 && src.at<uchar>(y, x) < mean[0] + stddev[0] * 0.5) {// 单通道图像中值滤波cv::Mat subRegion = result(cv::Range(y - windowSize / 2, y + windowSize / 2 + 1),cv::Range(x - windowSize / 2, x + windowSize / 2 + 1));cv::medianBlur(region, subRegion, windowSize);break;} else if (numChannels == 3 &&src.at<cv::Vec3b>(y, x)[0] < mean[0] + stddev[0] * 0.5 &&src.at<cv::Vec3b>(y, x)[1] < mean[1] + stddev[1] * 0.5 &&src.at<cv::Vec3b>(y, x)[2] < mean[2] + stddev[2] * 0.5) {// 三通道图像中值滤波cv::Mat subRegion = result(cv::Range(y - windowSize / 2, y + windowSize / 2 + 1),cv::Range(x - windowSize / 2, x + windowSize / 2 + 1));cv::medianBlur(region, subRegion, windowSize);break;} else {// 增大核大小windowSize += 2;if (windowSize > maxWindowSize) {break;}}}}}return result;
}int main() {// 读取图像cv::Mat image = cv::imread("input_image.jpg", cv::IMREAD_GRAYSCALE);// 应用自适应中值滤波cv::Mat result = adaptiveMedianBlur(image, 11);// 显示原始图像和处理后的图像cv::imshow("Original Image", image);cv::imshow("Adaptive Median Blur Image", result);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

下面对代码做一些解释:
(1)函数需要传入一个原图像和一个滤波核的上限,表示该图像做中值滤波时最大只能用maxWindowSize
(2)最上面两层for循环遍历核中心扫过的像素,例如一个8x8图像被maxWindowSize = 5x5的核扫过的区域如下阴影部分:
在这里插入图片描述
这两层循环确保我们只处理在图像内部且不会越界的像素。这是为了确保局部邻域的提取和处理都在图像内部进行

(3) 根据当前核大小提取局部邻域
cv::Mat region = src(cv::Range(y - windowSize / 2, y + windowSize / 2 + 1),
cv::Range(x - windowSize / 2, x + windowSize / 2 + 1));
代码以被最大核扫过的每个像素分别为当前核的一个中心,提取一个局部邻域,比如当前核为3x3,第一个被扫过像素的局部邻域如下:
在这里插入图片描述
(4)计算邻域的均值和标准差
(5)
if (src.at(y, x) < mean[0] + stddev[0] * 0.5)
这个条件的意思是:如果当前像素 (y, x) 的值小于局部邻域的平均灰度值加上标准差的一半,就执行中值滤波。这样的判断条件旨在处理相对较小的像素值,因为在图像中的边缘或包含细节的区域,这些值可能代表着重要的信息。在这些情况下,使用中值滤波有助于更好地保留细节。如果像素值相对较大,可能处于较均匀的区域,就不执行中值滤波,以免过度平滑图像。

加上标准差的一半的目的是提高容错性,使得判断更加灵活。这个设计的理念是在图像中的一些相对较暗的区域或包含细节的区域,由于灰度值的波动,可能出现一些像素的值略低于整体平均值。通过引入标准差的一半,可以允许更大的变化范围,从而更好地适应图像的局部特征。当然也可以把标准差的一半换成一个固定的值,具体可以根据实验来调整。

下面是带三通道的情况:

cv::Mat adaptiveMedianBlur1(const cv::Mat& src, int maxWindowSize) {cv::Mat result = src.clone();int numChannels = src.channels();for (int y = maxWindowSize / 2; y < src.rows - maxWindowSize / 2; ++y) {for (int x = maxWindowSize / 2; x < src.cols - maxWindowSize / 2; ++x) {int windowSize = 3;  // 初始核大小while (windowSize <= maxWindowSize) {// 提取局部邻域cv::Mat region = src(cv::Range(y - windowSize / 2, y + windowSize / 2 + 1),cv::Range(x - windowSize / 2, x + windowSize / 2 + 1));// 计算标准差cv::Scalar mean, stddev;cv::meanStdDev(region, mean, stddev);// 中值滤波if (numChannels == 1 && src.at<uchar>(y, x) < mean[0] + stddev[0] * 0.5) {// 单通道图像中值滤波cv::Mat subRegion = result(cv::Range(y - windowSize / 2, y + windowSize / 2 + 1),cv::Range(x - windowSize / 2, x + windowSize / 2 + 1));cv::medianBlur(region, subRegion, windowSize);break;}else if (numChannels == 3 &&src.at<cv::Vec3b>(y, x)[0] < mean[0] + stddev[0] * 0.5 &&src.at<cv::Vec3b>(y, x)[1] < mean[1] + stddev[1] * 0.5 &&src.at<cv::Vec3b>(y, x)[2] < mean[2] + stddev[2] * 0.5) {// 三通道图像中值滤波cv::Mat subRegion = result(cv::Range(y - windowSize / 2, y + windowSize / 2 + 1),cv::Range(x - windowSize / 2, x + windowSize / 2 + 1));cv::medianBlur(region, subRegion, windowSize);break;}else {// 增大核大小windowSize += 2;if (windowSize > maxWindowSize) {break;}}}}}return result;
}
在这里插入图片描述

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

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

相关文章

MySQL 插入数据报错 Incorrect string value

当在sys_dict_data表中执行插入语句&#xff1b; insert into sys_dict_data values(1, 1, 男, 0, sys_user_sex, , , Y, 0, admin, sysdate(), , null, 性别男);报错信息如下&#xff1a; insert into sys_dict_data values(1, 1, 男, …

MySQL使用函数和存储过程实现:向数据表快速插入大量测试数据

实现过程 1.创建表 CREATE TABLE user_info (id INT(11) NOT NULL AUTO_INCREMENT,name VARCHAR(20) DEFAULT NULL,age INT(3) DEFAULT NULL,pwd VARCHAR(20) DEFAULT NULL,phone_number VARCHAR(11) DEFAULT NULL,email VARCHAR(255) DEFAULT NULL,address VARCHAR(255) DEF…

鸿蒙学习之TypeScript 语法理解笔记

1、变量及数据类型 // string&#xff1a;字符串&#xff0c;单引号或双引号 let msg : string hello wprld console.log(msg:msg)// number&#xff1a;数值、整数、浮点let num :number 21console.log(num:num)//boolean&#xff1a;布尔let finished: boolean truecons…

替代AMS1117-ADJ可调输出线性稳压器(LDO)

1、概 述 PC1117-ADJ/1.2/1.5/1.8/2.5/2.85/3.3/5是最大输出电流为1A的低压降正向稳压器&#xff0c;其中 PC1117-ADJ是可调输出电压版&#xff0c;只需要两个外接电阻即可实现输出电压在1.25V~13.8V范围内的调节&#xff0c;而PC1117-1.2/1.5/1.8/2.5/2.85/3.3/5是固定输出1.…

[linux] kaggle 数据集用linux下载

你可以通过以下步骤获取Kaggle的下载链接并在Linux中进行下载&#xff1a; 首先&#xff0c;确保你已经安装了Python和Kaggle API。如果没有安装&#xff0c;你可以通过以下命令安装&#xff1a; pip install kaggle 接着&#xff0c;你需要在Kaggle网站上获取API Token。登录…

腾讯云手动下发指令到设备-用于设备调试

打开腾讯云API Explorer&#xff0c;Publish Msg https://console.cloud.tencent.com/api/explorer?Productiotcloud&Version2021-04-08&ActionPublishMessagehttps://console.cloud.tencent.com/api/explorer?Productiotcloud&Version2021-04-08&ActionPub…

iptalbes firewalld

一、IPtables介绍Iptables(以下简称Iptables)是unix/linux自带的一款优秀且开放源代码的完全自由的基于包过滤(对OSI模型的四层或者是四层以下进行过滤)的防火墙工具&#xff0c;它的功能十分强大&#xff0c;使用非常灵活&#xff0c;可以对流入和流出服务器的数据包进行很精细…

蓝桥杯-03-蓝桥杯学习计划

蓝桥杯-03-蓝桥杯学习计划 参考资料 相关文献 报了蓝桥杯比赛&#xff0c;几乎零基础&#xff0c;如何准备&#xff0c;请大牛指导一下。谢谢&#xff1f; 蓝桥杯2022各组真题汇总(完整可评测) 基础学习 C语言网 ACM竞赛入门,蓝桥杯竞赛指南 廖雪峰的官方官网 算法题单 洛谷…

深圳找工作的网站

深圳吉鹿力招聘网是一家在深圳做的比较好的招聘网站&#xff0c;提供一站式的专业人力资源服务&#xff0c;包括网络招聘、校园招聘、猎头服务、招聘外包、企业培训以及人才测评等。深圳吉鹿力招聘网在深圳的口碑相当好&#xff0c;是一个很好的选择。 深圳找工作用 吉鹿力招聘…

ssrf介绍、相关php函数及demo演示

SSRF系列 危害&#xff08;利用&#xff09; 漏洞判断 回显 延时 DNS请求 相关函数

Python的文件的读写操作【侯小啾Python基础领航计划 系列(二十七)】

Python_文件的读写操作【侯小啾Python基础领航计划 系列(二十七)】 大家好,我是博主侯小啾, 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔…

燃烧效果:Burning Shader

NEW! Added HDRP 14.0 shaders NEW! Added HDRP 10.0 shaders NEW!

硬件基础:MOS管

MOSFET概述 MOSFET由MOS(Metal Oxide Semiconductor金属氧化物半导体)FET(Field Effect Transistor场效应晶体管)这个两个缩写组成&#xff0c;即全称为金属氧化物场效应管&#xff0c;简称MOS管。 即通过给金属层(M-金属铝)的栅极和隔着氧化层(O-绝缘层SiO2)的源极施加电压&am…

Intellij idea 快速定位到文件的开头或者结尾的几种方式

方式一&#xff1a;Scroll To Top / Scroll To Bottom 首先打开Keymap设置&#xff0c;并搜索Scroll To 依次点击File->Settings->Keymap可打开该界面 对于Scroll To Top 快速滑动定位到文件顶部&#xff0c; Scroll To Bottom快速定位到文件底部 默认是没有设置快捷键的…

虹科分享 | 平衡速度和优先级:为多样化的实时需求打造嵌入式网络(4)——从理论到实践:CANopen源代码配置

正如前文所述&#xff0c;CANopen的适应性在满足实时应用需求方面发挥着至关重要的作用。本系列文章的最后一部分将向您展示 CANopen 源代码配置的技术细节&#xff0c;以及实现高效实时性能的优化方法。 前文回顾&#xff1a; 虹科分享 | 平衡速度和优先级&#xff1a;为多样…

git打tag和版本控制规范

我们在开发中经常会遇到要打tag的情况&#xff0c;但这个tag应该如何打呢&#xff1f;我不知道大家平时是怎么打的&#xff0c;但我基本就是从1.0.0开始进行往上递增&#xff0c;至于如何递增&#xff0c;基本凭感觉。今天同事新打了一个tag进行发版&#xff0c;然后被架构点名…

博捷芯:半导体芯片切割,一道精细工艺的科技之门

在半导体制造的过程中&#xff0c;芯片切割是一道重要的环节&#xff0c;它不仅决定了芯片的尺寸和形状&#xff0c;还直接影响到芯片的性能和使用效果。随着科技的不断进步&#xff0c;芯片切割技术也在不断发展&#xff0c;成为半导体制造领域中一道精细工艺的科技之门。 芯片…

git的安装及ssh配置(Linux)

环境 CentOS Linux release 7.9.2009 (Core) Xftp7 安装 方法一&#xff1a;yum安装 yum是一个客户端软件&#xff0c;就好比手机上的应用商店&#xff0c;帮助我们对软件的下载、安装和卸载 1、首先查看自己是否安装过git [rootxiaoxi ~]# git -bash: git: command not fo…

小米秒享3--非小米电脑

小米妙享中心是小米最新推出的一款功能&#xff0c;能够为用户们提供更加舒适便利的操作体验。简单的说可以让你的笔记本和你的小米手机联动&#xff0c;比如你在手机的文档&#xff0c;连接小米共享后&#xff0c;可以通过电脑进行操作。 对于非小米电脑想要体验终版秒享AIOT…

如何使用内网穿透工具实现公网访问GeoServe Web管理界面

文章目录 前言1.安装GeoServer2. windows 安装 cpolar3. 创建公网访问地址4. 公网访问Geo Servcer服务5. 固定公网HTTP地址6. 结语 前言 GeoServer是OGC Web服务器规范的J2EE实现&#xff0c;利用GeoServer可以方便地发布地图数据&#xff0c;允许用户对要素数据进行更新、删除…