中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值。简单点说,就是用模板中所有像素值的中值代替原像素值。
模板可以有很多个,举一个最简单的3*3的模板:
Z5 = mid (Z1,Z2,Z3,Z4,Z5,Z6,Z7,Z8,Z9)
实现的思路:用一个数组存储模板中所有的像素值,进行排序,取数组中的中间值赋值给当前像素点。排序算法有很多,网上搜一下可以直接复制下来。
用的工具是Visual Studio2019和opencv-4.1.0,排序算法用的是网上复制下来的插入排序
#include
#include
#include
#include
using namespace cv;
using namespace std;
//像素点的位置数组
int dx[] = { -1,0,1,-1,0,1,-1,0,1 };
int dy[] = { -1,-1,-1,0,0,0,1,1,1 };
//插入排序,返回中间值
int InsertSort(int arr[], int size)
{
for (int i = 1; i < size; i++)
{
int temp = arr[i];
int j = i - 1;
while (j >= 0)
{
if (arr[j] > temp)arr[j + 1] = arr[j];
else break;
j--;
}
arr[j + 1] = temp;
}
return arr[4];
}
//主函数
int main()
{
Mat srcImage;
srcImage = imread("1.jpg",0);//读取图像,与cpp文件同级目录
Mat dst;
dst.create(srcImage.size(),srcImage.type());
cout <<srcImage.rows << ":" << srcImage.cols << " ";
for (int i = 0; i < srcImage.rows; i++) {
for (int j = 0; j < srcImage.cols; j++) {
if ((i - 1) >= 0 && (i + 1) < srcImage.rows && (j - 1) >= 0 && (j + 1) < srcImage.cols) {
int d[9];
for (int k = 0; k < 9; ++k) {
int gray = srcImage.at<uchar>(i + dx[k], j + dy[k]);
d[k] = gray;
}
dst.at<uchar>(i, j) = InsertSort(d, 9);
}
else {
int gray = srcImage.at<uchar>(i, j);
dst.at<uchar>(i, j) = gray;
}
}
}
imshow("中值滤波", dst);
imshow("显示图像", srcImage);
waitKey(0);
return 0;
}
百度百科中提到中值滤波法对消除椒盐噪声非常有效,能使图像平滑,在光学测量条纹图象的相位分析处理方法中有特殊作用,但就普通的图像来说只是变的稍稍模糊了。
中途有遇到很奇怪的错误:图片只显示一半
这是因为原图像可能不是灰度图,在某行代码上加个参数就可以搞定了
srcImage = imread("1.jpg",0);
0是灰度模式加载,1是彩色模式(默认),-1是原图加载含alpha channel信息
Over!!!