中值滤波原理及应用
中值滤波器是统计排序滤波器的一种,是一种非线性空间滤波器。中值滤波器是通过其像素邻域内像素排序为基础,然后用这些像素排序后的中值作为该像素点新的像素值,若邻域中有一些像素值相同时,所有相等的值都可作为中值。假如3×3邻域有一系列像素值(12,54,66,5,10,20,70,20,18),排序后为(5,10,12,18,20,20,54,66,70),那么中值就是20。
中值滤波器最有效的就是处理椒盐噪声的能力,但是不适合处理点和线太多的图像。
代码如下:
#include <opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
void select_sort(vector<uchar>&arr)//选择排序
{
for (int i = 0; i < arr.size(); i++)
{
int k = i;
for (int j = i + 1; j < arr.size(); j++)
{
if (arr[k] > arr[j])
{
k = j;
}
}
if (k != i)
{
swap(arr[k], arr[i]);
}
}
}
void mymedianblur(const Mat&src, Mat&dst, Size ksize)//中值滤波
{
//若模板不是奇数模板,则报错退出
if (ksize.width % 2 == 0 || ksize.height % 2 == 0)
{
cout << "please input odd ksize!" << endl;
exit(-1);
}
//根据ksize大小扩充模板边界
int awidth = (ksize.width - 1) / 2;
int aheight = (ksize.height - 1) / 2;
Mat asrc;
copyMakeBorder(src, asrc, aheight, aheight, awidth, awidth, BORDER_DEFAULT);
//根据图像通道数遍历图像求均值
//通道数为1
if (src.channels() == 1)
{
for (int i = aheight; i < src.rows + aheight; i++)
{
for (int j = awidth; j < src.cols + awidth; j++)
{
vector<uchar> arr;
for (int k = i - aheight; k <= i + aheight; k++)
{
for (int l = j - awidth; l <= j + awidth; l++)
{
arr.push_back(asrc.at<uchar>(k, l));
}
}
select_sort(arr);//选择排序
dst.at<uchar>(i - aheight, j - awidth)= arr[(ksize.area() - 1) / 2];//将中值映射到输出图像
}
}
}
//通道数为3
if (src.channels() == 3)
{
for (int i = aheight; i < src.rows + aheight; i++)
{
for (int j = awidth; j < src.cols + awidth; j++)
{
vector<vector<uchar>> arr(3);
for (int k = i - aheight; k <= i + aheight; k++)
{
for (int l = j - awidth; l <= j + awidth; l++)
{
arr[0].push_back(asrc.at<Vec3b>(k, l)[0]);
arr[1].push_back(asrc.at<Vec3b>(k, l)[1]);
arr[2].push_back(asrc.at<Vec3b>(k, l)[2]);
}
}
for (int m = 0; m < 3; m++)
{
select_sort(arr[m]);//选择排序
dst.at<Vec3b>(i - aheight, j - awidth)[m] = arr[m][(ksize.area() - 1) / 2];//将中值映射到输出图像
}
}
}
}
}
int main()
{
Mat src = imread("C:/Users/msi-/Desktop/picture/20190130005650499.png",0);
Mat dst;
dst = Mat::zeros(src.size(), src.type());
imshow("椒盐图片", src);
mymedianblur(src, dst, Size(5, 5));
imshow("滤波处理后的椒盐图片", dst);
waitKey(0);
return 0;
}
初始图片:
滤波后图片: