中值濾波的延時性問題

關於中值濾波算法的幾點注意事項:

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.

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