【图像处理OpenCV(C++版)】——5.6 图像平滑之联合双边滤波

前言

😊😊😊欢迎来到本博客😊😊😊

🌟🌟🌟 本专栏主要结合OpenCV和C++来实现一些基本的图像处理算法并详细解释各参数含义,适用于平时学习、工作快速查询等,随时更新。

😊😊😊 具体食用方式:可以点击本专栏【OpenCV快速查找(更新中)】–>搜索你要查询的算子名称或相关知识点,或者通过这篇博客👉通俗易懂OpenCV(C++版)详细教程——OpenCV函数快速查找(不断更新中)]查阅你想知道的知识,即可食用。

🎁🎁🎁支持:如果觉得博主的文章还不错或者您用得到的话,可以悄悄关注一下博主哈,如果三连收藏支持就更好啦!这就是给予我最大的支持!😙😙😙


文章目录

    • 学习目标
    • 一、联合双边滤波原理
    • 二、C++实现
      • 2.1 原理实现
      • 2.2 OpenCV函数
    • 三、 总结

学习目标

  • 了解联合双边滤波含义及原理
  • C++实现联合双边滤波案例

  每一张图像都可能包含某种程度的噪声,噪声可以理解为由一种或者多种原因造成的灰度值的随机变化。
  在大多数情况下,通过平滑技术(也常称为滤波技术)进行抑制或者去除,其中具备保持边缘(Edge Preserving)作用的平滑技术得到了更多的关注。
  常用的平滑处理算法包括基于二维离散卷积高斯平滑、均值平滑,基于统计学方法的中值平滑,具备保持边缘作用的平滑算法的双边滤波、导向滤波等。


一、联合双边滤波原理

  联合双边滤波(Joint bilaterral Filter或称Cross Bilater Filter)与双边滤波类似,原理具体过程如下:

  (1) 首先,对每个位置的邻域构建空间距离权重模板。与双边滤波构建空间距离权重模
板一样。

  (2) 然后构建相似性权重模板。这是与双边滤波唯一的不同之处双边滤波是根据原图,对于每一个位置,通过该位置和其邻域的灰度值的差的指数来估计相似性;而联合双边滤波是首先对原图进行高斯平滑,根据平滑的结果,用当前位置及其邻域的值的差来估计相似性权重模板。

  (3) 接着,空间距离权重模板和相似性权重模板点乘,然后归一化,作为最后的权重模板。最后将权重模板与原图注意不是高斯平滑的结果)在该位置的邻域对应位置积的和作为输出值。整个过程只在第二步计算相似性权重模板时和双边滤波不同,但是对图像平滑的效果,特别是对纹理图像来说,却有很大的不同。


二、C++实现

2.1 原理实现

  通过定义函数jointBLF()实现联合双边滤波,其中参数size代表权重模板的尺寸,Size类的第一个参数是宽,第二个参数是高,即Size(W,H)。具体实现代码如下:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <cmath>
