高斯滤波分解计算

        根据很多博客和高斯函数的理论知识,高斯函数具有分离性,二维计算可以分解为两个一维高斯计算,这样分解的计算量有很大程度的减少,所以参考众多博客,使用了c++,将网上存在一些可以使用的分离版高斯滤波进行少量调整,使其真正能够使用(至少是我自己能够跑通可以出正确结果),下面将代码分享给大家:

参考自 高斯滤波(GaussianFilter)原理及C++实现_小武的博客-CSDN博客_c++实现高斯滤波

void separateGaussianFilter1(const Mat &src, Mat &dst, int ksize, double sigma)
{
	//Mat src = src1.clone();
	CV_Assert(src.channels() == 1 || src.channels() == 3); // 只处理单通道或者三通道图像
	// 生成一维的高斯滤波模板
	double *matrix = new double[ksize];
	double sum = 0;
	int origin = ksize / 2;
	for (int i = 0; i < ksize; i++)
	{
		// 高斯函数前的常数可以不用计算,会在归一化的过程中给消去
		double g = exp(-(i - origin) * (i - origin) / (2 * sigma * sigma));
		sum += g;
		matrix[i] = g;
	}
	// 归一化
	for (int i = 0; i < ksize; i++)
		matrix[i] /= sum;
	// 将模板应用到图像中
	int border = ksize / 2;
	copyMakeBorder(src, dst, border, border, border, border, cv::BORDER_REPLICATE);
	int channels = dst.channels();
	int rows = dst.rows - border;
	int cols = dst.cols - border;
	// 水平方向
	for (int i = border; i < rows; i++)
	{
		for (int j = border; j < cols; j++)
		{
			double sum[3] = { 0 };
			float* ptr = dst.ptr<float>(i);
			for (int k = -border; k <= border; k++)
			{
				int border_k = border + k;
				int j_k=j+k;
				if (channels == 1)
				{
					sum[0] += matrix[border_k] * ptr[j_k]; // 行不变,列变化;先做水平方向的卷积
				}
				else if (channels == 3)
				{
					int j_k_3 = (j_k)* 3;
					sum[0] += matrix[border_k] * ptr[j_k_3];
					sum[1] += matrix[border_k] * ptr[j_k_3 + 1];
					sum[2] += matrix[border_k] * ptr[j_k_3 + 2];

				}
			}
			for (int k = 0; k < channels; k++)
			{
				if (sum[k] < 0)
					sum[k] = 0;
				else if (sum[k] > 255)
					sum[k] = 255;
			}
			if (channels == 1)
				ptr[j] = static_cast<float>(sum[0]);
			else if (channels == 3)
			{
				int j_3 = j * 3;
				ptr[j_3] = static_cast<float>(sum[0]);
				ptr[j_3 + 1] = static_cast<float>(sum[1]);
				ptr[j_3 + 2] = static_cast<float>(sum[2]);

			}
		}
	}
	// 竖直方向
	for (int i = border; i < rows; i++)
	{
		for (int j = border; j < cols; j++)
		{
			double sum[3] = { 0 };

			for (int k = -border; k <= border; k++)
			{
				float* ptr = dst.ptr<float>(i+k);
				int border_k = border + k;
				if (channels == 1)
				{
					sum[0] += matrix[border_k] * ptr[j]; // 列不变,行变化;竖直方向的卷积
				}
				else if (channels == 3)
				{
					int j_3 = j * 3;
					sum[0] += matrix[border_k] * ptr[j_3];
					sum[1] += matrix[border_k] * ptr[j_3 + 1];
					sum[2] += matrix[border_k] * ptr[j_3 + 2];
				}
			}
			for (int k = 0; k < channels; k++)
			{
				if (sum[k] < 0)
					sum[k] = 0;
				else if (sum[k] > 255)
					sum[k] = 255;
			}
			float* ptr = dst.ptr<float>(i);
			if (channels == 1)
				ptr[j] = static_cast<float>(sum[0]);
			else if (channels == 3)
			{
				int j_3 = j * 3;
				ptr[j_3] = static_cast<float>(sum[0]);
				ptr[j_3 + 1] = static_cast<float>(sum[1]);
				ptr[j_3 + 2] = static_cast<float>(sum[2]);
			}
		}
	}
	dst = dst(Rect(ksize / 2, ksize/2,src.cols,src.rows));
	delete[] matrix;
}

 但是我还是发现两个问题:

1.使用我这个程序,为什么将二维高斯计算分解成两个一维高斯计算,反而计算时间更久了,是代码的问题还是原理的问题,

2.分解计算和利用二维高斯计算得到的结果不是完全相同的(数值不相同,但相差不大),这是为什么呢。

还望广大网友如果知道上述问题的答案,告诉我一声,小渣渣在这里万分感激

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值