"
【自写】使用高斯滤波来处理图像
"
一、算法的原理
1.高斯滤波:
高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波器是一类根据高斯函数的形状来选择权值的线性平滑滤波器,对于抑制服从正态分布的噪声非常有效。
2. 算法实现:
可以简单地理解为是对整幅图像像素值进行加权平均,针对每一个像素点的值,都由其本身值和邻域内的其他像素值经过加权平均后得到。
具体操作:用一个用户指定的模板(或称卷积、掩膜)去扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。
一维高斯分布:
二维高斯分布:
二、步骤:
○读取原图片。
○确定内核值,初始化输出图片大小和零值。
○通过二维高斯分布的公式,根据内核值大小创建一个正态分布且已经归一化的卷积核。
○通过反射101来扩充原图片的边界
○分通道进行原图片和卷积核间的卷积,输出结果图片。
○与原函数进行对比。
三、代码:
#include<iostream>
#include<algorithm>
#include<opencv2\core.hpp>
#include<opencv2\highgui.hpp>
#include<opencv2\imgproc.hpp>
using namespace cv;
using namespace std;
Mat srcimg;
int Value = 3;
Mat getgausssian(int n, double sigma)
{
int x, y, t = 0;
double m1, m2, sum = 0;
double zhi = -1 / (2 * sigma*sigma);
double xi = 1 / (2 * sigma*sigma*3.14159);
Mat gausssian(n, n, CV_64FC1);
if (sigma <= 0)
sigma = 0.3 *((n - 1) *0.5 - 1) + 0.8;
for (x = 0, m1 = x - (n - 1) / 2; x < n; x++, m1++)
{
for (y = 0, m2 = y + (n - 1) / 2; y < n; y++, m2--)
{
gausssian.at<double>(x, y) = (double)exp(zhi*(m1*m1 + m2 * m2));
}
}
for (x = 0, m1 = x - (n - 1) / 2; x < n; x++, m1++)
{
for (y = 0, m2 = y + (n - 1) / 2; y < n; y++, m2--, t++)
{
sum += gausssian.at<double>(x, y);
}
}
for (x = 0, m1 = x - (n - 1) / 2; x < n; x++, m1++)
{
for (y = 0, m2 = y + (n - 1) / 2; y < n; y++, m2--, t++)
{
gausssian.at<double>(x, y) /= sum;
}
}
return gausssian;
}
void gausssianFilter(Mat src, Mat & dst, Size ksize, double sigmaX, double sigmaY = 0)
{
int n = ksize.width;
int channel = src.channels();
if (sigmaX <= 0 && sigmaY <= 0)
{
sigmaX = 0.3 *((ksize.width - 1) *0.5 - 1) + 0.8;
sigmaY = 0.3 *((ksize.height - 1) *0.5 - 1) + 0.8;
}
Mat gausssian = getgausssian(n, sigmaX);
copyMakeBorder(src, src, 0, n-1, 0, n-1, BORDER_REFLECT_101);
int dst_w = src.cols - ksize.width + 1;
int dst_h = src.rows - ksize.height + 1;
for (int m = 0; m < channel; m++)
{
for (int i = 0; i < dst_h; i = i++)
{
for (int j = 0; j < dst_w; j = j++)
{
double g = 0;
for (int z = 0; z < ksize.height; z++)
{
for (int q = 0; q < ksize.width; q++)
{
g += src.at<Vec3b>(z + i, q + j)[m] * gausssian.at<double>(z, q);
//图像变暗是因为int数据丢失了太多微小数据
}
}
dst.at<Vec3b>(i, j)[m] = g;
}
}
}
}
int main()
{
srcimg = imread("C:\\Users\\DELL\\Desktop\\tu1.png");
Mat dstimg(Size(srcimg.cols, srcimg.rows), srcimg.type(), Scalar(0));
Mat dst666;
gausssianFilter(srcimg, dstimg, Size(Value * 2 + 1, Value * 2 + 1), 0, 0);
GaussianBlur(srcimg, dst666, Size(Value * 2 + 1, Value * 2 + 1), 0, 0);
imshow("原图", srcimg);
imshow("已知核半径的高斯滤波图", dstimg);
imshow("原函数的图", dst666);
waitKey(0);
return 0;
}
代码结果展示:
这个有很多东西都很基础,还可以完善…有问题可以在评论区回复,如果觉得有帮助,可以点个赞或者留个言支持一下,谢谢。