#include <opencv2/imgproc.hpp>using namespace std;
using namespace cv;
cv::Mat getClosenessWeight1(double Sigma_g, Size size) {//获取模板大小int H = size.height;int W = size.width;//获取模板中心点int H_center = (H - 1) / 2;int W_center = (W - 1) / 2;//设置 空间距离权重模板Mat ClosenessWeight = Mat::zeros(size, CV_64FC1);for (int r = 0; r < H; r++){for (int c = 0; c <W; c++){double norm2 = pow(double(r- HH_center),2.0)+ pow(double(c - W_center), 2.0);double Sigma_g2 =2 * pow(Sigma_g, 2.0);//模板赋值ClosenessWeight.at<double>(r, c) = exp(-norm2 / Sigma_g2);}}return ClosenessWeight;
}
}Mat jointBLF(Mat I, Size size,float sigma_g,float sigma_d,int borterType=BORDER_DEFAULT){//构建空间距离得权重模板Mat closenessWeight = getClosenessWeight1(sigma_g, size);//对图片I进行高斯平滑Mat Ig;GaussianBlur(I, Ig, size,sigma_g);int winH = size.height;int winW = size.width;//平滑窗口得高、宽为奇数CV_Assert(winH > 0 && winW > 0);CV_Assert(winH%2==1&& winW%2==1);//中心点int half_winW = (winW - 1) / 2;int half_winH = (winH - 1) / 2;//对原图和高斯平滑后的结果进行边界扩充Mat Ip, Igp;copyMakeBorder(I,Ip, half_winW,half_winW, half_winH, half_winH,borterType);copyMakeBorder(Ig,Igp, half_winW, half_winW,half_winH, half_winH, borterType);//图像得宽高int rows = I.rows;int cols = I.cols;int i=0, j=0;//联合双边滤波后得输出图Mat jblf = Mat::zeros(I.size(), CV_64FC1);for (int r = half_winH; r < half_winH+ rows; r++){for (int c = half_winW; c < half_winW+ cols; c++){//当前位置的像素值double pixel = I.at<double>(r, c);//获取当前位置的作用区域(领域)Mat region = Igp(Rect(c- half_winW,r- half_winH,size.width,size.height));//设置当前位置相似性权重模板Mat similaritWeight;pow(region - pixel, 2.0, similaritWeight);exp(-0.5 * similaritWeight /pow(sigma_d, 2), similaritWeight);//空间距离权重模板与相似性权重模板点乘 并归一化Mat weight = closenessWeight.mul(similaritWeight);weight = weight /sum(weight)[0];//权重模板与当前领域对应位置相乘,求和Mat Iregion = Ip(Rect(c - half_winW,r - half_winH, size.width, size.height));jblf.at<double>(i, j)= sum(Iregion.mul(weight))[0];j += 1;}j = 0;i+=1;}return jblf;			
}

  主函数:

int main() {//输入图像cv::Mat I = imread("D:/VSCodeFile/OpenCV_CSDN/image/img4.jpg", CV_LOAD_IMAGE_GRAYSCALE);if (!I.data){return -1;}Mat fI;I.convertTo(fI,CV_64F,1.0,0);//联合双边滤波Mat jblf = jointBLF(fI, Size(33, 33), 7, 2);Mat jblf8U;jblf.convertTo(jblf8U, CV_8U, 1, 0);//显示imshow("联合双边滤波", jblf);imshow("原图", I);waitKey(0);return 0;
}

2.2 OpenCV函数

  在OpenCV中通过定义函数jointBilateralFilter实现了联合双边滤波的功能:

jointBilateralFilter(InputArray joint,InputArray src,OutputArray dst,int d,double sigmaColor,double sigmaSpace,int borderType = BORDER_DEFAULT 
)		
参数解释
joint进行联合滤波的导向图像,8位或浮点、1通道或3通道图像
src输入图像,可以为单通道或多通道,与joint图像一致
dst输出矩阵,其大小与数据类型和src一致
d表示在过滤过程中每个像素邻域的直径。如果这个值设其为非正数,那么会从第五个参数sigmaSpace来计算出它来,在使用过程中类似于模糊力度。
sigmaColor颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。类似模糊范围的意思,范围越大看着越模糊
sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。值越大,图像的过渡效果越好
borderType推断图像边缘像素的边界模式,默认

三、 总结

  最后,长话短说,大家看完就好好动手实践一下,切记不能三分钟热度、三天打鱼,两天晒网。OpenCV是学习图像处理理论知识比较好的一个途径,大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,有什么问题希望大家可以积极评论交流,我也会及时更新,来督促自己学习进度。希望大家觉得不错的可以点赞、关注、收藏。


🚶🚶🚶 今天的文章就到这里啦~
喜欢的话,点赞👍、收藏⭐️、关注💟哦 ~

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

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

相关文章

【kubernetes系列】kubernetes之计算资源管理

资源类型 在 Kubernetes 中&#xff0c;Node 提供资源&#xff0c;而 Pod 使用资源。其中资源分为计算&#xff08;CPU、Memory、GPU&#xff09;、存储&#xff08;Disk、SSD&#xff09;、网络&#xff08;Network Bandwidth、IP、Ports&#xff09;。这些资源提供了应用运行…

EasyCVR告警类型设置后首页需要刷新才能更新的问题优化

EasyCVR视频融合平台基于云边端一体化架构&#xff0c;可支持多协议、多类型设备接入&#xff0c;包括&#xff1a;NVR、IPC、视频编码器、无人机、车载设备、智能手持终端、移动执法仪等。平台具有强大的数据接入、处理及分发能力&#xff0c;可在复杂的网络环境中&#xff0c…

