cmtkTypedArrayNoiseEstimatorMaximumLikelihood.cxx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 2008-2011 SRI International
00004 //
00005 //  This file is part of the Computational Morphometry Toolkit.
00006 //
00007 //  http://www.nitrc.org/projects/cmtk/
00008 //
00009 //  The Computational Morphometry Toolkit is free software: you can
00010 //  redistribute it and/or modify it under the terms of the GNU General Public
00011 //  License as published by the Free Software Foundation, either version 3 of
00012 //  the License, or (at your option) any later version.
00013 //
00014 //  The Computational Morphometry Toolkit is distributed in the hope that it
00015 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00016 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 //  GNU General Public License for more details.
00018 //
00019 //  You should have received a copy of the GNU General Public License along
00020 //  with the Computational Morphometry Toolkit.  If not, see
00021 //  <http://www.gnu.org/licenses/>.
00022 //
00023 //  $Revision: 2752 $
00024 //
00025 //  $LastChangedDate: 2011-01-17 11:33:31 -0800 (Mon, 17 Jan 2011) $
00026 //
00027 //  $LastChangedBy: torstenrohlfing $
00028 //
00029 */
00030 
00031 #include "cmtkTypedArrayNoiseEstimatorMaximumLikelihood.h"
00032 
00033 namespace
00034 cmtk
00035 {
00036 
00037 /*   Maximum-likelihood estimation of the noise variance.
00038  */
00039 TypedArrayNoiseEstimatorMaximumLikelihood::TypedArrayNoiseEstimatorMaximumLikelihood
00040 ( const TypedArray* data, const size_t histogramBins ) 
00041 {
00042 //  Histogram<unsigned int>::SmartPtr histogram( data->GetHistogram( histogramBins ) );
00043   UNUSED(histogramBins);
00044 
00045   size_t overriddenHistogramBins = 255;
00046   Histogram<unsigned int>::SmartPtr histogram( data->GetHistogram( overriddenHistogramBins ) );
00047 
00048   // Find first maximum
00049   size_t idx = 0;
00050   while ( (idx < (overriddenHistogramBins-1)) && ( (*histogram)[idx] <= (*histogram)[idx+1] ) )
00051     {
00052     ++idx;
00053     }
00054   // Now find following minimum
00055   while ( (idx < (overriddenHistogramBins-1)) && ( (*histogram)[idx] > (*histogram)[idx+1] ) )
00056     {
00057     ++idx;
00058     }
00059   
00060    /*  Part of estimating the noise variance by this method is
00061     *  deciding how many histogram bins to use in the computations
00062     *  below (i.e. determining the value of K in Sijbers).  
00063     *  K is called numBinsToUse here, and we'll initialize it
00064     *  to the bin with the minimum following the first maximum.
00065     *  It will then be refined using the EstimateNumBinsToUse method.
00066     */
00067   int numBinsToUse = idx;
00068 
00069   float sigmaUpperBound = 100;
00070   
00071   // Step size in search for sigma
00072   double stepSize = 0.1;
00073 
00074   // Threshold for how close two iterations of the below should
00075   // be before deciding we've found a good sigma
00076   double sigmaThresh = 0.1; 
00077 
00078   // maxLikelySigma corresponds to sigma-hat in the Sijbers paper
00079   double maxLikelySigma = 23.0;
00080   double prevMaxLikelySigma = 0.0;
00081 
00082   while ( sqrt( pow( maxLikelySigma - prevMaxLikelySigma, 2 ) ) > sigmaThresh )
00083     {
00084     
00085     std::cout << "K: " << numBinsToUse << "\tprevMaxLikelySigma: " << prevMaxLikelySigma << "\tmaxLikelySigma: " << maxLikelySigma << std::endl;
00086     prevMaxLikelySigma = maxLikelySigma;
00087 
00088     double curSigmaMinimizer;
00089     double minSigmaMinimizer = std::numeric_limits<double>::max(); 
00090 
00091     const double bin0Squared = pow( histogram->BinToValue( 0 ), 2 );
00092     const double binKSquared = pow( histogram->BinToValue(numBinsToUse-1), 2 );
00093 
00094      /*  This for loop iterates through values of sigma, assigning
00095       *  the one that produces the least value of minSigmaMinimizer
00096       *  to maxLikelySigma.
00097       */
00098     for ( double sigma = 1; sigma < sigmaUpperBound; sigma += stepSize )
00099       {
00100       const double twoSigmaSquared = 2 * pow( sigma, 2 );
00101       double sumForSearch = 0.0; 
00102 //      double productForSearch = 1.0; 
00103   
00104       for ( int j = 1; j <= numBinsToUse; j++ )
00105         {
00106         const double curAddend = (*histogram)[j] 
00107           * ( exp( -1 * ( pow( (double)(histogram->BinToValue(j-1)), 2 ) / twoSigmaSquared ) )
00108               - exp( -1 * ( pow( (double)(histogram->BinToValue( j )), 2 ) / twoSigmaSquared ) ) );  
00109         sumForSearch += curAddend;
00110         }
00111       
00112       curSigmaMinimizer = /*binsSum 
00113                         * */( exp( -bin0Squared / twoSigmaSquared ) - exp( -binKSquared / twoSigmaSquared ) ) - sumForSearch;
00114       
00115       if ( curSigmaMinimizer < minSigmaMinimizer ) 
00116         {
00117         minSigmaMinimizer = curSigmaMinimizer;
00118         maxLikelySigma = sigma;
00119         }
00120       }
00121     numBinsToUse = static_cast<int>( Superclass::EstimateNumBinsToUse( data, histogram, maxLikelySigma ) );
00122     }
00123     
00124     std::cout << maxLikelySigma << std::endl;
00125 
00126   //return static_cast<Types::DataItem>( maxLikelySigma );
00127     this->m_NoiseLevelSigma = static_cast<Types::DataItem>( 0 );
00128 }
00129 
00130 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines