图像滤波总结

中值滤波器

        中值滤波器是一种常用的非线性滤波器,其基本原理是:选择待处理像素的一个邻域中各像素值的中值来代替待处理的像素。主要功能使某像素的灰度值与周围领域内的像素比较接近,从而消除一些孤立的噪声点,所以中值滤波器能够很好的消除椒盐噪声。不仅如此,中值滤波器在消除噪声的同时,还能有效的保护图像的边界信息,不会对图像造成很大的模糊(相比于均值滤波器)。

中值滤波器的效果受滤波窗口尺寸的影响较大,在消除噪声和保护图像的细节存在着矛盾:滤波窗口较小,则能很好的保护图像中的某些细节,但对噪声的过滤效果就不是很好,因为实际中的噪声不可能只占一个像素位置;反之,窗口尺寸较大有较好的噪声过滤效果,但是会对图像造成一定的模糊。另外,根据中值滤波器原理,如果在滤波窗口内的噪声点的个数大于整个窗口内非噪声像素的个数,则中值滤波就不能很好的过滤掉噪声。

算法实现:

uchar adaptiveProcess(const Mat &im, int row,int col,int kernelSize,int maxSize)
{vector<uchar> pixels;for (int a = -kernelSize / 2; a <= kernelSize / 2; a++)for (int b = -kernelSize / 2; b <= kernelSize / 2; b++){pixels.push_back(im.at<uchar>(row + a, col + b));}sort(pixels.begin(), pixels.end());auto min = pixels[0];auto max = pixels[kernelSize * kernelSize - 1];auto med = pixels[kernelSize * kernelSize / 2];auto zxy = im.at<uchar>(row, col);if (med > min && med < max){// to Bif (zxy > min && zxy < max)return zxy;elsereturn med;}else{kernelSize += 2;if (kernelSize <= maxSize)return adpativeProcess(im, row, col, kernelSize, maxSize); // 增大窗口尺寸,继续A过程。elsereturn med;}
}

高斯滤波

        高斯滤波也是一种非常常见的滤波方法,其核的形式为:

 

其中是图像中的点的坐标,  为标准差,高斯模板就是利用这个函数来计算的,x和y都是代表,以核中心点为坐标原点的坐标值。这里想说一下 的作用,当 比较小的时候,生成的高斯模板中心的系数比较大,而周围的系数比较小,这样对图像的平滑效果不明显。而当 比较大时,生成的模板的各个系数相差就不是很大,比较类似于均值模板,对图像的平滑效果比较明显。

高斯滤波没有特别多可说的,最主要的作用是滤除高斯噪声,即符合正态分布的噪声。

实现的方式有两种,第一种是按照公式暴力实现,代码如下:

//O(m * n * ksize^2)
void GaussianFilter(const Mat &src, Mat &dst, int ksize, double sigma)
{CV_Assert(src.channels() || src.channels() == 3); //只处理3通道或单通道的图片double **GaussianTemplate = new double *[ksize];for(int i = 0; i < ksize; i++){GaussianTemplate[i] = new double [ksize];}generateGaussianTemplate(GaussianTemplate, ksize, sigma);//paddingint border = ksize / 2;copyMakeBorder(src, dst, border, border, border, border, BORDER_CONSTANT);int channels = dst.channels();int rows = dst.rows - border;int cols = dst.cols - border;for(int i = border; i < rows; i++){for(int j = border; j< cols; j++){double sum[3] = {0};for(int a = -border; a <= border; a++){for(int b = -border; b <= border; b++){if(channels == 1){sum[0] += GaussianTemplate[border+a][border+b] * dst.at<uchar>(i+a, j+b);}else if(channels == 3){Vec3b rgb = dst.at<Vec3b>(i+a, j+b);auto k = GaussianTemplate[border+a][border+b];sum[0] += k * rgb[0];sum[1] += k * rgb[1];sum[2] += k * rgb[2];}}}for(int k = 0; k < channels; k++){if(sum[k] < 0) sum[k] = 0;else if(sum[k] > 255) sum[k] = 255;}if(channels == 1){dst.at<uchar >(i, j) = static_cast<uchar >(sum[0]);}else if(channels == 3){Vec3b rgb = {static_cast<uchar>(sum[0]), static_cast<uchar>(sum[1]), static_cast<uchar>(sum[2])};dst.at<Vec3b>(i, j) = rgb;}}}for(int i = 0; i < ksize; i++)delete[] GaussianTemplate[i];delete[] GaussianTemplate;
}

双边滤波

双边滤波是一种非线性滤波方法,是结合了图像的邻近度和像素值相似度的一种折中,在滤除噪声的同时可以保留原图的边缘信息。整个双边滤波是由两个函数构成:一个函数是由空间距离决定的滤波器系数,另外一个诗由像素差值决定的滤波器系数。整个双边滤波的公式如下:

其中权重系数 取决于定义域核:

和值域核

的乘积。其中定义域核影响的是空间位置,如果把图像看成一个二维函数,那么定义域就是图像的坐标,值域就是该坐标处对应的像素值。定义域核就是普通的高斯核,全局使用一个就可以。但值域核是需要对每个像素点滑动进行计算的。

那么如何理解双边滤波呢

高斯滤波的滤波核的意义是,滤波后的像素值等于窗口内的像素值的加权平均值,权值系数是符合高斯分布,距离该点越近,权值越大。但是没有考虑像素值与当前点的差距。现在加上值域核,意义就在,滤波后当前点的像素值还会受到领域内像素值与自身的像素值差异的影响,不仅仅是距离来决定。这样,在平缓的区域里,由于像素值差异非常小,则值域的权重趋向于1,所以双边滤波就近似为高斯滤波。而在边缘区域中,由于像素值的差异比较大,则值域核趋向于0,权重下降,即当前像素受到领域内像素影响比较小,从而保留了边缘信息。

双边滤波的代码

opencv中提供了bilateralFilter()函数来实现双边滤波操作,其原型如下:

void cv::bilateralFilter(InputArray src,
OutputArray 	dst,
int 	d,
double 	sigmaColor,
double 	sigmaSpace,
int 	borderType = BORDER_DEFAULT 
)		
  • InputArray src: 输入图像,可以是Mat类型,图像必须是8位整型或浮点型单通道、三通道的图像。

  • OutputArray dst: 输出图像,和原图像有相同的尺寸和类型。

  • int d: 表示在过滤过程中每个像素邻域的直径范围。如果这个值是非正数,则函数会从第五个参数sigmaSpace计算该值。

  • double sigmaColor: 颜色空间过滤器的值,这个参数的值月大,表明该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域。 (这个参数可以理解为值域核的 和 )

  • double sigmaSpace: 坐标空间中滤波器的sigma值,如果该值较大,则意味着越远的像素将相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。当d>0时,d指定了邻域大小且与sigmaSpace无关,否则d正比于sigmaSpace. (这个参数可以理解为空间域核的 和 )

  • int borderType=BORDER_DEFAULT: 用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT.

  • #include <iostream>
    #include <opencv2/opencv.hpp>using namespace std;
    using namespace cv;//定义全局变量
    const int g_ndMaxValue = 100;
    const int g_nsigmaColorMaxValue = 200;
    const int g_nsigmaSpaceMaxValue = 200;
    int g_ndValue;
    int g_nsigmaColorValue;
    int g_nsigmaSpaceValue;Mat g_srcImage;
    Mat g_dstImage;//定义回调函数
    void on_bilateralFilterTrackbar(int, void*);int main()
    {g_srcImage = imread("lena.jpg");//判断图像是否加载成功if(g_srcImage.empty()){cout << "图像加载失败!" << endl;return -1;}elsecout << "图像加载成功!" << endl << endl;namedWindow("原图像", WINDOW_AUTOSIZE);imshow("原图像", g_srcImage);//定义输出图像窗口属性和轨迹条属性namedWindow("双边滤波图像", WINDOW_AUTOSIZE);g_ndValue = 10;g_nsigmaColorValue = 10;g_nsigmaSpaceValue = 10;char dName[20];sprintf(dName, "邻域直径 %d", g_ndMaxValue);char sigmaColorName[20];sprintf(sigmaColorName, "sigmaColor %d", g_nsigmaColorMaxValue);char sigmaSpaceName[20];sprintf(sigmaSpaceName, "sigmaSpace %d", g_nsigmaSpaceMaxValue);//创建轨迹条createTrackbar(dName, "双边滤波图像", &g_ndValue, g_ndMaxValue, on_bilateralFilterTrackbar);on_bilateralFilterTrackbar(g_ndValue, 0);createTrackbar(sigmaColorName, "双边滤波图像", &g_nsigmaColorValue,g_nsigmaColorMaxValue, on_bilateralFilterTrackbar);on_bilateralFilterTrackbar(g_nsigmaColorValue, 0);createTrackbar(sigmaSpaceName, "双边滤波图像", &g_nsigmaSpaceValue,g_nsigmaSpaceMaxValue, on_bilateralFilterTrackbar);on_bilateralFilterTrackbar(g_nsigmaSpaceValue, 0);waitKey(0);return 0;
    }void on_bilateralFilterTrackbar(int, void*)
    {bilateralFilter(g_srcImage, g_dstImage, g_ndValue, g_nsigmaColorValue, g_nsigmaSpaceValue);imshow("双边滤波图像", g_dstImage);
    }

    形态学滤波

        在特殊领域运算形式——结构元素(Sturcture Element),在每个像素位置上与二值图像对应的区域进行特定的逻辑运算。运算结构是输出图像的相应像素。运算效果取决于结构元素大小内容以及逻辑运算性质。

结构元素简单地定义为像素的结构(形状)以及一个原点(又称为锚点),使用形态学滤波涉及对图像的每个像素应用这个结构元素,当结构元素的原点与给定的像素对齐时,它与图像相交部分定义了一组进行形态学运算的像素。原则上,结构元素可以是任何形状,但通常使用简单的形状,比如方形、圆形和菱形,而原点位于中心位置(基于效率的考虑)。

腐蚀和膨胀两个滤波操作也运算在每个像素周围像素集合上(邻域),这是由结构元素定义的。当应用到一个给定的像素时,结构元素的锚点与该像素的位置对齐,而所有与他相交的像素都被包括在当前像素集合中。腐蚀替换当前像素为像素集合中找到的最小的像素值,而膨胀则替换为像素集合中找到的最大像素值。当然,对于二值图像,每个像素只能被替换为白色像素或黑色像素。

图像滤波源码可参考:OpenCV+QT实现的图像边缘检测、滤波、特征匹配、特征提取源码

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

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

相关文章

超美!ChatGPT DALL-E 3已可用,另外GPT-4可上传图片进行问答

今天&#xff0c;在ChatGPT里使用DALL-E 3的功能终于上线了。以下是截图&#xff1a; 在GPT-4下加了一个菜单入口&#xff0c;名为 DALL-E 3&#xff0c;这也意味着ChatGPT免费账户暂时不能使用这个功能。 我们体验一下这个功能。 技术交流 建了技术交流群&#xff01;想要进…

解决echarts配置滚动(dataZoom)后导出图片数据不全问题

先展现一个echarts&#xff0c;并配置dataZoom&#xff0c;每页最多10条数据&#xff0c;超出滚动 <div class"echartsBox" id"echartsBox"></div>onMounted(() > {nextTick(() > {var chartDom document.getElementById(echartsBox);…

如何在雷电模拟器上安装Magisk并加载movecert模块抓https包(二)

接来下在PC端安装和配置Charles&#xff0c;方法同下面链接&#xff0c;不再赘述。在模拟器上安装magisk实现Charles抓https包&#xff08;二&#xff09;_小小爬虾的博客-CSDN博客 一、记录下本机IP和代理端口 二、在手机模拟器上设置代理192.168.31.71:8888&#xff0c;设置…

接口自动化测试_L1

目录&#xff1a; 接口自动化测试框架介绍 接口测试场景自动化测试场景接口测试在分层测试中的位置接口自动化测试与 Web/App 自动化测试对比接口自动化测试与 Web/App 自动化测试对比接口测试工具类型为什么推荐 RequestsRequests 优势Requests 环境准备接口请求方法接口请求…

LeetCode【118】杨辉三角

题目&#xff1a; 解析&#xff1a; 该题目解析起来更像是数学推导&#xff0c;找到里面的规律 1、第n行有n个元素 2、第i行第j个元素&#xff0c;为第i-1行&#xff0c;j-1个元素和j个元素的和 3、每行第一个&#xff0c;最后一个元素是1 代码&#xff1a; public List<…

Docker 的数据管理和网络通信

目录 Docker 的数据管理 管理 Docker 容器中数据的方式 端口映射 容器互联&#xff08;使用centos镜像&#xff09; Docker 镜像的创建 Dockerfile 操作常用的指令 编写 Dockerfile 时格式 Dockerfile 案例 Docker 的数据管理 管理 Docker 容器中数据的方式 管理 Doc…

STM32使用HAL库驱动DS3231

1、STM32通讯口配置 启动IIC&#xff0c;默认配置即可。 2、头文件 #ifndef __DS3231_H #define __DS3231_H#include "main.h"#define DS3231_COM_PORT hi2c1 /*通讯端口*//**************************** defines *******************************/ #define DS3231…

cocos2d-x C++与Lua交互

Cocos版本&#xff1a; 3.10 Lua版本&#xff1a; 5.1.4 环境&#xff1a; window Visual Studio 2013 Lua Lua作为一种脚本语言&#xff0c; 它的运行需要有宿主的存在&#xff0c;通过Lua虚拟栈进行数据交互。 它的底层实现是C语言&#xff0c;C语言封装了很多的API接口&a…

ICCV23中的域泛化相关研究

ICCV23中的域泛化相关研究 【OCR】Order-preserving Consistency Regularization for Domain Adaptation and Generalization【iDAG】iDAG: Invariant DAG Searching for Domain Generalization【RIDG】Domain Generalization via Rationale Invariance【3DLabelProp】Domain G…

2023年医药商业行业发展研究报告

第一章 行业概况 1.1 定义 医药商业行业&#xff0c;作为医药领域的重要组成部分&#xff0c;扮演着至关重要的角色。这一行业专注于医药商品的经营与流通&#xff0c;确保药品能够有效、安全地到达消费者手中。随着医药科技的进步和市场需求的增长&#xff0c;医药商业行业在…

Android攻城狮学鸿蒙 -- 点击事件

具体参考&#xff1a;华为官网学习地址 1、点击事件&#xff0c;界面跳转 对于一个按钮设置点击事件&#xff0c;跳转页面。但是onclick中&#xff0c;如果pages前边加上“/”&#xff0c;就没法跳转。但是开发工具加上“/”才会给出提示。不知道是不是开发工具的bug。&#…

C++day6

编程题&#xff1a; 以下是一个简单的比喻&#xff0c;将多态概念与生活中的实际情况相联系&#xff1a; 比喻&#xff1a;动物园的讲解员和动物表演 想象一下你去了一家动物园&#xff0c;看到了许多不同种类的动物&#xff0c;如狮子、大象、猴子等。现在&#xff0c;动物…

ubuntu下查看realsense摄像头查看支持的分辨率和频率

引言&#xff1a; 在实际应用中&#xff0c;摄像头的频率如果过高&#xff0c;可能会造成系统图像处理的压力过大&#xff0c;因此需要选择合适的参数才能达到预期的效果。本文主要探讨设置realsense相关参数 1、打开终端&#xff0c;输入rs-enumerate-devices rs-enumerate-…

Java架构师系统架构设计性能评估

目录 1 导论2 架构评估基础系统性能衡量的基本指标2.1 系统性能的指标2.2 数据库指标2.3 并发用户数2.4 网络延迟2.4 系统吞吐量2.5 资源性能指标 3 架构评估基础服务端性能测试3.1基准测试3.2 负载测试3.3 压力测试3.4 疲劳强度测试3.5 容量测试 1 导论 本章的主要内容是掌握架…

018-第三代软件开发-整体介绍

第三代软件开发-整体介绍 文章目录 第三代软件开发-整体介绍项目介绍整体介绍Qt 属性系统QML 最新软件技术框架 关键字&#xff1a; Qt、 Qml、 属性、 Qml 软件架构 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff08;Qt Meta-Object …

【Kotlin精简】第2章 集合

1 简介 在 Kotlin 中集合主要分为可变集合与只读集合&#xff0c;其中可变集合使用 “Mutable” 前缀 集合类名表示&#xff0c;比如 MutableList、MutableSet、MutableMap 等。而对于只读集合就是和 Java 中集合类名是一致。 Java 中的 List 非 Kotlin 中的 List , 因为 Kot…

风光十几年的MIUI要无了,小米自研MIOS即将就位

今年8月小米新品发布会上&#xff0c;K60 至尊版亮相的同时带来了下一代系统&#xff08;或者说UI &#xff09;的名字&#xff1a;MIUI 15 。 好家伙不知不觉已经要更到 15 了&#xff0c;大家用过几个版本呢&#xff1f; 回想起 MIUI V1 内测发布、MIUI V5 全民刷机、MIUI 8…

skywalking动态配置[集成nacos/apollo/consul]

说明:以下配置仅关于的阈值规则的动态配置,其他参数也可以进行配置。 1,skywalking动态配置集成nacos 编辑application.yml nacos配置参数如下: nacos:# Nacos Server HostserverAddr: 10.10.5.145# Nacos Server Portport: 8848# Nacos Configuration Groupgroup: skywal…

【数据结构】二叉树--链式结构的实现 (遍历)

目录 一 二叉树的遍历 1 构建一个二叉树 2 前序遍历 3 中序遍历 4 后续遍历 5 层序 6 二叉树销毁 二 应用(递归思想) 1 二叉树节点个数 2 叶子节点个数 3 第K层的节点个数 4 二叉树查找值为x的节点 5 判断是否是二叉树 一 二叉树的遍历 学习二叉树结构&#xff0…

TOGAF(企业架构)

TOGAF 核心概念&#xff08;官方原版&#xff09; 什么是TOGAF&#xff1f; TOGAF?是一种经验证的企业架构方法和框架&#xff0c;被世界领先的组织用于提高业务效率。它是一个企业架构标准&#xff0c;确保企业架构专业人员之间的标准、方法和通信一致&#xff0c;以便我们…