|
|
View previous topic :: View next topic |
Author |
Message |
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
Question for PCM programmer on modifying median filter |
Posted: Fri Mar 16, 2012 6:41 am |
|
|
I have a question for PCM programmer, but anyone else that has the answer is just as welcome. I trying to adapt the original "median filter" which I think PCM programmer posted a few years back. I am trying to adapt this filter so it removes occasional spikes from data on five individual data channels, the data comes from a 22bit converter so I have to use int32 for all data handling. Because I gather, process and send out data sequentially, I think the best method would be to duplicate the main filter function five times with a different function name in each case. So I have tried this and I have gotten very weird results, mainly because I screwed-up a few things like
" memset(sorted_data, 0, MEDIAN_FILTER_WIDTH * 2);" and
"memcpy(sorted_data, input_buffer, num_elements * 2);" which I believe only works on bytes, so how would you modify these two functions to handle int32 data? Also I have been sharing the following function with all five median filter functions;
void Insertion_Sort_32(unsigned int32 *data, char array_size);
Should the above function be also discrete to each filter function?
Here is a copy of the modified median filter shown only for a single section
// DEFINES
#define MEDIAN_FILTER_WIDTH 5
//------------------------------------------
// FUNCTION PROTOTYPES
unsigned int32 median_filter(unsigned int32 latest_element);
void Insertion_Sort_32(unsigned int32 *data, char array_size);
//========================================================
// filters.c
//-------------------
// median_filter:
// This function sorts an array of longs so it's in
// ascending order. It then returns the middle element.
// ie., If the array has 7 elements (0-6), it returns
// the element at index 3. The user should ensure that
// the array has an odd number of elements.
// This function stores data from prior calls in a static
// buffer.
// The output of this function will always be N/2 +1
// elements behind the input data, where N is the filter width.
unsigned int32 median_filter(unsigned int32 latest_element)
{
static unsigned int32 input_buffer[MEDIAN_FILTER_WIDTH];
static char inbuf_index = 0;
static char num_elements = 0;
static unsigned int32 sorted_data[MEDIAN_FILTER_WIDTH];
unsigned int32 median;
// Insert incoming data element into circular input buffer.
input_buffer[inbuf_index] = latest_element;
inbuf_index++;
if(inbuf_index >= MEDIAN_FILTER_WIDTH) // If index went past buffer end
inbuf_index = 0; // then reset it to start of buffer
if(num_elements < MEDIAN_FILTER_WIDTH)
num_elements++;
// THIS LINE MAY NOT BE NEEDED IF SORTED DATA IS STATIC.
// memset(sorted_data, 0, MEDIAN_FILTER_WIDTH * 2);
// Copy input data buffer to the (to be) sorted data array.
memcpy(sorted_data, input_buffer, num_elements * 2); // memcpy works on bytes
// Then sort the data.
Insertion_Sort_32(sorted_data, MEDIAN_FILTER_WIDTH);
// During the first few calls to this function, we have fewer
// elements in the sorted data array than the filter width.
// So to compensate for that, we pick the median from the number
// of elements that are available. ie, if we have 3 elements,
// we pick the middle one of those as the median.
// Also, because the sort function sorts the data from low to high,
// we have to calculate the index from the high end of the array.
median = sorted_data[MEDIAN_FILTER_WIDTH - 1 - num_elements/2];
return(median);
}
//-------------------------------------------------------------
//-----------------------------------------------------
void Insertion_Sort_32(unsigned int32 *data, char array_size)
{
char i, j;
unsigned int32 index;
for(i = 1; i < array_size; i++)
{
index = data[i];
j = i;
while ((j > 0) && (data[j-1] > index))
{
data[j] = data[j-1];
j = j - 1;
}
data[j] = index;
}
} |
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
Posted: Fri Mar 16, 2012 6:54 am |
|
|
I guess for the following functions which I never clearly understood, I would have to change them as follows to work with an int32?
memset(sorted_data, 0, MEDIAN_FILTER_WIDTH * 4);
and
memcpy(sorted_data, input_buffer, num_elements * 4);
But I am still not sure that you can share the Insertion_sort() function? |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Fri Mar 16, 2012 7:46 am |
|
|
Hi,
It's bad forum etiquitte to address a question to a specific member. You should also learn to use the "code" button when you post your code.
John |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Fri Mar 16, 2012 8:49 am |
|
|
Several comments:
First, in general, having any code duplicated more than perhaps twice, is a sign that you are not really 'thinking'.
Make a single function, and hand it the _address_ of a structure, containing the memory block and temporary values. The same code then does for everything.
Then, int32, is 4 bytes. memset, and memcpy, work in bytes. The original code used int16's, which are 2 bytes, hence the '*2'. You need *4.
As a further comment though, if you are averaging the data, and just want to reject extreme values, consider an 'Olympic' average algorithm. As an example, just sum ten values, and while you are summing then, record the largest and smallest value you see. Then subtract these two values from the sum, and divide by eight. Result an average of the eight 'middle' values in the group of ten. Simpler, quicker, and uses a lot less space, while working to reject the extreme values, which sounds as if this is exactly what is needed. This is the basis of the 'trimmean' function in Excel.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|