cmtkEntropyMinimizationIntensityCorrectionFunctionalBase.cxx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2009 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2010 SRI International
00006 //
00007 //  This file is part of the Computational Morphometry Toolkit.
00008 //
00009 //  http://www.nitrc.org/projects/cmtk/
00010 //
00011 //  The Computational Morphometry Toolkit is free software: you can
00012 //  redistribute it and/or modify it under the terms of the GNU General Public
00013 //  License as published by the Free Software Foundation, either version 3 of
00014 //  the License, or (at your option) any later version.
00015 //
00016 //  The Computational Morphometry Toolkit is distributed in the hope that it
00017 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00018 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //  GNU General Public License for more details.
00020 //
00021 //  You should have received a copy of the GNU General Public License along
00022 //  with the Computational Morphometry Toolkit.  If not, see
00023 //  <http://www.gnu.org/licenses/>.
00024 //
00025 //  $Revision: 2438 $
00026 //
00027 //  $LastChangedDate: 2010-10-11 15:36:16 -0700 (Mon, 11 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include <Segmentation/cmtkEntropyMinimizationIntensityCorrectionFunctionalBase.h>
00034 
00035 #include <System/cmtkThreadPool.h>
00036 #include <System/cmtkException.h>
00037 
00038 #include <algorithm>
00039 
00040 #ifdef CMTK_BUILD_DEMO
00041 #  include <IO/cmtkVolumeIO.h>
00042 #endif // #ifdef CMTK_BUILD_DEMO
00043 
00044 namespace cmtk
00045 {
00046 
00049 void
00050 EntropyMinimizationIntensityCorrectionFunctionalBase
00051 ::SetInputImage( UniformVolume::SmartConstPtr& inputImage )
00052 {
00053   this->m_InputImage = inputImage;
00054   this->m_NumberOfPixels = this->m_InputImage->GetNumberOfPixels();
00055   
00056   const Types::DataItemRange range = this->m_InputImage->GetData()->GetRange();
00057   this->m_InputImageRange = range.Width();
00058   
00059   if ( this->m_UseLogIntensities )
00060     {
00061     this->m_EntropyHistogram = HistogramType::SmartPtr( new LogHistogramType( this->m_NumberOfHistogramBins ) );
00062     }
00063   else
00064     {
00065     this->m_EntropyHistogram = HistogramType::SmartPtr( new HistogramType( this->m_NumberOfHistogramBins ) );
00066     }
00067   // extend value range to accomodate corrected intensities without overflows
00068   this->m_EntropyHistogram->SetRange( Types::DataItemRange( range.m_LowerBound - this->m_InputImageRange, range.m_UpperBound + this->m_InputImageRange ) );
00069   
00070   if ( this->m_ForegroundMask.size() )
00071     this->UpdateCorrectionFactors();
00072   
00073   this->m_BiasFieldAdd = FloatArray::Create( this->m_NumberOfPixels );
00074   this->m_BiasFieldAdd->Fill( 0.0 );
00075   this->m_BiasFieldMul = FloatArray::Create( this->m_NumberOfPixels );
00076   this->m_BiasFieldAdd->Fill( 1.0 );
00077 
00078   this->m_OutputImage = UniformVolume::SmartPtr( this->m_InputImage->CloneGrid() );
00079   this->m_OutputImage->CreateDataArray( TYPE_FLOAT );
00080 }
00081 
00082 void
00083 EntropyMinimizationIntensityCorrectionFunctionalBase
00084 ::SetForegroundMask( const UniformVolume& foregroundMask )
00085 {
00086   const size_t maskPixels = foregroundMask.GetNumberOfPixels();
00087 
00088   if ( maskPixels != this->m_NumberOfPixels )
00089     {
00090     throw Exception( "Number of mask pixels does not match number of input image pixels." );
00091     }
00092 
00093   this->m_ForegroundMask.resize( maskPixels );
00094   if ( (this->m_SamplingDensity > 0) && (this->m_SamplingDensity < 1) )
00095     {
00096     for ( size_t i = 0; i < maskPixels; ++i )
00097       {
00098       this->m_ForegroundMask[i] = (foregroundMask.GetDataAt( i ) > 0) && (MathUtil::UniformRandom() <= this->m_SamplingDensity);
00099       }
00100     }
00101   else
00102     {
00103     for ( size_t i = 0; i < maskPixels; ++i )
00104       {
00105       this->m_ForegroundMask[i] = (foregroundMask.GetDataAt( i ) > 0);
00106       }
00107     }
00108   
00109   if ( this->m_InputImage )
00110     this->UpdateCorrectionFactors();
00111 }
00112 
00113 UniformVolume::SmartPtr& 
00114 EntropyMinimizationIntensityCorrectionFunctionalBase
00115 ::GetOutputImage( CoordinateVector& v, const bool foregroundOnly )
00116 {
00117   this->SetParamVector( v );
00118   this->UpdateBiasFields( foregroundOnly );
00119   this->UpdateOutputImage( foregroundOnly );
00120   return this->m_OutputImage;
00121 }
00122 
00123 EntropyMinimizationIntensityCorrectionFunctionalBase::ReturnType
00124 EntropyMinimizationIntensityCorrectionFunctionalBase
00125 ::EvaluateAt( CoordinateVector& v )
00126 {
00127   this->SetParamVector( v );
00128   this->UpdateBiasFields();
00129   this->UpdateOutputImage();
00130   return this->Evaluate();
00131 }
00132 
00133 #ifdef CMTK_BUILD_DEMO
00134 void
00135 EntropyMinimizationIntensityCorrectionFunctionalBase
00136 ::SnapshotAt( CoordinateVector& v )
00137 {
00138   this->SetParamVector( v );
00139   this->UpdateBiasFields();
00140 
00141   static int it = 0;
00142   this->UpdateOutputImage( false /*foregroundOnly*/ );
00143   UniformVolume::SmartConstPtr slice = this->m_OutputImage->ExtractSlice( AXIS_Z, this->m_OutputImage->m_Dims[2] / 2 );
00144   
00145   char path[PATH_MAX];
00146   snprintf( path, PATH_MAX, "mrbias-%03d.nii", it++ );
00147   VolumeIO::Write( *slice, path );
00148 }
00149 #endif
00150   
00151 
00152 void
00153 EntropyMinimizationIntensityCorrectionFunctionalBase
00154 ::UpdateOutputImage( const bool foregroundOnly )
00155 {
00156   ThreadPool& threadPool = ThreadPool::GetGlobalThreadPool();
00157   const size_t numberOfTasks = 4 * threadPool.GetNumberOfThreads() - 3;
00158   
00159   std::vector<UpdateOutputImageThreadParameters> taskParameters( numberOfTasks );
00160   for ( size_t task = 0; task < numberOfTasks; ++task )
00161     {
00162     taskParameters[task].thisObject = this;
00163     taskParameters[task].m_ForegroundOnly = foregroundOnly;
00164     }
00165   threadPool.Run( UpdateOutputImageThreadFunc, taskParameters );
00166 }
00167  
00168 void
00169 EntropyMinimizationIntensityCorrectionFunctionalBase
00170 ::UpdateOutputImageThreadFunc( void *args, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t )
00171 {
00172   UpdateOutputImageThreadParameters* threadParameters = static_cast<UpdateOutputImageThreadParameters*>( args );
00173   
00174   Self* This = threadParameters->thisObject;
00175   const Self* ThisConst = threadParameters->thisObject;
00176   
00177   const UniformVolume* inputImage = ThisConst->m_InputImage;
00178   TypedArray::SmartPtr outputData = This->m_OutputImage->GetData();
00179   const size_t numberOfPixels = inputImage->GetNumberOfPixels();
00180 
00181   const float* biasFieldPtrAdd = ThisConst->m_BiasFieldAdd->GetDataPtrTemplate();
00182   const float* biasFieldPtrMul = ThisConst->m_BiasFieldMul->GetDataPtrTemplate();
00183 
00184   Types::DataItem value;
00185   for ( size_t ofs = taskIdx; ofs < numberOfPixels; ofs += taskCnt )
00186     {
00187     if ( !threadParameters->m_ForegroundOnly || ThisConst->m_ForegroundMask[ofs] )
00188       {
00189       if ( inputImage->GetDataAt( value, ofs ) )
00190         {
00191         outputData->Set( value * biasFieldPtrMul[ofs] + biasFieldPtrAdd[ofs], ofs );
00192         }
00193       else
00194         {
00195         outputData->SetPaddingAt( ofs );
00196         }
00197       }     
00198     else
00199       {
00200       outputData->SetPaddingAt( ofs );
00201       }
00202     }
00203 }
00204 
00205 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines