【无标题】

c++ 实现高斯滤波

//

#include <iostream>
#include <opencv2/opencv.hpp>

cv::Mat getConvolutionKernel(cv::Size ksize, double sigam);
void GaussinaBlur(cv::Mat& input, cv::Mat& output, cv::Size ksize, double sigam);
void imagePading(cv::Mat& input, cv::Mat& output, int hight, int low, int left, int right);

int main() {

	cv::Mat image = cv::imread("D:\\code\\c++Code\\TestCanny\\111.png", 1);
	image.convertTo(image, CV_64F);
	GaussinaBlur(image, image, cv::Size(11,11), 1.5);

	//cv::GaussianBlur(image, image, cv::Size(11, 11), 1.5);

	cv::normalize(image, image, 0, 1, cv::NORM_MINMAX);
	cv::imshow("gaussian", image);
	cv::waitKey(0);
}




// 高斯滤波
void GaussinaBlur(cv::Mat &input, cv::Mat &output, cv::Size ksize, double sigam) {
	// step1 : 生成卷积核
	cv::Mat convolutionKernel = getConvolutionKernel( ksize,  sigam);
	
	int width = ksize.width;
	int hight = ksize.height;

	int halfWidth = (width - 1) / 2;
	int halfHight = (hight - 1) / 2;
	

	int addHight = halfHight, addLow = halfHight, addLeft = halfWidth, addLight = halfWidth;
	
	cv::Mat pimage;
	imagePading(input, pimage, addHight, addLow, addLeft, addLight);

	// 卷积运算
	output = cv::Mat::zeros(input.size(), input.type());

	if (input.channels() == 1) {
		for (int i = halfHight; i < pimage.rows - halfHight; i++) {
			for (int j = halfWidth; j < pimage.cols - halfWidth; j++) {
				double sumA = 0;
				for (int z = i - halfHight; z <= i + halfHight / 2; z++) {
					for (int h = j - halfWidth; h <= j + halfWidth; h++) {
						sumA += pimage.at<double>(z, h) * convolutionKernel.at<double>(z - (i - halfHight), h - (j - halfWidth));
					}
				}
				pimage.at<double>(i, j) = sumA;
			}
		}
	}
	else if (input.channels() == 3)
	{
		for (int i = halfHight; i < pimage.rows - halfHight; i++) {
			for (int j = halfWidth; j < pimage.cols - halfWidth; j++) {
				cv::Vec3d sumA = 0;
				for (int z = i - halfHight; z <= i + halfHight / 2; z++) {
					for (int h = j - halfWidth; h <= j + halfWidth; h++) {
						sumA[0] += pimage.at<cv::Vec3d>(z, h)[0] * convolutionKernel.at<double>(z - (i - halfHight), h - (j - halfWidth));
						sumA[1] += pimage.at<cv::Vec3d>(z, h)[1] * convolutionKernel.at<double>(z - (i - halfHight), h - (j - halfWidth));
						sumA[2] += pimage.at<cv::Vec3d>(z, h)[2] * convolutionKernel.at<double>(z - (i - halfHight), h - (j - halfWidth));
					}
				}
				pimage.at<cv::Vec3d>(i, j)[0] = sumA[0];
				pimage.at<cv::Vec3d>(i, j)[1] = sumA[1];
				pimage.at<cv::Vec3d>(i, j)[2] = sumA[2];
			}
		}
	}

	output = pimage(cv::Rect(halfHight, halfWidth,input.cols, input.rows));

}

void imagePading(cv::Mat& input, cv::Mat &output, int hight, int low, int left, int right) {

	// 填充0
	int rows = input.rows + hight + low;
	int cols = input.cols + left + right;

	if (input.channels() == 1) {
		output = cv::Mat::zeros(rows, cols, CV_64F);

		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < cols; j++) {
				if (i >= hight && i < rows - low && j >= left && j < cols - right) {

					output.at<double>(i, j) = input.at<double>(i - hight, j - left);
				}
			}
		}
	}
	else if(input.channels() == 3)
	{
		output = cv::Mat::zeros(rows, cols, CV_64FC3);

		for (int c = 0; c < input.channels(); c++) {
			for (int i = 0; i < rows; i++) {
				for (int j = 0; j < cols; j++) {
					if (i >= hight && i < rows - low && j >= left && j < cols - right) {

						output.at<cv::Vec3d>(i, j)[0] = input.at<cv::Vec3d>(i - hight, j - left)[0];
						output.at<cv::Vec3d>(i, j)[1] = input.at<cv::Vec3d>(i - hight, j - left)[1];
						output.at<cv::Vec3d>(i, j)[2] = input.at<cv::Vec3d>(i - hight, j - left)[2];
					}
				}
			}
		}

	}


}

cv::Mat getConvolutionKernel(cv::Size ksize, double sigam) {   // size 

	// 生成卷积核
	cv::Mat convolutionKernel(ksize , CV_64FC1);
	int width = ksize.width;
	int hight = ksize.height;

	int centerW = (width - 1) / 2;
	int centerH = (hight - 1) / 2;

	double x, y;
	double sum = 0;

	for (int i = 0; i < hight; i++) {
		x = std::pow(i - centerH, 2);

		for (int j = 0; j < width; j++) {
			y = std::pow(j - centerW, 2);

			double temp = std::exp(-(x + y) / (2 * std::pow(sigam, 2)));
			convolutionKernel.at<double>(i, j) = temp;
			sum += temp;
		}
	}
	// 归一化
	convolutionKernel = convolutionKernel / sum;


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值