前言:
欢迎来到本博客
本专栏主要结合OpenCV和C++来实现一些基本的图像处理算法并详细解释各参数含义,适用于平时学习、工作快速查询等,随时更新。
具体食用方式:可以点击本专栏【OpenCV快速查找(更新中)】–>搜索你要查询的算子名称或相关知识点,或者通过这篇博客通俗易懂OpenCV(C++版)详细教程——OpenCV函数快速查找(不断更新中)]查阅你想知道的知识,即可食用。
支持:如果觉得博主的文章还不错或者您用得到的话,可以悄悄关注一下博主哈,如果三连收藏支持就更好啦!这就是给予我最大的支持!
学习目标
- 了解高斯平滑含义
- 熟悉高斯卷积核的构建及分离
- C++实现高斯平滑案例
每一张图像都可能包含某种程度的噪声,噪声可以理解为由一种或者多种原因造成的灰度值的随机变化。
在大多数情况下,通过平滑技术(也常称为滤波技术)进行抑制或者去除,其中具备保持边缘(Edge Preserving)作用的平滑技术得到了更多的关注。
常用的平滑处理算法包括基于二维离散卷积的高斯平滑、均值平滑,基于统计学方法的中值平滑,具备保持边缘作用的平滑算法的双边滤波、导向滤波等。
下面将详细介绍高斯平滑技术原理、常见应用及实现。
一、高斯卷积核的构建及分离性
1.1 相关概念
假设构造宽(列数)为W
、高(行数)为H
的高斯卷积算子gaussKernelH×W,W
和H
均为奇数,锚点(中心点)位置为:[(H-1)/2,(w-1)/2]
,则:
(1) 计算高斯矩阵
r(rows)、c(cols)代表位置索引,其中0≤c≤W-1,0≤r≤H-1,且r,c均为整数。
(2) 计算高斯矩阵的和
(3) 高斯矩阵除以其本身的和,即归一化,得到的便是高斯卷积算子
1.2 高斯卷积算子是可分离卷积核
在计算高斯矩阵过程中:
高斯卷积核可分离成一维水平方向上的高斯核和一维垂直方向上的高斯核,或者反过来,即:
基于这种分离性,OpenCV给出了构建一维垂直方向上的高斯卷积核的函数:
Mat cv::getGaussianKernel(int ksize,
double sigma,
int ktype = CV_64F )
参数 | 解释 |
---|---|
ksize | 一维垂直方向上高斯核的行数,必须为正奇数 |
sigma | 标准差,若不设置,即sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8 |
ktype | 返回值的数据类型,CV_32F或者为CV_64F,默认CV_64F |
返回值就是一个ksize×1
的垂直方向上的高斯核,而对于一维水平方向上的高斯核,只需对垂直方向上的高斯核进行转置即可。
二、C++实现
因为高斯卷积核是可分离的,所以可以通过定义可分离卷积函数sepConv2D_Y_X (此处用sepFilter2D
代替)来实现图像的高斯平滑:
cv::Mat gaussBlur(const Mat &image,Size winsize,float sigma,int ddepth=CV_64F,Point anchor=Point(-1,-1),int boderType=BORDER_DEFAULT) {
//卷积核的宽高须为正基数
CV_Assert(winsize.width % 2 ==1 && winsize.height % 2 == 1);
//构建垂直方向上的高斯核
Mat gK_y = getGaussianKernel(winsize.height,sigma,CV_64F);
//构建水平方向上的高斯核
Mat gK_x = getGaussianKernel(winsize.width, sigma, CV_64F);
//转置
gK_x = gK_x.t();
//分离高斯卷积
Mat BlurImage;
Mat gK_y = getGaussianKernel(winsize.height,sigma,CV_64F);
//sepConv2D_Y_X
sepFilter2D(image,BlurImage, ddepth, gK_y, gK_x, Point(-1, -1));
return BlurImage;
}
OpenCV提供了高斯平滑函数:
void cv::GaussianBlur(InputArray src,
OutputArray dst,
Size ksize,
double sigmaX,
double sigmaY = 0,
int borderType = BORDER_DEFAULT
)
参数 | 解释 |
---|---|
src | 输入矩阵,支持数据类型为:CV_8U, CV_16U, CV_16S, CV_32F or CV_64F |
dst | 输出矩阵,大小与数据类型同src一致 |
ksize | 高斯核大小,宽高均为正奇数,宽高可不相同 |
sigmaX | 一维水平方向上高斯核的标准差 |
sigmaY | 一维垂直方向上高斯核的标准差。若sigmaY为0,则将它设置为等于 sigmaX(即:sigmaY=sigmaX);如果sigmaX和sigmaY都是0,那么就由ksize.width和ksize.height计算出来(计算方式可以查阅上面getGaussianKernel() ,建议指定所有参数值 |
borderType | 边界扩充方式,默认BORDER_DEFAULT |
注:边界扩充说明
从参数的设置可以看出,GaussianBlur()
也是通过分离的高斯卷积核实现的,也可以令水平方向和垂直方向上的标准差不相同,但是一般会取相同的标准差。
当平滑窗口比较小时,对标准差的变化不是很敏感,得到的高斯平滑效果差别不大;相反,当平滑窗口较大时,对标准差的变化很敏感,得到的高斯平滑效果差别较大。
三、 总结
最后,长话短说,大家看完就好好动手实践一下,切记不能三分钟热度、三天打鱼,两天晒网。OpenCV是学习图像处理理论知识比较好的一个途径,大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,有什么问题希望大家可以积极评论交流,我也会及时更新,来督促自己学习进度。希望大家觉得不错的可以点赞、关注、收藏。
今天的文章就到这里啦~
喜欢的话,点赞、收藏️、关注哦 ~
文章评论