【图像处理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是学习图像处理理论知识比较好的一个途径,大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,有什么问题希望大家可以积极评论交流,我也会及时更新,来督促自己学习进度。希望大家觉得不错的可以点赞、关注、收藏。


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

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

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

相关文章

Orleans 微软基于 Actor 的分布式框架

一、Actor模型工作原理 Actor模型是一种并发编程模型&#xff0c;它基于消息传递实现&#xff0c;是一种轻量级的并发模型。在Actor模型中&#xff0c;每个Actor都是一个独立的执行单元&#xff0c;它可以接收和发送消息&#xff0c;并且可以执行一些本地操作&#xff0c;但是不…

Internet Download Manager IDM 破解版 中文便携版 v6.41.15

Internet Download Manager 介绍 Internet Download Manager&#xff0c;全球最佳下载利器。Internet Download Manager (简称IDM) 是一款Windows 平台功能强大的多线程下载工具&#xff0c;国外非常受欢迎。支持断点续传&#xff0c;支持嗅探视频音频&#xff0c;接管所有浏览…

【Python爬虫开发基础⑭】Scrapy架构(组件介绍、架构组成和工作原理)

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;python网络爬虫从基础到实战 欢迎订阅&#xff01;后面的内容会越来越有意思~ &#x1f4a1;往期推荐&#xff1a; ⭐️前面比较重要的基础内容&#xff1a; 【Python爬…

【ArcGIS Pro微课1000例】0028:绘制酒店分布热力图(POI数据)

本文讲解在ArcGIS Pro中文版中,基于长沙市酒店宾馆分布矢量点数据(POI数据)绘制酒店分布热力图。 文章目录 一、加载酒店分布数据二、绘制热度图参考阅读: 【GeoDa实用技巧100例】004:绘制长沙市宾馆热度图 【ArcGIS微课1000例】0070:制作宾馆酒店分布热度热力图 一、加载…

从0到1构建证券行业组织级项目管理体系的探索与实践︱东吴证券PMO负责人娄鹏呈

东吴证券股份有限公司信息技术总部PMO负责人娄鹏呈先生受邀为由PMO评论主办的2023第十二届中国PMO大会演讲嘉宾&#xff0c;演讲议题&#xff1a;从0到1构建证券行业组织级项目管理体系的探索与实践。大会将于8月12-13日在北京举办&#xff0c;敬请关注&#xff01; 议题简要&a…

联通 Flink 实时计算平台化运维实践

摘要&#xff1a;本文整理自联通数科实时计算团队负责人、Apache StreamPark Committer 穆纯进在 Flink Forward Asia 2022 平台建设专场的分享&#xff0c;本篇内容主要分为四个部分&#xff1a; 实时计算平台背景介绍 Flink 实时作业运维挑战 基于 StreamPark 一体化管理 …

力扣题目解析:生成奇数个字符的字符串的巧妙方法

本篇博客会讲解力扣“1374. 生成每种字符都是奇数个的字符串”的解题思路&#xff0c;这是题目链接。 这道题的解题思路很巧妙&#xff0c;它利用了字符串长度n的奇偶性&#xff1a; 如果n是奇数&#xff0c;那么就把字符串全部填充为’a’&#xff0c;这样每种字符都是奇数个…

基于linux下的高并发服务器开发(第一章)- 目录遍历函数

10 / 目录遍历函数 // 打开一个目录 #include <sys/types.h> #include <dirent.h>DIR *opendir(const char *name); 参数&#xff1a; - name: 需要打开的目录的名称 返回值&#xff1a; DIR * 类型&#xff0c;理解为目录流 错误…

网络安全/黑客技术—学习笔记

一、什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防两面…

韦东山Linux驱动入门实验班(4)LED驱动

前言 &#xff08;1&#xff09;我们学习完hello驱动之后&#xff0c;对驱动程序开发有了一点点认识了之后。现在可以开始对硬件进行实际操作了&#xff0c;本人使用的是i.max6ull开发板&#xff0c;STM32MP157和全志的D1H也会进行讲解。 &#xff08;2&#xff09;如果还有对于…

