【图像处理OpenCV(C++版)】——5.3 图像平滑之均值平滑(滤波)

前言

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

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

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

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


文章目录

    • 学习目标
    • 一、均值卷积核的构建及分离性
      • 1.1 相关概念
      • 1.2 均值卷积核构建与分离
    • 二、快速均值平滑
    • 三、 C++实现
      • 3.1 均值平滑
      • 3.2 快速均值平滑
    • 四、 总结

学习目标

  • 了解均值平滑含义
  • 熟悉均值卷积核的构建及分离
  • 熟悉快速均值平滑原理及实现
  • C++实现均值平滑、快速均值平滑案例

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

  下面将详细介绍均值平滑技术原理、常见应用及实现。


一、均值卷积核的构建及分离性

1.1 相关概念

  均值平滑,顾名思义,图像中每一个位置的邻域的平均值作为该位置的输出值

  高为H、宽为W 的均值卷积算子的构建方法很简单,令所有元素均为1/(W*H),即:

  其中,W、H均为奇数,锚点位置为 [(H-1)/2,(W-1)/2]。

1.2 均值卷积核构建与分离

  与高斯滤波核一样,均值平滑算子也是可分离卷积核,即:

  例如:5行3列的均值平滑算子可以进行以下分离:

  代码实现与分离的高斯卷积是类似的,只需将高斯算子替换成均值算子即可。利用卷积核的分离性和卷积的结合律。
  虽然减少了运算量,但是随着卷积核窗口大小的增加,计算量仍会继续增大,可以利用图像的积分,实现时间复杂度为O(1)的快速均值平滑


二、快速均值平滑

  学习快速均值平滑之前,先了解一下图像的积分。r行c列的图像矩阵I的积分Integral可以这样定义:

  即任意一个位置的积分等于该位置左上角所有值的和。例如:

  同时,也可以利用矩阵的积分,计算出矩阵中任意矩形区域的和

  例如:计算I的以(2,2)为中心,从左上角(rTop,cLeft)=(1,1)至右下角(rBottom,cRight)=(3,3)的矩形区域的和:

  可以从积分后的图像矩阵中找到对应的值计算:

即:5+1+7+1+5+9+2+6+2=54+1-8-9

  均值平滑的原理本质上是计算任意一个点的邻域的平均值,而平均值是由该邻域的和除以邻域的面积得到的。这样无论怎样改变平滑窗口的大小,都可以利用图像的积分图快速计算每个点的邻域的和

  对于图像积分,OpenCV提供了函数:


void cv::integral(InputArray src,
OutputArray sum,
int sdepth = -1 
)	
参数解释
src输入H×W矩阵,数据类型为CV_8U、CV_32F或者为CV_64F
sum输出矩阵,大小为(H+1)×(W+1)
depth输出图位深,若为-1则与src一致

  接下来介绍OpenCV均值平滑函数及C++实现快速均值平滑。


三、 C++实现

3.1 均值平滑

  OpenCV提供了函数:

void cv::blur(InputArray src,
		OutputArray dst,
		Size ksize,
		Point anchor = Point(-1,-1),
		int borderType = BORDER_DEFAULT 
)
参数解释
src输入矩阵,数据类型为CV_8U、CV_32F或者为CV_64F
dst输出矩阵,大小和数据类型与src一致
ksize均值平滑卷积核尺寸大小,Size(宽,高)
anchor锚点,Point(-1,-1)表示中心点
borderType边界扩充类型

注:边界扩充说明

  例如:

#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;

int main(){
	cv::Mat src=cv::imread("image/path");
	cv:Mat dst;
	cv::blur(src,dst,Size(3,3),cv::Point(-1,-1));
	cv::imshow("src",src);
	cv::imshow("dst",dst);
	cv::waitKey(0);
	
	return 0;

  还有一个函数,也能实现均值平滑功能:


void cv::boxFilter(InputArray src,
		OutputArray dst,
		int ddepth,
		Size ksize,
		Pointanchor = Point(-1,-1),
		bool normalize = true,
		int borderType = BORDER_DEFAULT 
)	
参数解释
src输入矩阵,数据类型为CV_8U、CV_32F或者为CV_64F
dst输出矩阵,大小和数据类型与src一致
depth输出图位深,若为-1则与src一致
ksize均值平滑卷积核尺寸大小,Size(宽,高)
anchor锚点,Point(-1,-1)表示中心点
normalize是否归一化
borderType边界扩充类型(具体详见上面blur())

3.2 快速均值平滑

  通过定义函数fastMeanBlur()来实现快速均值平滑,其中该函数的参数image代表输入图像winSize代表平滑窗口的尺寸borderType代表边界扩充类型。具体代码如下:

#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 fastMeanBlur(cv::Mat image,cv::Size winSize,int boderType,Scalar value=Scalar()) {
	//判断滑动窗口大小是否为奇数
	int hei = winSize.height;
	int wei = winSize.width;
	CV_Assert(hei % 2 == 1 && wei  % 2 == 1);
	
	//滑动窗口的中心点
	int h_center = (hei - 1) / 2;
	int w_center = (wei - 1) / 2;

	//滑动窗口面积
	float area = float(hei * wei);
	cv::Mat padImg;
	//边界扩充
	cv::copyMakeBorder(image,padImg,h_center, h_center,w_center,w_center,boderType,value);

	//图像积分
	cv::Mat integralImage;
	cv::integral(padImg, integralImage,CV_32FC1);

	//输入图像矩阵宽高
	int cols = image.cols;
	int rows = image.rows;
	int c = 0, r = 0;
	
	Mat meanImage = Mat::zeros(image.size(), CV_32FC1);
	for (int h = h_center;h < h_center+rows; h++)
	{
		for (int w = 0; w < w_center+cols; w++)
		{
			float BottomRight = integralImage.at<float>(h + h_center + 1, w + w_center + 1);
			float TopLeft = integralImage.at<float>(h - h_center, w - w_center);
			float TopRight = integralImage.at<float>(h + h_center + 1, w -w_center);
			float BottomLeft = integralImage.at<float>(h - h_center,w + w_center+1);
			meanImage.at<float>(r, c) =(BottomRight + TopLeft - TopRight - BottomLeft) / area;
			c++;
		}
		r++;
		c = 0;
	}
	return meanImage;
}
	
}	

四、 总结

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


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

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

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

相关文章

Linux终端与进程的关系 ( 1 ) -【Linux通信架构系列】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the…

C高级重点

1、请简要描述一下Linux文件系统的层级结构&#xff0c;包括不同目录的作用和功能。 Linux的文件系统结构是一个倒插树结构&#xff0c;所有的文件都从根目录出发。 2、find指令的用途 find 查找的路径 -name 文件名 ----->在指定路径下&#xff0c;以文件名为条件查找文…

总结vue3 的一些知识点:​Vue3 起步

目录 引言 Vue3 混入 实例 选项合并 实例 实例 全局混入 实例 Vue3 起步 Vue 3.0 实例 data 选项 实例 方法 总结 引言 Vue 进阶系列教程将在本号持续发布&#xff0c;一起查漏补缺学个痛快&#xff01;若您有遇到其它相关问题&#xff0c;非常欢迎在评论中留言讨…

Ubuntu 20.04.02 LTS安装virtualbox7.0

ubuntu22.04的软件仓库也有virtualbox&#xff0c;不过版本较老。 使用安装命令&#xff1a;sudo apt install virtualbox 如果想要安装最新版&#xff0c;那么需要去官网下载deb包或者使用官方的仓库。 这里采用安装Oracle官方仓库的方法。 执行如下命令&#xff1a; wge…

HTTP调用:你考虑到超时、重试、并发了吗?

今天&#xff0c;我们一起聊聊进行 HTTP 调用需要注意的超时、重试、并发等问题。 与执行本地方法不同&#xff0c;进行 HTTP 调用本质上是通过 HTTP 协议进行一次网络请求。网络请求必然有超时的可能性&#xff0c;因此我们必须考虑到这三点&#xff1a; 首先&#xff0c;框架…

抖音本地生活团购服务商

抖音本地生活团购服务商市场前景非常广阔。随着移动互联网的普及和人们对本地生活服务需求的增加&#xff0c;本地生活团购行业已成为一个快速增长的市场。而抖音平台拥有庞大的用户基础和强大的社交媒体传播力&#xff0c;为本地生活团购服务商提供了巨大的发展机遇。 抖音…

【博客674】警惕Prometheus 中的重复样本和无序时间戳错误

警惕Prometheus 中的重复样本和无序时间戳错误 1、场景 您的 Prometheus 服务器日志中是否遇到过以下错误&#xff1f; "Error on ingesting out-of-order samples" "Error on ingesting samples with different value but same timestamp" "dupli…

图解CNN中的卷积(卷积运算、池化、Padding、多通道的卷积)

文章目录 卷积操作池化Padding对多通道&#xff08;channels&#xff09;图片的卷积套上激活函数是什么样的参考&#xff1a; 卷积层是深度学习神经网络中经常使用的一种层。它通过卷积运算来提取输入的特征&#xff0c;常用于图像、语音等信号处理任务中。 卷积层有以下几个参…