Appium-Python-Client 源码剖析 (一) driver 的元素查找方法

目录 前言 源码版本:0.9 结构图&#xff1a; mobileby.py appium 的 webdriver.py selenium 的 webdriver.py seleniumdriver appiumdriver 前言 Appium-Python-Client是一个用于Python语言的Appium客户端库&#xff0c;它提供了丰富的API和功能&#xff0c;用于编写和…

cocosCreator 3.6以上接入腾迅Bugly 捕捉JS错误 Android

cocosCreator3.6以上接入Bugly上报其实很简单&#xff0c;不需要网上那么多弯弯绕&#xff0c;三须三步走。 1. 按照官网方式接入android的bugly 2. android端写一个Bugly上报管理类 3. 修改你工程目录下native\engine\common\Classes\目录下的Game.h, Game.cpp两个文件&…

字符串编程练习(C++)

ex1 字符串变形 描述 对于一个长度为 n 字符串&#xff0c;我们需要对它做一些变形。 首先这个字符串中包含着一些空格&#xff0c;就像"Hello World"一样&#xff0c;然后我们要做的是把这个字符串中由空格隔开的单词反序&#xff0c;同时反转每个字符的大小写。…

JS-27 前端数据请求方式;HTTP协议的解析;JavaScript XHR、Fetch的数据请求与响应函数;前端文件上传XHR、Fetch

目录 1_前端数据请求方式1.1_前后端分离的优势1.2_网页的渲染过程 – 服务器端渲染1.3_网页的渲染过程 – 前后端分离 2_HTTP协议的解析2.1_HTTP概念2.2_网页中资源的获取2.3_HTTP的组成2.4_HTTP的版本2.5_HTTP的请求方式2.6_HTTP Request Header2.7_HTTP Response响应状态码 3…

多媒体开发之cgo

go语言作为近十年来优秀的现代开发语言的代表&#xff0c;由于继承了c语言的简洁和很多现代语言的表达方式&#xff0c;在广泛的应用场景中得到众多爱好者的喜爱&#xff0c;如何将go和c、c进行联合开发&#xff0c;拓展整个开发生态&#xff0c;不用重复造轮子&#xff0c;掌握…

P1403 [AHOI2005] 约数研究

题目描述 科学家们在 Samuel 星球上的探险得到了丰富的能源储备&#xff0c;这使得空间站中大型计算机 Samuel II 的长时间运算成为了可能。由于在去年一年的辛苦工作取得了不错的成绩&#xff0c;小联被允许用 Samuel II 进行数学研究。 小联最近在研究和约数有关的问题&…

【redis】redis管道简述

redis管道可以一次性发送多条命令。 命令示例如下&#xff1a; [xxxlocalhost ~]$ echo -e "set k4 99\nincr k4\nget k4" | nc localhost 6379 \OK :100 $3 100下面先简述一下这条命令的组成&#xff0c;再简述一下管道的常用场景和注意事项。 首先&#xff0c;|是…

IDEA 搭建Android 开发环境

项目实战 废话不多说开始创建先第一个 Android 项目 步骤一 FILE → New → Project 步骤二-选择 Android 项目模板 选那个安卓机器人,如果没有这个选项,需要升级IDEA版本或者安装安卓插件 选择*Basic Activity* Next-下一步 步骤三-项目初始化 名称、包名、安装位置自行调整…

双电源并用问题与解决方案

双电源并用问题 曾经有客户在电源模块应用过程中出现过这样的应用场景&#xff0c;如下图1所示。客户使用两路电源给后端电路进行供电&#xff0c;要求在不断电的情况下切换输入电源&#xff0c;此过程中发现后端电路会出现损坏。对各个节点波形进行分析后发现&#xff0c;在给…

【C++】STL之list容器的模拟实现

个人主页&#xff1a;&#x1f35d;在肯德基吃麻辣烫 分享一句喜欢的话&#xff1a;热烈的火焰&#xff0c;冰封在最沉默的火山深处。 文章目录 前言一、list的三个类的关系分析图vector和list的区别1.节点的成员变量以及构造函数2.list的迭代器 二、list的增删查改工作2.1inse…