00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef FILTERS_MEDIAN_H
00031 #define FILTERS_MEDIAN_H
00032
00033 #include <stdint.h>
00034 #include <sstream>
00035 #include <cstdio>
00036
00037 #include <boost/scoped_ptr.hpp>
00038
00039 #include "filters/filter_base.h"
00040
00041 #include "filters/realtime_circular_buffer.h"
00042
00043
00044
00045
00046
00047
00048
00049 #define ELEM_SWAP(a,b) { register elem_type t=(a);(a)=(b);(b)=t; }
00050
00051 namespace filters
00052 {
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 template <typename elem_type>
00067 elem_type kth_smallest(elem_type a[], int n, int k)
00068 {
00069 register int i,j,l,m ;
00070 register elem_type x ;
00071 l=0 ; m=n-1 ;
00072 while (l<m) {
00073 x=a[k] ;
00074 i=l ;
00075 j=m ;
00076 do {
00077 while (a[i]<x) i++ ;
00078 while (x<a[j]) j-- ;
00079 if (i<=j) {
00080 ELEM_SWAP(a[i],a[j]) ;
00081 i++ ; j-- ;
00082 }
00083 } while (i<=j) ;
00084 if (j<k) l=i ;
00085 if (k<i) m=j ;
00086 }
00087 return a[k] ;
00088 }
00089 #define median(a,n) kth_smallest(a,n,(((n)&1)?((n)/2):(((n)/2)-1)))
00090 #undef ELEM_SWAP
00091
00092
00096 template <typename T>
00097 class MedianFilter: public filters::FilterBase <T>
00098 {
00099 public:
00101 MedianFilter();
00102
00105 ~MedianFilter();
00106
00107 virtual bool configure();
00108
00113 virtual bool update(const T& data_in, T& data_out);
00114
00115 protected:
00116 std::vector<T> temp_storage_;
00117 boost::scoped_ptr<RealtimeCircularBuffer<T > > data_storage_;
00118
00119 T temp;
00120
00121
00122 uint32_t number_of_observations_;
00123
00124 };
00125
00126 template <typename T>
00127 MedianFilter<T>::MedianFilter():
00128 number_of_observations_(0)
00129 {
00130
00131 };
00132
00133 template <typename T>
00134 MedianFilter<T>::~MedianFilter()
00135 {
00136 };
00137
00138
00139 template <typename T>
00140 bool MedianFilter<T>::configure()
00141 {
00142 int no_obs = -1;
00143 if (!FilterBase<T>::getParam(std::string("number_of_observations"), no_obs))
00144 {
00145 fprintf(stderr, "Error: MedianFilter was not given params.\n");
00146 return false;
00147 }
00148 number_of_observations_ = no_obs;
00149
00150 data_storage_.reset( new RealtimeCircularBuffer<T >(number_of_observations_, temp));
00151 temp_storage_.resize(number_of_observations_);
00152
00153 return true;
00154 };
00155
00156 template <typename T>
00157 bool MedianFilter<T>::update(const T& data_in, T& data_out)
00158 {
00159 if (!FilterBase<T>::configured_)
00160 return false;
00161
00162 data_storage_->push_back(data_in);
00163
00164
00165 unsigned int length = data_storage_->size();
00166
00167
00168 for (uint32_t row = 0; row < length; row ++)
00169 {
00170 temp_storage_[row] = (*data_storage_)[row];
00171 }
00172 data_out = median(&temp_storage_[0], length);
00173
00174
00175 return true;
00176 };
00180 template <typename T>
00181 class MultiChannelMedianFilter: public filters::MultiChannelFilterBase <T>
00182 {
00183 public:
00185 MultiChannelMedianFilter();
00186
00189 ~MultiChannelMedianFilter();
00190
00191 virtual bool configure();
00192
00197 virtual bool update(const std::vector<T>& data_in, std::vector<T>& data_out);
00198
00199 protected:
00200 std::vector<T> temp_storage_;
00201 boost::scoped_ptr<RealtimeCircularBuffer<std::vector<T> > > data_storage_;
00202
00203 std::vector<T> temp;
00204
00205
00206 uint32_t number_of_observations_;
00207
00208 };
00209
00210 template <typename T>
00211 MultiChannelMedianFilter<T>::MultiChannelMedianFilter():
00212 number_of_observations_(0)
00213 {
00214
00215 };
00216
00217 template <typename T>
00218 MultiChannelMedianFilter<T>::~MultiChannelMedianFilter()
00219 {
00220 };
00221
00222
00223 template <typename T>
00224 bool MultiChannelMedianFilter<T>::configure()
00225 {
00226 int no_obs = -1;
00227 if (!FilterBase<T>::getParam("number_of_observations", no_obs))
00228 {
00229 fprintf(stderr, "Error: MultiChannelMedianFilter was not given params.\n");
00230 return false;
00231 }
00232 number_of_observations_ = no_obs;
00233
00234 temp.resize(this->number_of_channels_);
00235 data_storage_.reset( new RealtimeCircularBuffer<std::vector<T> >(number_of_observations_, temp));
00236 temp_storage_.resize(number_of_observations_);
00237
00238 return true;
00239 };
00240
00241 template <typename T>
00242 bool MultiChannelMedianFilter<T>::update(const std::vector<T>& data_in, std::vector<T>& data_out)
00243 {
00244
00245 if (data_in.size() != this->number_of_channels_ || data_out.size() != this->number_of_channels_)
00246 return false;
00247 if (!FilterBase<T>::configured_)
00248 return false;
00249
00250 data_storage_->push_back(data_in);
00251
00252
00253 unsigned int length = data_storage_->size();
00254
00255
00256 for (uint32_t i = 0; i < this->number_of_channels_; i++)
00257 {
00258 for (uint32_t row = 0; row < length; row ++)
00259 {
00260 temp_storage_[row] = (*data_storage_)[row][i];
00261 }
00262 data_out[i] = median(&temp_storage_[0], length);
00263 }
00264
00265 return true;
00266 };
00267
00268
00269 }
00270 #endif// FILTERS_MEDIAN_H