探索iOS之Metal编程指南

iOS推出Metal渲染库为了取代OpenGL。Metal有自己的Shader语言&#xff0c;渲染效率比OpenGL高。在这里我们一起探索&#xff1a;Metal使用C限制、预处理定义、动态链接配置、GPU编译配置、设备坐标系、视口坐标系、纹理坐标系、矢量类型、矩阵类型、采样器状态、矩阵相乘。 1、…

第 107 场LeetCode双周赛

A 最大字符串配对数目 显然各字符串对 间匹配的先后顺序不影响最大匹配数目, 可以从后往前遍历数组, 判断前面是否有和当前末尾构成匹配的. class Solution { public:int maximumNumberOfStringPairs(vector<string> &words) {int res 0; while (words.size…

使用 Jetpack Compose 构建 RadioButton

欢迎阅读本篇关于使用 Jetpack Compose 构建 RadioButton&#xff08;单选按钮&#xff09;的博客。Jetpack Compose 是 Google 发布的现代化 UI 工具包&#xff0c;用于构建 Android 界面。它的声明式设计使得 UI 开发更加简洁直观。 一、什么是 RadioButton&#xff1f; Rad…

【深度学习】3-4 神经网络的学习- 学习算法的实现

神经网络的学习步骤如下所示&#xff1a; 步骤1(mini-batch) 从训练数据中随机选出一部分数据&#xff0c;目标是减小mini-batch的损失函数的值 步骤2(计算梯度) 为了减小mini-batch的损失函数的值&#xff0c;需要求出各个权重参数的梯度 步骤3(更新参数) 将权重参数沿梯度…

ModaHub魔搭社区:向量数据库MIlvus服务端配置(四)

目录 常见问题 常见问题 除了配置文件外&#xff0c;怎样可以判断我确实在使用 GPU 做搜索&#xff1f; 有以下三种方式&#xff1a; 使用 nvidia-smi 命令查看 GPU 使用情况。用 Prometheus 配置&#xff0c;详见 使用 Grafana 展示监控指标 > 系统运行指标。使用 Milv…

【完美复现】面向配电网韧性提升的移动储能预布局与动态调度策略【IEEE33节点】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

制造企业实施MES系统受到的影响因素有哪些?

实施MES系统会遇到哪些影响因素&#xff1f;或者说企业实施MES系统的交付率为什么低&#xff1f; 我觉得关键点在于&#xff1a;在当前MES产品化程度普遍不高的大环境下&#xff0c;对项目及管理软件本身认知过于简单&#xff0c;且缺失有经验行业人才&#xff0c;是当前大部分…

windows下安装Visual Studio + CMake+OpenCV + OpenCV contrib+TensorRT

目录 1 安装visual studio 2 安装CMake 3 OpenCV源码安装 3.1 OpenCV源码下载 3.2 OpenCV contrib源码下载 3.3 安装OpenCV 3.4 安装OpenCV-crontrib 3.5 VS生成代码 4 环境配置 5 TensorRT安装 5.1 TensorRT安装 5.2 Python下安装TensorRT库 最近在研究windows系统…

Unity渲染工程收集

NPR 非真实渲染 UnityURP-AnimeStyleCelShader SSR 屏幕空间反射 UnitySSReflectionURP

分布式机器学习(Parameter Server)

分布式机器学习中&#xff0c;参数服务器(Parameter Server)用于管理和共享模型参数&#xff0c;其基本思想是将模型参数存储在一个或多个中央服务器上&#xff0c;并通过网络将这些参数共享给参与训练的各个计算节点。每个计算节点可以从参数服务器中获取当前模型参数&#xf…

架构基本概念和架构本质

什么是架构和架构本质 在软件行业&#xff0c;对于什么是架构&#xff0c;都有很多的争论&#xff0c;每个人都有自己的理解。此君说的架构和彼君理解的架构未必是一回事。因此我们在讨论架构之前&#xff0c;我们先讨论架构的概念定义&#xff0c;概念是人认识这个世界的基础…

UWB超宽带定位技术的原理及定位方法

uwb定位技术即超宽带技术&#xff0c;它是一种无载波通信技术&#xff0c;利用纳秒级的非正弦波窄脉冲传输数据&#xff0c;因此其所占的频谱范围很宽。传统的定位技术是根据信号强弱来判别物体位置&#xff0c;信号强弱受外界 影响较大&#xff0c;因此定位出的物体位置与实际…