空间滤波
空间滤波原理
图像的滤波分为频率滤波和空间滤波,顾名思义频率滤波是在频率上进行相应的操作,而空间滤波是在空域上对像素的邻域进行一系列的操作以达到相应的效果的方法。空滤滤波在图像边界上回存在邻域像素不足的情况,而本文的解决方案是用零来填充,当然你也可以用其它合适的方法来解决这一问题。
算术均值滤波
算术均值滤波算是一种比较简单的滤波,它的做法是对图像像素点的邻域进行进行求和取均值。这种做法可以滤除图像细小细节,包含噪声(算是图像的细节部分),根据滤波模板的大小可决定滤波细节的大小,但同时会使图像的的边缘模糊。此滤波方法可用于高斯噪声的滤波,因为高斯噪声的均值是零(补充:高斯滤波对高斯噪声处理的效果更好, 原因:增大了中心像素的权重系数,计算结果更接近原图像像素值,保持图像不会过于模糊)。对于一些特征提取操作,使用模糊图像效果更好,因为细节部分更少,大部分融入了背景,使得网络更加容易训练。
参考代码
#include<iostream>
#include<string>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
void test1();
Mat arithmeticMeanFilter(Mat &src, int size);
void test2();
cv::Mat addSaltNoise(const cv::Mat &src, int n, int op);
Mat middleFilter(Mat &src, int size);
double findNumber(double* num, int start, int end, int n);
void test3();
Mat laplasFilter(Mat &src, bool standard, bool sharpen);
double standardImageSingleArray(Mat &src, double* num, int rank);
uchar pixesDeal(double n);
Mat standardImageSingle(Mat &src, int rank);
Mat addImage(Mat &src1, Mat &src2, double rate1, double rate2, double zero, bool standard);
void test4();
void test5();
Mat sobelFilter(Mat &src);
int main()
{
test1();
test2();
test3();
test4();
test5();
return 0;
}
// 测试一
void test1()
{
// 获取彩色图像
Mat src = imread("D:/ali.png", 1);
Mat dst = arithmeticMeanFilter(src, 5);
// 显示
imshow("原图", src);
imshow("算术均值滤波", dst);
waitKey(0);
destroyAllWindows();
}
// 算术均值滤波
Mat arithmeticMeanFilter(Mat &src, int size)
{
if (src.channels() == 3)
{
vector<Mat> bgr;
// 通道分离
split(src, bgr);
// 通道遍历
for (int i = 0; i < 3; i++)
// 算术均值滤波
bgr[i] = arithmeticMeanFilter(bgr[i], size);
// 通道合并
Mat dst;
merge(bgr, dst);
return dst;
}
// 深拷贝
Mat dst = src.clone();
double sum;
// 遍历像素
for (int i = 0; i < src.rows; i++)
for (int j = 0; j < src.cols; j++)
{
// 初始化
sum = 0;
// 遍历模板
for (int n = -size/2; n <= size/2; n++)
for (int m = -size/2; m <= size/2; m++)
{
// 边缘补零
if (i + n < 0 || j + m < 0 || i + n >= src.rows || j + m >= src.cols)
sum += 0;
else
sum += dst.at<uchar>(i + n, j + m);
}
dst.at<uchar>(i, j) = saturate_cast<int>(sum / (size*size));
}
return dst;
}
效果图与应用场景


从图中可明显感受到图像的边缘变得模糊,对于高斯噪声的去噪效果后续文章会有介绍。
中值滤波
中值滤波是根据像素点邻域的大小,取其均值代替中心点的像素值,是一种非线性滤波。中值滤波的设计是出于对椒盐噪声的处理。用均值滤波效果不太好,因为噪声的均值不等于零。而中值滤波可有效滤除图像上的极值点,对椒盐噪声的滤波效果极好。
参考代码
// 测试二
void test2()
{
// 获取彩色图像
Mat src = imread("D:/ali.png", 1);
// 添加椒盐噪声
Mat noise = addSaltNoise(src, 10000, 0);
// 中值滤波
Mat dst = middleFilter(noise, 3);
// 显示
imshow("原图", src);
imshow("椒盐噪声图", noise);
imshow("中值滤波", dst);
waitKey(0);
destroyAllWindows();
}
// 添加椒盐噪声op=0, 添加盐粒噪声op=1, 添加胡椒噪声op=2
cv::Mat addSaltNoise(const cv::Mat &src, int n, int op)
{
cv::Mat dst = src.clone();
if (op == 0 || op == 1)
{
for (int k = 0; k < n; k++)
{
int i = rand() % dst.rows;
int j = rand() % dst.cols;
// 通道判定
if (dst.channels() == 1)
{
dst.at<uchar>(i, j) = 255; // 添加盐噪声
}
else
{
dst.at<cv::Vec3b