normalizedCorrelator.h

Go to the documentation of this file.
00001 
00015 #ifndef DLR_NUMERIC_NORMALIZEDCORRELATOR_H
00016 #define DLR_NUMERIC_NORMALIZEDCORRELATOR_H
00017 
00018 #include <cmath>
00019 #include <deque>
00020 #include <dlrNumeric/array2D.h>
00021 
00022 namespace dlr {
00023 
00024   namespace numeric {
00025 
00026 
00115     template <class Type>
00116     class NormalizedCorrelator
00117     {
00118     public:
00119 
00129       NormalizedCorrelator(bool trackInput = false);
00130 
00131 
00161       template <class IterType0, class IterType1>
00162       NormalizedCorrelator(IterType0 begin0,
00163                            IterType0 end0,
00164                            IterType1 begin1,
00165                            bool trackInput = false);
00166 
00167 
00172       ~NormalizedCorrelator();
00173 
00174 
00191       inline void
00192       addSample(Type sample0, Type sample1);
00193 
00194 
00210       inline void
00211       addSampleWithoutTracking(Type sample0, Type sample1);
00212 
00213 
00239       template <class IterType0, class IterType1>
00240       void
00241       addSamples(IterType0 begin0, IterType0 end0, IterType1 begin1);
00242 
00243 
00248       void
00249       clear();
00250 
00251 
00287       void
00288       enableInputTracking(bool trackInput = true);
00289       
00290 
00301       inline size_t
00302       getCount() const;
00303 
00304 
00313       Type
00314       getNormalizedCorrelation() const;
00315 
00316 
00325       inline bool
00326       isInputTrackingEnabled() const {return m_inputTracker0Ptr != 0;}
00327       
00328 
00341       void
00342       removeOldestSamples(size_t count);
00343 
00344 
00356       void
00357       removeSample(Type sample0, Type sample1);
00358 
00359 
00375       inline void
00376       removeSampleWithoutTracking(Type sample0, Type sample1);
00377 
00378 
00400       template <class IterType0, class IterType1>
00401       void
00402       removeSamples(IterType0 begin0, IterType0 end0, IterType1 begin1);
00403       
00404     private:
00405 
00406       size_t m_count;
00407       std::deque<Type>* m_inputTracker0Ptr;
00408       std::deque<Type>* m_inputTracker1Ptr;
00409       Type m_sum0;
00410       Type m_sum1;
00411       Type m_sum00;
00412       Type m_sum01;
00413       Type m_sum11;
00414 
00415     };
00416 
00417   } // namespace numeric
00418 
00419 } // namespace dlr
00420 
00421 
00422 /* ============ Definitions of inline & template functions ============ */
00423 
00424 namespace dlr {
00425 
00426   namespace numeric {
00427     
00428     // This constructor initializes the NormalizedCorrelator
00429     // instance, but doesn't add any samples.
00430     template <class Type>
00431     NormalizedCorrelator<Type>::
00432     NormalizedCorrelator(bool trackInput)
00433       : m_count(0),
00434         m_inputTracker0Ptr(0),
00435         m_inputTracker1Ptr(0),
00436         m_sum0(static_cast<Type>(0)),
00437         m_sum1(static_cast<Type>(0)),
00438         m_sum00(static_cast<Type>(0)),
00439         m_sum01(static_cast<Type>(0)),
00440         m_sum11(static_cast<Type>(0))
00441     {
00442       if(trackInput) {
00443         this->enableInputTracking();
00444       }
00445     }
00446     
00447 
00448     // This constructor initializes the NormalizedCorrelator
00449     // instance using sequences of samples from the two signals to
00450     // be correlated.
00451     template <class Type>
00452     template <class IterType0, class IterType1>
00453     NormalizedCorrelator<Type>::
00454     NormalizedCorrelator(IterType0 begin0, IterType0 end0, IterType1 begin1,
00455                          bool trackInput)
00456       : m_count(0),
00457         m_inputTracker0Ptr(0),
00458         m_inputTracker1Ptr(0),
00459         m_sum0(static_cast<Type>(0)),
00460         m_sum1(static_cast<Type>(0)),
00461         m_sum00(static_cast<Type>(0)),
00462         m_sum01(static_cast<Type>(0)),
00463         m_sum11(static_cast<Type>(0))
00464     {
00465       if(trackInput) {
00466         this->enableInputTracking();
00467       }
00468       this->addSamples(begin0, end0, begin1);
00469     }
00470     
00471 
00472     // The destructor destroys the NormalizedCorrelator instance and
00473     // cleans up any associated resources.
00474     template <class Type>
00475     NormalizedCorrelator<Type>::
00476     ~NormalizedCorrelator()
00477     {
00478       this->enableInputTracking(false);
00479     }
00480 
00481     
00482     // This member function adds a single pair of samples (one from
00483     // each of the two signals to be correlated) to the normalized
00484     // correlation calculation.
00485     template <class Type>
00486     void
00487     NormalizedCorrelator<Type>::
00488     addSample(Type sample0, Type sample1)
00489     {
00490       // Copy input, if required to do so.
00491       if(this->isInputTrackingEnabled()) {
00492         m_inputTracker0Ptr->push_back(sample0);
00493         m_inputTracker1Ptr->push_back(sample1);
00494       }
00495       this->addSampleWithoutTracking(sample0, sample1);
00496     }
00497 
00498     
00499     // This member function works identically to addSample(), with
00500     // the exception that input tracking is never updated.
00501     template <class Type>
00502     inline void
00503     NormalizedCorrelator<Type>::
00504     addSampleWithoutTracking(Type sample0, Type sample1)
00505     {
00506       m_sum0 += sample0;
00507       m_sum1 += sample1;
00508       m_sum00 += sample0 * sample0;
00509       m_sum01 += sample0 * sample1;
00510       m_sum11 += sample1 * sample1;
00511       ++m_count;
00512     }
00513 
00514 
00515     // This member function adds a sequence of pairs of samples
00516     // (each pair containing one sample from each of the two signals
00517     // to be correlated) to the normalized correlation calculation.
00518     template <class Type>
00519     template <class IterType0, class IterType1>
00520     void
00521     NormalizedCorrelator<Type>::
00522     addSamples(IterType0 begin0, IterType0 end0, IterType1 begin1)
00523     {
00524       // Copy input, if required to do so.
00525       if(this->isInputTrackingEnabled()) {
00526         IterType0 begin0Copy = begin0;
00527         IterType1 begin1Copy = begin1;
00528         while(begin0Copy != end0) {
00529           m_inputTracker0Ptr->push_back(*begin0Copy);
00530           m_inputTracker1Ptr->push_back(*begin1Copy);
00531           ++begin0Copy;
00532           ++begin1Copy;
00533         }
00534       }
00535 
00536       // Update statistics.
00537       while(begin0 != end0) {
00538         this->addSampleWithoutTracking(*begin0, *begin1);
00539         ++begin0;
00540         ++begin1;
00541       }
00542     }
00543       
00544 
00545     // This member function removes all samples from the
00546     // NormalizedCorrelator instance.
00547     template <class Type>
00548     void
00549     NormalizedCorrelator<Type>::
00550     clear()
00551     {
00552       if(this->isInputTrackingEnabled) {
00553         // Clear input tracking cache by re-enabling.  The
00554         // documentation above says this has undefined result, but
00555         // because we control the implementation, it's ok for us to
00556         // abuse it.
00557         this->enableInputTracking(true);
00558       }
00559       m_count = 0;
00560       m_sum0 = static_cast<Type>(0);
00561       m_sum1 = static_cast<Type>(0);
00562       m_sum00 = static_cast<Type>(0);
00563       m_sum01 = static_cast<Type>(0);
00564       m_sum11 = static_cast<Type>(0);
00565     }
00566 
00567 
00568     // This member function enables (or disables) internal
00569     // recordkeeping that allows samples to be automatically removed
00570     // from the normalized correlation calculation following the
00571     // order in which they were added.
00572     template <class Type>
00573     void
00574     NormalizedCorrelator<Type>::
00575     enableInputTracking(bool trackInput)
00576     {
00577       if(trackInput) {
00578         if(m_inputTracker0Ptr == 0) {
00579           m_inputTracker0Ptr = new std::deque<Type>;
00580         } else {
00581           m_inputTracker0Ptr->clear();
00582         }
00583         if(m_inputTracker1Ptr == 0) {
00584           m_inputTracker1Ptr = new std::deque<Type>;
00585         } else {
00586           m_inputTracker1Ptr->clear();
00587         }
00588       } else {
00589         if(m_inputTracker0Ptr != 0) {
00590           delete m_inputTracker0Ptr;
00591           m_inputTracker0Ptr = 0;
00592         }
00593         if(m_inputTracker1Ptr != 0) {
00594           delete m_inputTracker1Ptr;
00595           m_inputTracker1Ptr = 0;
00596         }
00597       }
00598     }
00599       
00600 
00601     // This member function returns the number of sample pairs
00602     // contributing to the normalized correlation.
00603     template <class Type>
00604     inline size_t
00605     NormalizedCorrelator<Type>::
00606     getCount() const
00607     {
00608       return m_count;
00609     }
00610 
00611       
00612     // This member function returns the normalized correlation of
00613     // all the currently added sample pairs.
00614     template <class Type>
00615     Type
00616     NormalizedCorrelator<Type>::
00617     getNormalizedCorrelation() const
00618     {
00619       if(m_count == 0) {
00620         return static_cast<Type>(1);
00621       }
00622       Type oneOverN = static_cast<Type>(1) / static_cast<Type>(m_count);
00623       Type numerator = m_sum01 - oneOverN * m_sum0 * m_sum1;
00624       Type denominator = std::sqrt((m_sum00 - oneOverN * m_sum0 * m_sum0)
00625                                    * (m_sum11 - oneOverN * m_sum1 * m_sum1));
00626       return numerator / denominator;
00627     }
00628 
00629     
00630     // If input tracking is enabled, this member function removes
00631     // pairs of samples from the normalized correlation calculation,
00632     // following the order in which they were added.
00633     template <class Type>
00634     void
00635     NormalizedCorrelator<Type>::
00636     removeOldestSamples(size_t count)
00637     {
00638       if(!(this->isInputTrackingEnabled())) {
00639         DLR_THROW(LogicException,
00640                   "NormalizedCorrelator::removeInputSamples()",
00641                   "Attempt to call removeOldestSamples() method of a "
00642                   "NormalizedCorrelator instance that does not have "
00643                   "input tracking enabled.");
00644       }
00645       if(count > (m_inputTracker0Ptr->size())) {
00646         DLR_THROW(ValueException,
00647                   "NormalizedCorrelator::removeInputSamples()",
00648                   "Trying to remove more samples than have been added.");
00649       }
00650       while(count != 0) {
00651         // Warning(xxx): if this call is changed to removeSample(),
00652         // then no tests fail, but calls to removeOldestSamples() will
00653         // throw.
00654         this->removeSampleWithoutTracking(m_inputTracker0Ptr->front(),
00655                                           m_inputTracker1Ptr->front());
00656         m_inputTracker0Ptr->pop_front();
00657         m_inputTracker1Ptr->pop_front();
00658         --count;
00659       }
00660     }
00661 
00662       
00663     // This member function removes a pair of sample values from the
00664     // normalized correlation calculation.
00665     template <class Type>
00666     void
00667     NormalizedCorrelator<Type>::
00668     removeSample(Type sample0, Type sample1)
00669     {
00670       if(this->isInputTrackingEnabled()) {
00671         DLR_THROW(NotImplementedException,
00672                   "NormalizedCorrelator::removeSample()",
00673                   "Currently, removeSample() can only be called if "
00674                   "input tracking is not enabled.");
00675       }
00676       this->removeSampleWithoutTracking(sample0, sample1);
00677     }
00678 
00679     
00680     // This member function works identically to removeSample(),
00681     // with the exception that input tracking is never updated.
00682     template <class Type>
00683     inline void
00684     NormalizedCorrelator<Type>::
00685     removeSampleWithoutTracking(Type sample0, Type sample1)
00686     {
00687       m_sum0 -= sample0;
00688       m_sum1 -= sample1;
00689       m_sum00 -= sample0 * sample0;
00690       m_sum01 -= sample0 * sample1;
00691       m_sum11 -= sample1 * sample1;
00692       --m_count;
00693     }        
00694 
00695 
00696     // This member function removes a sequence of pairs of samples
00697     // (each pair containing one sample from each of the two signals
00698     // to be correlated) from the normalized correlation
00699     // calculation.
00700     template <class Type>
00701     template <class IterType0, class IterType1>
00702     void
00703     NormalizedCorrelator<Type>::
00704     removeSamples(IterType0 begin0, IterType0 end0, IterType1 begin1)
00705     {
00706       if(this->isInputTrackingEnabled()) {
00707         DLR_THROW(NotImplementedException,
00708                   "NormalizedCorrelator::removeSamples()",
00709                   "Currently, removeSamples() can only be called if "
00710                   "input tracking is not enabled.");
00711       }
00712 
00713       while(begin0 != end0) {
00714         this->removeSampleWithoutTracking(*begin0, *begin1);
00715         ++begin0;
00716         ++begin1;
00717       }
00718     }
00719 
00720 
00721   } // namespace numeric
00722 
00723 } // namespace dlr
00724 
00725 #endif /* #ifndef DLR_NUMERIC_NORMALIZEDCORRELATOR_H */

Generated on Wed Nov 25 00:42:42 2009 for dlrUtilities Utility Library by  doxygen 1.5.8