中值滤波的延时性问题

关于中值滤波算法的几点注意事项:

1.根据相关文献报道[1],滤波窗口宽度设置在采样率的80~90%[2],是为合理宽度;

2.中值滤波之后的基线数据(滤波过程中,笔者初始化窗口值为0),应左移半窗口宽度后,与原数据对应相减,所得数据为去基线漂移后的数据;

3.对于原数据,在进行中值滤波前,需要进行尾部延拓半窗口宽度(与中值滤波延时对应),笔者将延拓部分取值0;

4.对应相减时,取基线数据从半窗口宽度处始,至结尾止,并按此顺序与原数据(延拓前)对应相减。


实验结果对比:

通过对比

origin_data[i] - med_data[i],

origin_data[i] - med_data[i + half_win_width]以及

origin_data[i + half_win_width] - med_data[i]三者图像,


发现中值滤波效果最佳者

为origin_data[i] - med_data[i + half_win_width],

origin_data[i] - med_data[i]次之,

origin_data[i + half_win_width] - med_data[i]最差。


此对比从一定程度上证明了上述的中值滤波延时结论。


顺序中值滤波代码:

中值获取:

#ifndef __MEDIAN_H__
#define __MEDIAN_H__

class Wave_filter
{
public:
	Wave_filter();
	~Wave_filter();

	void reset(void);
	void get_median(int, int &);
	void get_median(int *, int, int *&);
private:
#ifndef SAMPLARATE
#define SAMPLERATE 250
#endif // !SAMPLARATE
#ifndef MEDWIDTH
#define MEDWIDTH SAMPLERATE * 8 /10 + 1
#endif // !MEDWIDTH

	int median(int), *value_pool, *time_pool, ers_pos, add_pos, running_time, time_pos;
};

#endif // ! __MEDIAN_H__

#include "Median.h"

Wave_filter::Wave_filter() :ers_pos(-1), add_pos(-2), time_pos(0)
{
	value_pool = new int[MEDWIDTH]();
	time_pool = new int[MEDWIDTH]();
	running_time = 0;
	for (int i = MEDWIDTH; i > 0; running_time++)
	{
		i >>= 1;
	}
}

Wave_filter::~Wave_filter()
{
	delete[] value_pool;
	delete[] time_pool;
}

void Wave_filter::reset()
{
	ers_pos = add_pos = -1;
	time_pos = 0;
	for (int i = 0; i < MEDWIDTH; i++)
	{
		time_pool[i] = value_pool[i] = 0;
	}
}

int Wave_filter::median(int data)
{
	if (time_pos >= MEDWIDTH)
	{
		time_pos = 0;
	}

	int left_bd = 0, mid_pos;

	for (int i = 0; i < running_time; i++)
	{
		mid_pos = MEDWIDTH >> (i + 1);
		if (time_pool[time_pos] == value_pool[left_bd + mid_pos])
		{
			ers_pos = left_bd + mid_pos;
			break;
		}
		else if (time_pool[time_pos] > value_pool[left_bd + mid_pos])
		{
			left_bd += mid_pos;
		}
		if (mid_pos < 1)
		{
			while (time_pool[time_pos] > value_pool[left_bd + mid_pos])
			{
				mid_pos++;
			}
			ers_pos = left_bd + mid_pos;
		}
	}

	left_bd = 0;

	if (data < value_pool[0])
	{
		add_pos = -1;
	}
	else if (data >= value_pool[MEDWIDTH - 1])
	{
		add_pos = MEDWIDTH - 1;
	}
	else
	{
		for (int i = 0; i < running_time; i++)
		{
			mid_pos = MEDWIDTH >> (i + 1);
			if (data >= value_pool[left_bd + mid_pos] && data < value_pool[left_bd + mid_pos + 1])
			{
				add_pos = left_bd + mid_pos;
				break;
			}
			else if (data >= value_pool[left_bd + mid_pos])
			{
				left_bd += mid_pos;
			}
			if (mid_pos < 1)
			{
				while (data >= value_pool[left_bd + mid_pos])
				{
					mid_pos++;
				}
				add_pos = left_bd + mid_pos - 1;
			}
		}
	}

	if (ers_pos == add_pos || ers_pos - 1 == add_pos)
	{
		value_pool[ers_pos] = data;
	}
	else if (ers_pos < add_pos)
	{
		for (int i = ers_pos; i < add_pos; i++)
		{
			value_pool[i] = value_pool[i + 1];
		}

		value_pool[add_pos] = data;
	}
	else
	{
		add_pos++;

		for (int i = ers_pos; i > add_pos; i--)
		{
			value_pool[i] = value_pool[i - 1];
		}

		value_pool[add_pos] = data;
	}

	time_pool[time_pos] = data;
	time_pos++;

	return *(value_pool + ((MEDWIDTH) >> 1));
}

void Wave_filter::get_median(int in_data, int &out_data)
{
	out_data = median(in_data);
}

void Wave_filter::get_median(int *in_data, int length, int *&out_data)
{
	for (int i = 0; i < length + (MEDWIDTH >> 1); i++)
	{
		if (i < MEDWIDTH >> 1)
		{
			*(out_data) = median(*(in_data + i));
		}
		else if (i >= length)
		{
			*(out_data + i - (MEDWIDTH >> 1)) = median(0);
		}
		else
		{
			*(out_data + i - (MEDWIDTH >> 1)) = median(*(in_data + i));
		}
	}
}


References:

[1] 蔡坤,陆尧胜. 基于中值滤波的心电基线校正方法的研究[J]. 医疗设备信息,2004,02:5-7.

[2] 刘文娜. 基于ECG信号进行心律失常及睡眠呼吸暂停综合症诊断分析[D].南京邮电大学,2015.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章