Simulink仿真模块 - Data Store Read

Data Store Read:从数据存储中读取数据 在仿真库中的位置为:Simulink / Signal Routing 模型为: 说明 Data Store Read 模块将指定数据存储中的数据复制到其输出中。多个 Data Store Read 模块可从同一个数据存储读取数据。 用来读取数据的源数据存储由 Data Store Memory 模…

低代码技术:提高效率降低成本的全新选择

一、前言 企业想要独立的应用程序&#xff0c;开发者在寻求更快速、更高效、更灵活的开发方法&#xff0c;以适应快速变化的市场需求。在这个背景下&#xff0c;低代码技术以提高效率降低成本的方式走进人们视野&#xff0c;成为了一种全新的应用程序开发方式。 二、相比传统的…

手写IOC

IOC原理(手写IOC) Spring框架的IOC是基于反射机制实现的。 反射回顾 Java反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff0c;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性&#xff1b;这种动态获取信息…

在Linux下做性能分析1:基本模型

介绍 本Blog开始介绍一下在Linux分析性能瓶颈的基本方法。主要围绕一个基本的分析模型&#xff0c;介绍perf和ftrace的使用技巧&#xff0c;然后东一扒子&#xff0c;西一扒子&#xff0c;逮到什么说什么&#xff0c;也不一定会严谨。主要是把这个领域的一些思路和技巧串起来。…

解码 LangChain|用 LangChain 和 Milvus 从零搭建 LLM 应用

如何从零搭建一个 LLM 应用&#xff1f;不妨试试 LangChain Milvus 的组合拳。 作为开发 LLM 应用的框架&#xff0c;LangChain 内部不仅包含诸多模块&#xff0c;而且支持外部集成&#xff1b;Milvus 同样可以支持诸多 LLM 集成&#xff0c;二者结合除了可以轻松搭建一个 LLM…

计算机科学与技术专业课程内容汇总

大学课程结束了&#xff0c;真的好快。昨天把专业课程涉及到的内容汇总了下&#xff0c;还是挺多的&#xff0c;存到网盘里也不会丢&#xff0c;电脑存储空间还能扩大。 把网盘链接放在这里&#xff0c;希望大家共勉。图片中所涉内容仅为部分课程。 链接&#xff1a;https://…

7.kafka+ELK连接

文章目录 kafkaELK连接部署Kafkakafka操作命令kafka架构深入FilebeatKafkaELK连接 kafkaELK连接 部署Kafka ###关闭防火墙systemctl stop firewalld systemctl disable firewalldsetenforce 0vim /etc/selinux/configSELINUXdisabled###下载安装包官方下载地址&#xff1a;ht…

js小写金额转大写 自动转换

// 小写转为大写convertCurrency(money) {var cnNums [零, 壹, 贰, 叁, 肆, 伍, 陆, 柒, 捌, 玖]var cnIntRadice [, 拾, 佰, 仟]var cnIntUnits [, 万, 亿, 兆]var cnDecUnits [角, 分, 毫, 厘]// var cnInteger 整var cnIntLast 元var maxNum 999999999999999.9999var…

船舶中压配电板应用弧光保护,可解决母排故障短路问题,对于提高船舶电站的安全性、稳定性,降低经济损失具有重要意义。-安科瑞黄安南

摘要&#xff1a;船舶中压配电板弧光故障导致的设备损坏和停电事故&#xff0c;不仅会造成较大的经济损失&#xff0c;而且严重影响船舶电站的安全稳定运行&#xff0c;威胁船舶电站操作人员的安全。弧光保护是基于电力系统开关柜发生弧光故障时而设计的一套母线保护系统&#…

使用testify包辅助Go测试指南

我虽然算不上Go标准库的“清教徒”&#xff0c;但在测试方面还多是基于标准库testing包以及go test框架的&#xff0c;除了需要mock的时候&#xff0c;基本上没有用过第三方的Go测试框架。我在《Go语言精进之路》[2]一书中对Go测试组织的讲解也是基于Go testing包和go test框架…