C++实现,基于opencv的高斯滤波

开发环境

opencv版本:opencv4.5.1
VS版本:VS2017
Qt版本:Qt5.12.3

C++实现高斯滤波器

一、目的:去除噪声,使图像平滑。

二、原理

1.一维高斯分布:
在这里插入图片描述
2.二维高斯分布:
在这里插入图片描述
3、高斯滤波一般使用的二维零均值的高斯分布函数,通过高斯分布函数求出模板系数,例如一个3*3的模板:以模板的中心位置为坐标原点进行取样,其中模板各个坐标位置如下图,x轴水平向右,y轴垂直向下,(x,y)表示
在这里插入图片描述

4、将各个位置的坐标代入二维零均值高斯分布函数,计算出来的模板有两种形式:
整数模板和小数模板,可以使用二维数组来存放计算出的模板系数
①小数模板:
在这里插入图片描述
②整数模板:
在这里插入图片描述
伪代码:
输入:目标核,核的大小,sigma值
1.以x,y方向联合实现获取高斯模板
①、取样获得模板
②、将坐标代入高斯公式
③、将对应的值写入高斯核中
④、归一化
输入:原图像,目标图像,核
1.判断原图像是否为空,空则直接返回
2.判断核的是否为奇数
3.原图像边界填充,目标图像清空
4.用高斯核高斯滤波

图像:
原图:
在这里插入图片描述
结果图像:
在这里插入图片描述
部分核心代码:

/ x,y方向联合实现获取高斯模板
void imageJ::GenerateGaussMask(cv::Mat& Mask, cv::Size wsize, double sigma) {
	Mask.create(wsize, CV_64F);
	int h = wsize.height;
	int w = wsize.width;
	int center_h = (h - 1) / 2;
	int center_w = (w - 1) / 2;
	double sum = 0.0;
	double x, y;
	for (int i = 0; i < h; ++i) {
		y = pow(i - center_h, 2);
		for (int j = 0; j < w; ++j) {
			x = pow(j - center_w, 2);
			//因为最后都要归一化的,常数部分可以不计算,也减少了运算量
			double g = exp(-(x + y) / (2 * sigma*sigma));
			Mask.ptr<double>(i)[j] = g;
			sum += g;
		}
	}
	Mask = Mask / sum;
}
// 按二维高斯函数实现高斯滤波
void imageJ::GaussianFilter(cv::Mat& src, cv::Mat& dst, cv::Mat window) {
	int hh = (window.rows - 1) / 2;
	int hw = (window.cols - 1) / 2;
	dst = cv::Mat::zeros(src.size(), src.type());
	//边界填充
	cv::Mat Newsrc;
	cv::copyMakeBorder(src, Newsrc, hh, hh, hw, hw, cv::BORDER_REPLICATE);//边界复制
	dst.zeros(src.size(), src.type());
	//高斯滤波
	for (int i = hh; i < src.rows + hh; ++i) {
		for (int j = hw; j < src.cols + hw; ++j) {
			double sum[3] = { 0 };

			for (int r = -hh; r <= hh; ++r) {
				for (int c = -hw; c <= hw; ++c) {
					if (src.channels() == 1) {
						sum[0] = sum[0] + Newsrc.ptr<uchar>(i + r)[j + c] * window.ptr<double>(r + hh)[c + hw];
					}
					else if (src.channels() == 3) {
						cv::Vec3b rgb = Newsrc.ptr<cv::Vec3b>(i + r)[j + c];
						sum[0] = sum[0] + rgb[0] * window.ptr<double>(r + hh)[c + hw];//B
						sum[1] = sum[1] + rgb[1] * window.ptr<double>(r + hh)[c + hw];//G
						sum[2] = sum[2] + rgb[2] * window.ptr<double>(r + hh)[c + hw];//R
					}
				}
			}

			for (int k = 0; k < src.channels(); ++k) {
				if (sum[k] < 0)
					sum[k] = 0;
				else if (sum[k] > 255)
					sum[k] = 255;
			}
			if (src.channels() == 1)
			{
				dst.ptr<uchar>(i - hh)[j - hw] = static_cast<uchar>(sum[0]);
			}
			else if (src.channels() == 3)
			{
				cv::Vec3b rgb = { static_cast<uchar>(sum[0]), static_cast<uchar>(sum[1]), static_cast<uchar>(sum[2]) };
				dst.ptr<cv::Vec3b>(i - hh)[j - hw] = rgb;
			}

		}
	}

}

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值