Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "cmtkSimpleLevelset.h"
00032
00033 #include <Base/cmtkMathUtil.h>
00034 #include <Base/cmtkUniformVolume.h>
00035 #include <Base/cmtkUniformVolumePainter.h>
00036 #include <Base/cmtkUniformVolumeFilter.h>
00037 #include <Base/cmtkUnits.h>
00038
00039 #include <System/cmtkProgress.h>
00040
00041 #ifdef CMTK_BUILD_DEMO
00042 # include <IO/cmtkVolumeIO.h>
00043 #endif // #ifdef CMTK_BUILD_DEMO
00044
00045 void
00046 cmtk::SimpleLevelset
00047 ::InitializeCenteredSphere()
00048 {
00049 this->m_Levelset = this->m_Volume->CloneGrid();
00050 this->m_Levelset->CreateDataArray( TYPE_FLOAT );
00051 this->m_Levelset->GetData()->Fill( -1.0 );
00052
00053 FixedVector<3,int> center( this->m_Volume->GetDims() );
00054 center /= 2;
00055
00056 UniformVolumePainter painter( this->m_Levelset );
00057 painter.DrawSphere( center, this->m_ScaleInitialSphere * ((this->m_Levelset->GetDims()[0]+this->m_Levelset->GetDims()[1]+this->m_Levelset->GetDims()[2])/6), 1.0 );
00058 }
00059
00060 void
00061 cmtk::SimpleLevelset
00062 ::Evolve( const int numberOfIterations, const bool forceIterations, const bool verbose )
00063 {
00064 const size_t numberOfPixels = this->m_Volume->GetNumberOfPixels();
00065 size_t nInsideOld = 0, nInside = 1;
00066
00067 Progress::Begin( 0, numberOfIterations, 1, "Levelset Evolution" );
00068 for ( int it = 0; (it < numberOfIterations) && ((nInside!=nInsideOld) || forceIterations); ++it )
00069 {
00070 Progress::SetProgress( it );
00071
00072 nInsideOld = nInside;
00073 nInside = 0;
00074 Types::DataItem insideSum = 0, outsideSum = 0;
00075
00076 this->m_Levelset->SetData( UniformVolumeFilter( this->m_Levelset ).GetDataGaussFiltered( this->m_FilterSigma ) );
00077 #pragma omp parallel for reduction(+:nInside) reduction(+:insideSum) reduction(+:outsideSum)
00078 for ( size_t n = 0; n < numberOfPixels; ++n )
00079 {
00080 if ( this->m_Levelset->GetDataAt( n ) > 0 )
00081 {
00082 insideSum += this->m_Volume->GetDataAt( n );
00083 ++nInside;
00084 }
00085 else
00086 outsideSum += this->m_Volume->GetDataAt( n );
00087 }
00088
00089 const size_t nOutside = numberOfPixels - nInside;
00090 const Types::DataItem ratioInOut = 1.0 * nInside / nOutside;
00091
00092 const Types::DataItem mInside = insideSum / nInside;
00093 const Types::DataItem mOutside = outsideSum / nOutside;
00094
00095 if ( verbose )
00096 std::cerr << it << " IN: " << nInside << " " << mInside << " OUT: " << nOutside << " " << mOutside << "\r";
00097
00098 #pragma omp parallel for
00099 for ( size_t n = 0; n < numberOfPixels; ++n )
00100 {
00101 const Types::DataItem data = this->m_Volume->GetDataAt( n );
00102 const Types::DataItem zInside = fabs( mInside - data );
00103 const Types::DataItem zOutside = fabs( mOutside - data );
00104 Types::DataItem newLevel = this->m_Levelset->GetDataAt( n );
00105 if ( zInside>zOutside )
00106 {
00107 newLevel -= this->m_TimeDelta * ratioInOut;
00108 }
00109 else
00110 {
00111 newLevel += this->m_TimeDelta / ratioInOut;
00112 }
00113 this->m_Levelset->SetDataAt( std::min<Types::DataItem>( this->m_LevelsetThreshold, std::max<Types::DataItem>( -this->m_LevelsetThreshold, newLevel ) ), n );
00114 }
00115
00116 #ifdef CMTK_BUILD_DEMO
00117 UniformVolume::SmartConstPtr slice = this->m_Levelset->ExtractSlice( AXIS_Z, this->m_Levelset->m_Dims[2] / 2 );
00118
00119 char path[PATH_MAX];
00120 snprintf( path, PATH_MAX, "levelset-%03d.nii", it );
00121 VolumeIO::Write( *slice, path );
00122 #endif
00123 }
00124
00125 Progress::Done();
00126 }
00127
00128 cmtk::UniformVolume::SmartPtr&
00129 cmtk::SimpleLevelset
00130 ::GetLevelset( const bool binarize, const float threshold )
00131 {
00132 if ( binarize )
00133 {
00134 this->m_Levelset->GetData()->Binarize( threshold );
00135 this->m_Levelset->SetData( TypedArray::SmartPtr( this->m_Levelset->GetData()->Convert( TYPE_BYTE ) ) );
00136 }
00137
00138 return this->m_Levelset;
00139 }