利用openCV实现中值滤波自定义滤波窗口尺寸的功能(类似halcon中的median_rect函数功能)

利用openCV实现中值滤波自定义滤波窗口尺寸的功能(类似halcon中的median_rect函数功能)

在halcon图像库中有一个常用的中值滤波算子median_rect:
median_rect(Image : ImageMedian : MaskWidth, MaskHeight : )
其中Image为输入图像,ImageMedian为输出图像,MaskWidth为滤波窗口的宽度,MaskHieght为滤波窗口的高度。
openCV中自带了中值滤波的函数medianBlur:
C++: void medianBlur(InputArray src, OutputArray dst, int ksize)
其中src为输入图像,dst为输出图像,ksize为滤波窗口的大小。
halcon中的中值滤波算子相对于openCV中的中值滤波算子,在滤波窗口上有所不同。在halcon中可以分别定义滤波窗口的宽度与高度,生成一个MaskWidthMaskHeight 大小的滤波窗口,然后openCV中只能定义正方形的尺寸为ksizeksize的滤波窗口,无法分别定义宽度和高度,所以相比halcon中的median_rect算子灵活性不高。
在一个具体的项目中,根据实际情况,需要对图像进行中值滤波,当设定滤波窗口宽度为1,高度为11时效果最佳。然后在利用openCV进行实现时,现有的中值滤波函数medianBlur无法满足要求,因此仿照halcon中的滤波函数进行了编写,其中排序采用的是希尔排序法。由于要处理的图像尺寸不大,且时间要求不高,所以对于编写的程序没做过多速度方面的优化。下面贴出具体的代码。

int medianValue(int arr[], int len)
{
	//希尔排序法
	int N = len;
	for (int gap = N / 2; gap > 0; gap /= 2)
	{
		for (int i = gap; i < N; i++)
		{
			int inserted = arr[i];
			int j;
			for (j = i - gap; j >= 0 && inserted < arr[j]; j -= gap)
			{
				arr[j + gap] = arr[j];
			}
			arr[j + gap] = inserted;
		}
	}
	return (N / 2.0) >(N / 2) ? arr[N / 2] : (arr[N / 2 - 1] + arr[N / 2]) / 2;
}

void mediaImage(Mat srcImage, Mat &outImage,int kernel_w,int kernel_h)
{
	kernel_w = kernel_w % 2 == 0 ? kernel_w + 1 : kernel_w;//滤波窗口边长需要为奇数
	kernel_h = kernel_h % 2 == 0 ? kernel_h + 1 : kernel_h;

	outImage.create(srcImage.size(), srcImage.type());
	
	Mat borderImage;
	copyMakeBorder(srcImage, borderImage, kernel_h / 2, kernel_h / 2, kernel_w / 2, kernel_w / 2, BORDER_DEFAULT);//添加边缘

	uchar* p = NULL;
	uchar* output = NULL;
	int *value = new int[kernel_w*kernel_h];
	
	for (int j = 0; j <= borderImage.rows - kernel_h; j++)//处理行
	{
		output = outImage.ptr(j);
		for (int i = 0; i < borderImage.cols - kernel_w / 2; i++)//处理列
		{
			for (int ptr_i = 0; ptr_i < kernel_h; ptr_i++)
			{
				p = borderImage.ptr(j + ptr_i);
				for (int row_i = 0; row_i < kernel_w; row_i++)
				{
					value[ptr_i*kernel_w + row_i] = (int)p[i + row_i];//将滤波窗口中的数据添加到数组中
				}
			}
			*output++ = medianValue(value, kernel_w*kernel_h);//进行
		}
	}
	p = NULL;
	delete p;
	output = NULL;
	delete output;
}

对编写的这段代码进行了测试,选择一张图像,分别利用这段代码和halcon中的median_rect算子进行处理,滤波窗口尺寸分别为(33),(44),(55),(16),(110),(101),(48),(84),两者处理结果完全相同。不过代码未经优化,在处理速度上要明显慢于halcon中的median_rect算子。下一步考虑在滤波过程中对数组中添加数据以及排序部分进行优化。

水平有限,难免有错误和不足之处,恳请批评指正

你可能感兴趣的:(Halcon,openCV算子)