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;
}