C++实现灰度图的中值滤波

C++实现灰度图的中值滤波

      • 代码实现
      • 效果
      • 遇到的BUG

中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值。简单点说,就是用模板中所有像素值的中值代替原像素值。

模板可以有很多个,举一个最简单的3*3的模板:
C++实现灰度图的中值滤波_第1张图片
Z5 = mid (Z1,Z2,Z3,Z4,Z5,Z6,Z7,Z8,Z9)

实现的思路:用一个数组存储模板中所有的像素值,进行排序,取数组中的中间值赋值给当前像素点。排序算法有很多,网上搜一下可以直接复制下来。

用的工具是Visual Studio2019opencv-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;
}

效果

C++实现灰度图的中值滤波_第2张图片
C++实现灰度图的中值滤波_第3张图片
百度百科中提到中值滤波法对消除椒盐噪声非常有效,能使图像平滑,在光学测量条纹图象的相位分析处理方法中有特殊作用,但就普通的图像来说只是变的稍稍模糊了。

遇到的BUG

中途有遇到很奇怪的错误:图片只显示一半
C++实现灰度图的中值滤波_第4张图片
这是因为原图像可能不是灰度图,在某行代码上加个参数就可以搞定了

srcImage = imread("1.jpg",0);

0是灰度模式加载,1是彩色模式(默认),-1是原图加载含alpha channel信息

Over!!!

你可能感兴趣的:(数字图像处理,C++,中值滤波,灰度图)