一、概述
使用高斯滤镜模糊图像。该函数将源图像与指定的高斯核进行卷积。
在图像处理中,高斯模糊(也称为高斯平滑)是通过高斯函数(以数学家和科学家卡尔弗里德里希高斯命名)对图像进行模糊处理的结果。
它是图形软件中广泛使用的效果,通常用于减少图像噪声和减少细节。这种模糊技术的视觉效果是一种类似于通过半透明屏幕观看图像的平滑模糊效果,与散焦镜头或通常照明下物体的阴影产生 的散景效果明显不同。
高斯平滑也被用作计算机视觉算法的预处理阶段,以增强不同尺度的图像结构。
二、GaussianBlur函数
1、函数原型
cv::GaussianBlur (InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT)
2、参数详解
src | 输入图像; 图像可以有任意数量的通道,它们是独立处理的,但深度应该是 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F。 |
dst | 输出与 src 大小和类型相同的图像。 |
ksize | 高斯核大小。 ksize.width 和 ksize.height 可以不同,但它们都必须是正数和奇数。 或者,它们可以是零,然后根据 sigma 计算它们。 |
sigmaX | X 方向的高斯核标准差。 |
sigmaY | Y方向的高斯核标准差; 如果 sigmaY 为零,则设置为等于 sigmaX,如果两个 sigma 均为零,则分别从 ksize.width 和 ksize.height 计算(详见 getGaussianKernel); 为了完全控制结果,无论将来可能修改所有这些语义,建议指定所有 ksize、sigmaX 和 sigmaY。 |
borderType | 像素外推法,请参阅 BorderTypes。 不支持 BORDER_WRAP。 |
三、OpenCV源码
1、源码路径
opencv\modules\imgproc\src\smooth.dispatch.cpp
2、源码代码
void GaussianBlur(InputArray _src, OutputArray _dst, Size ksize,
double sigma1, double sigma2,
int borderType)
{
CV_INSTRUMENT_REGION();
CV_Assert(!_src.empty());
int type = _src.type();
Size size = _src.size();
_dst.create( size, type );
if( (borderType & ~BORDER_ISOLATED) != BORDER_CONSTANT &&
((borderType & BORDER_ISOLATED) != 0 || !_src.getMat().isSubmatrix()) )
{
if( size.height == 1 )
ksize.height = 1;
if( size.width == 1 )
ksize.width = 1;
}
if( ksize.width == 1 && ksize.height == 1 )
{
_src.copyTo(_dst);
return;
}
bool useOpenCL = ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 &&
_src.rows() >= ksize.height && _src.cols() >= ksize.width &&
ksize.width > 1 && ksize.height > 1;
CV_UNUSED(useOpenCL);
int sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
Mat kx, ky;
createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2);
CV_OCL_RUN(useOpenCL && sdepth == CV_8U &&
((ksize.width == 3 && ksize.height == 3) ||
(ksize.width == 5 && ksize.height == 5)),
ocl_GaussianBlur_8UC1(_src, _dst, ksize, CV_MAT_DEPTH(type), kx, ky, borderType)
);
if(sdepth == CV_8U && ((borderType & BORDER_ISOLATED) || !_src.isSubmatrix()))
{
std::vector<ufixedpoint16> fkx, fky;
createGaussianKernels(fkx, fky, type, ksize, sigma1, sigma2);
static bool param_check_gaussian_blur_bitexact_kernels = utils::getConfigurationParameterBool("OPENCV_GAUSSIANBLUR_CHECK_BITEXACT_KERNELS", false);
if (param_check_gaussian_blur_bitexact_kernels && !validateGaussianBlurKernel(fkx))
{
CV_LOG_INFO(NULL, "GaussianBlur: bit-exact fx kernel can't be applied: ksize=" << ksize << " sigma=" << Size2d(sigma1, sigma2));
}
else if (param_check_gaussian_blur_bitexact_kernels && !validateGaussianBlurKernel(fky))
{
CV_LOG_INFO(NULL, "GaussianBlur: bit-exact fy kernel can't be applied: ksize=" << ksize << " sigma=" << Size2d(sigma1, sigma2));
}
else
{
CV_OCL_RUN(useOpenCL,
ocl_sepFilter2D_BitExact(_src, _dst, sdepth,
ksize,
(const uint16_t*)&fkx[0], (const uint16_t*)&fky[0],
Point(-1, -1), 0, borderType,
8/*shift_bits*/)
);
Mat src = _src.getMat();
Mat dst = _dst.getMat();
if (src.data == dst.data)
src = src.clone();
CV_CPU_DISPATCH(GaussianBlurFixedPoint, (src, dst, (const uint16_t*)&fkx[0], (int)fkx.size(), (const uint16_t*)&fky[0], (int)fky.size(), borderType),
CV_CPU_DISPATCH_MODES_ALL);
return;
}
}
if(sdepth == CV_16U && ((borderType & BORDER_ISOLATED) || !_src.isSubmatrix()))
{
CV_LOG_INFO(NULL, "GaussianBlur: running bit-exact version...");
std::vector<ufixedpoint32> fkx, fky;
createGaussianKernels(fkx, fky, type, ksize, sigma1, sigma2);
static bool param_check_gaussian_blur_bitexact_kernels = utils::getConfigurationParameterBool("OPENCV_GAUSSIANBLUR_CHECK_BITEXACT_KERNELS", false);
if (param_check_gaussian_blur_bitexact_kernels && !validateGaussianBlurKernel(fkx))
{
CV_LOG_INFO(NULL, "GaussianBlur: bit-exact fx kernel can't be applied: ksize=" << ksize << " sigma=" << Size2d(sigma1, sigma2));
}
else if (param_check_gaussian_blur_bitexact_kernels && !validateGaussianBlurKernel(fky))
{
CV_LOG_INFO(NULL, "GaussianBlur: bit-exact fy kernel can't be applied: ksize=" << ksize << " sigma=" << Size2d(sigma1, sigma2));
}
else
{
// TODO: implement ocl_sepFilter2D_BitExact -- how to deal with bdepth?
// CV_OCL_RUN(useOpenCL,
// ocl_sepFilter2D_BitExact(_src, _dst, sdepth,
// ksize,
// (const uint32_t*)&fkx[0], (const uint32_t*)&fky[0],
// Point(-1, -1), 0, borderType,
// 16/*shift_bits*/)
// );
Mat src = _src.getMat();
Mat dst = _dst.getMat();
if (src.data == dst.data)
src = src.clone();
CV_CPU_DISPATCH(GaussianBlurFixedPoint, (src, dst, (const uint32_t*)&fkx[0], (int)fkx.size(), (const uint32_t*)&fky[0], (int)fky.size(), borderType),
CV_CPU_DISPATCH_MODES_ALL);
return;
}
}
#ifdef HAVE_OPENCL
if (useOpenCL)
{
sepFilter2D(_src, _dst, sdepth, kx, ky, Point(-1, -1), 0, borderType);
return;
}
#endif
Mat src = _src.getMat();
Mat dst = _dst.getMat();
Point ofs;
Size wsz(src.cols, src.rows);
if(!(borderType & BORDER_ISOLATED))
src.locateROI( wsz, ofs );
CALL_HAL(gaussianBlur, cv_hal_gaussianBlur, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, cn,
ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, ksize.width, ksize.height,
sigma1, sigma2, borderType&~BORDER_ISOLATED);
CV_OVX_RUN(true,
openvx_gaussianBlur(src, dst, ksize, sigma1, sigma2, borderType))
#if defined ENABLE_IPP_GAUSSIAN_BLUR
// IPP is not bit-exact to OpenCV implementation
CV_IPP_RUN_FAST(ipp_GaussianBlur(src, dst, ksize, sigma1, sigma2, borderType));
#endif
sepFilter2D(src, dst, sdepth, kx, ky, Point(-1, -1), 0, borderType);
}
四、效果图像示例
![](https://img-blog.csdnimg.cn/be4be51e8b9d45f881875fa02eaeebdf.png)
![](https://img-blog.csdnimg.cn/4481c803ed4e491a93a080da29683d0e.png)
![](https://img-blog.csdnimg.cn/8c863d890f9c4db886fde4edf5c87aeb.png)