cmtkInverseInterpolationVolumeReconstructionBase.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: 2398 $
00026 //
00027 //  $LastChangedDate: 2010-10-05 14:54:37 -0700 (Tue, 05 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include <algorithm>
00034 
00035 #include "cmtkInverseInterpolationVolumeReconstructionBase.h"
00036 
00037 #include <Base/cmtkHistogramBase.h>
00038 #include <System/cmtkProgress.h>
00039 
00040 namespace
00041 cmtk
00042 {
00043 
00044 InverseInterpolationVolumeReconstructionBase
00045 ::InverseInterpolationVolumeReconstructionBase( const UniformVolume* originalImage, const int interleaveFactor, const int interleaveAxis )
00046   : VolumeInjectionReconstruction( originalImage, interleaveFactor, interleaveAxis ),
00047     m_RegionalIntensityTruncation( true ),
00048     m_LowestMaxError( 1e12 ),
00049     m_FourthOrderError( false ),
00050     m_ConstraintWeightLNorm( 0.0 )
00051 {
00052 }
00053 
00054 InverseInterpolationVolumeReconstructionBase
00055 ::InverseInterpolationVolumeReconstructionBase( const UniformVolume* reconstructionGrid, std::vector<UniformVolume::SmartPtr>& images )
00056   : VolumeInjectionReconstruction( reconstructionGrid, images ),
00057     m_RegionalIntensityTruncation( true ),
00058     m_LowestMaxError( 1e12 ),
00059     m_FourthOrderError( false ),
00060     m_ConstraintWeightLNorm( 0.0 )
00061 {
00062 }
00063 
00064 double
00065 InverseInterpolationVolumeReconstructionBase
00066 ::ComputeApproximationError()
00067 {
00068   this->m_MeanSquaredError = 0;
00069   this->m_MaximumError = 0;
00070 
00071   this->m_DifferencePassImages.clear();
00072 
00073   double squaredError = 0;
00074   size_t totalNumberOfPixels = 0;
00075   for ( int pass = 0; pass < this->m_NumberOfPasses; ++pass )
00076     {
00077     UniformVolume::SmartPtr differencePassImage( this->m_InterpolatedPassImages[pass]->CloneGrid());
00078     differencePassImage->CreateDataArray( TYPE_FLOAT, true/*setToZero*/ );
00079 
00080     const int numberOfPixels = this->m_InterpolatedPassImages[pass]->GetNumberOfPixels();
00081     
00082     for ( int idx = 0; idx < numberOfPixels; ++idx )
00083       {
00084       Types::DataItem originalData, interpolatedData;    
00085       this->m_OriginalPassImages[pass]->GetDataAt( originalData, idx );
00086 
00087       if ( this->m_InterpolatedPassImages[pass]->GetDataAt( interpolatedData, idx ) )
00088         {
00089         const double difference = interpolatedData - originalData;
00090         differencePassImage->SetDataAt( difference, idx );
00091         if ( this->m_FourthOrderError )
00092           squaredError += difference*difference*difference*difference;
00093         else
00094           squaredError += difference*difference;
00095 
00096         this->m_MaximumError = std::max<double>( fabs(difference), this->m_MaximumError );
00097         ++totalNumberOfPixels;
00098         }
00099       else
00100         {
00101         differencePassImage->GetData()->SetPaddingAt( idx );
00102         }
00103       }
00104     
00105     this->m_DifferencePassImages.push_back( differencePassImage );
00106     }
00107   return (this->m_MeanSquaredError = squaredError / totalNumberOfPixels);
00108 }
00109 
00110 void
00111 InverseInterpolationVolumeReconstructionBase
00112 ::Optimize( const int numberOfIterations )
00113 {
00114   const int numberOfPixels = this->m_CorrectedImage->GetNumberOfPixels();
00115   ap::real_1d_array x;
00116   x.setbounds( 1, numberOfPixels );
00117   for ( int i = 1; i <= numberOfPixels; ++i )
00118     {
00119     x(i) = this->m_CorrectedImage->GetDataAt( i-1 );
00120     }
00121 
00122   const int nbdAll = this->m_RegionalIntensityTruncation ? 2 : 0;
00123   ap::integer_1d_array nbd;
00124   nbd.setbounds( 1, numberOfPixels );
00125   for ( int i = 1; i <= numberOfPixels; ++i )
00126     {
00127     nbd(i) = nbdAll;
00128     if ( this->m_NeighorhoodMinPixelValues(i) > this->m_NeighorhoodMaxPixelValues(i) )
00129       {
00130       this->m_NeighorhoodMinPixelValues(i) = this->m_OriginalImageRange.m_LowerBound;
00131       this->m_NeighorhoodMaxPixelValues(i) = this->m_OriginalImageRange.m_UpperBound;
00132       }
00133     }
00134 
00135   Progress::Begin( 0, numberOfIterations, 1, "Inverse Interpolation" );
00136   
00137   int info;
00138   ap::lbfgsbminimize( this->m_FunctionAndGradient, numberOfPixels, 5, x, 1e-10 /*epsg*/, 1e-10 /*epsf*/, 1e-10 /*epsx*/, numberOfIterations, 
00139                       nbd, this->m_NeighorhoodMinPixelValues, this->m_NeighorhoodMaxPixelValues, info );
00140 
00141   Progress::Done();
00142   
00143   if ( info < 0 )
00144     StdErr << "ERROR: lbfgsbminimize returned status code " << info << "\n";
00145   else
00146     for ( int i = 1; i <= numberOfPixels; ++i )
00147       this->m_CorrectedImage->SetDataAt( x(i), i-1 );
00148 }
00149 
00150 } // namespace cmtk
00151 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines