Marsyas
0.6.0-alpha
|
00001 #include "MedianFilter.h" 00002 #include <map> 00003 #include <algorithm> 00004 00005 using std::ostringstream; 00006 using std::map; 00007 using std::multimap; 00008 using std::less; 00009 using std::pair; 00010 using std::min; 00011 using std::max; 00012 00013 using namespace Marsyas; 00014 00015 MedianFilter::MedianFilter(mrs_string inName) 00016 :MarSystem("MedianFilter",inName) 00017 { 00018 addControls(); 00019 } 00020 00021 MedianFilter::MedianFilter(const MedianFilter& inToCopy) 00022 :MarSystem(inToCopy) 00023 { 00024 ctrl_WindowSize_ = getctrl("mrs_natural/WindowSize"); 00025 WindowSize_ = inToCopy.WindowSize_; 00026 } 00027 00028 MedianFilter::~MedianFilter() {} 00029 00030 MarSystem* MedianFilter::clone() const 00031 { 00032 return new MedianFilter(*this); 00033 } 00034 00035 void MedianFilter::addControls() 00036 { 00037 addctrl("mrs_natural/WindowSize",10,ctrl_WindowSize_); 00038 ctrl_WindowSize_->setState(true); 00039 WindowSize_ = 10; 00040 } 00041 00042 void MedianFilter::myUpdate(MarControlPtr inSender) 00043 { 00044 WindowSize_ = ctrl_WindowSize_->to<mrs_natural>(); 00045 MarSystem::myUpdate(inSender); 00046 } 00047 00048 void MedianFilter::myProcess(realvec& inVec, realvec& outVec) 00049 { 00050 // Each element in the input vector is replaced by the median of 00051 // the elements that fall in a window surrounding the element, defined as: 00052 // element index + [0,1.. N-1] - floor(N/2) with N, the size of the window. 00053 00054 // Define moving window: once inserted, 00055 // the elements in the moving window are automatically sorted 00056 mrs_natural N = WindowSize_; 00057 multimap<mrs_real,mrs_natural,less<mrs_real> > theWindow; 00058 typedef multimap<mrs_real,mrs_natural,less<mrs_real> >::iterator iter; 00059 typedef pair<mrs_real,mrs_natural> element; 00060 00061 // M = floor(N/2) 00062 mrs_natural M = (mrs_natural)floor((mrs_real)N/2.); 00063 00064 // Initialize the moving window 00065 // For i=0, the window = [v(0), v(0),.. v(0),v(1),.. v(N-M)] 00066 for (int p=-M; p<=0; p++) 00067 theWindow.insert(element(inVec(0),p)); 00068 for (int p=1; p<=N-M-1; p++) 00069 theWindow.insert(element(inVec(p),p)); 00070 00071 mrs_natural I = inVec.getSize(); 00072 for (int i=0; i<I; ++i) 00073 { 00074 // Define to-be-inserted element 00075 element theNewOne(inVec(min(i+N-M,I-1)),i+N-M); 00076 00077 // Search for median, insert and delete position 00078 int theOffset = -M; 00079 00080 iter theMedian, theToDelete, theToInsert = theWindow.begin(); 00081 for (iter theIter=theWindow.begin(); theIter!=theWindow.end(); theIter++) 00082 { 00083 if (theOffset == 0) 00084 theMedian = theIter; 00085 if (theIter->second == i-M) 00086 // Index i-M = first inserted element (oldest) 00087 theToDelete = theIter; 00088 if (theNewOne.first > theIter->first) 00089 { 00090 // Update theToInsert as long as theIter 00091 // is smaller than the to-be-inserted element 00092 theToInsert = theIter; 00093 theToInsert++; 00094 } 00095 theOffset++; 00096 } 00097 00098 if (theToInsert == theToDelete) 00099 theToInsert++; 00100 00101 outVec(i) = theMedian->first; 00102 theWindow.erase(theToDelete); 00103 theWindow.insert(theToInsert,theNewOne); 00104 } 00105 }