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 
00032 
00033 #include "cmtkImagePairRegistration.h"
00034 
00035 #include <System/cmtkCommandLine.h>
00036 #include <Base/cmtkTypedArrayFunctionHistogramEqualization.h>
00037 #include <Base/cmtkDataGridFilter.h>
00038 
00039 namespace
00040 cmtk
00041 {
00042 
00043 ImagePairRegistration::ImagePreprocessor::ImagePreprocessor( const char* name, const char* key )
00044   : m_DataClassString( NULL ),
00045     m_DataClass( DATACLASS_GREY ),
00046     m_PaddingFlag( false ),
00047     m_PaddingValue( 0 ),
00048     m_LowerThresholdActive( false ),
00049     m_LowerThresholdValue( -CMTK_ITEM_MAX ),
00050     m_UpperThresholdActive( false ),
00051     m_UpperThresholdValue( CMTK_ITEM_MAX ),
00052     m_UsePruneHistogramBins( false ),
00053     m_PruneHistogramBins( 0 ),
00054     m_HistogramEqualization( false ),
00055     m_MedianFilterRadius( 0 ),
00056     m_SobelFilter( false ),
00057     m_CropIndex( NULL ),
00058     m_CropWorld( NULL ),
00059     m_AutoCropFlag( false ),
00060     m_AutoCropLevel( 0 ),
00061     m_Name( name ),
00062     m_Key( key )
00063 {
00064 }
00065 
00066 void 
00067 ImagePairRegistration::ImagePreprocessor::AttachToCommandLine
00068 ( CommandLine& cl )
00069 {
00070   char buffer[64];
00071   cl.BeginGroup( this->m_Name, strcat( strcpy( buffer, this->m_Name ), " Image Preprocessing" ) )->SetProperties( CommandLine::PROPS_NOXML );
00072   
00073   cl.AddOption( CommandLine::Key( strcat( strcpy( buffer, "class-" ), this->m_Key ) ), &this->m_DataClassString, "Data class: grey (default) or label" );
00074   cl.AddOption( CommandLine::Key( strcat( strcpy( buffer, "pad-" ), this->m_Key ) ), &this->m_PaddingValue, "Padding value", &this->m_PaddingFlag );
00075 
00076   cl.AddOption( CommandLine::Key( strcat( strcpy( buffer, "thresh-min-" ), this->m_Key ) ), &this->m_LowerThresholdValue, "Minimum value truncation threshold", &this->m_LowerThresholdActive );
00077   cl.AddOption( CommandLine::Key( strcat( strcpy( buffer, "thresh-max-" ), this->m_Key ) ), &this->m_UpperThresholdValue, "Maximum value truncation threshold", &this->m_UpperThresholdActive );
00078   
00079   cl.AddOption( CommandLine::Key( strcat( strcpy( buffer, "prune-histogram-" ), this->m_Key ) ), &this->m_PruneHistogramBins, "Number of bins for histogram-based pruning", &this->m_UsePruneHistogramBins );
00080   cl.AddSwitch( CommandLine::Key( strcat( strcpy( buffer, "histogram-equalization-" ), this->m_Key ) ), &this->m_HistogramEqualization, true, "Apply histogram equalization" );
00081   cl.AddOption( CommandLine::Key( strcat( strcpy( buffer, "median-filter-radius-" ), this->m_Key ) ), &this->m_MedianFilterRadius, "Apply median filter with given radius" );
00082   cl.AddSwitch( CommandLine::Key( strcat( strcpy( buffer, "sobel-filter-" ), this->m_Key ) ), &this->m_SobelFilter, true, "Apply Sobel edge detection filter" );
00083   
00084   cl.AddOption( CommandLine::Key( strcat( strcpy( buffer, "crop-index-" ), this->m_Key ) ), &this->m_CropIndex, "Cropping region in pixel index coordinates [parsed as %d,%d,%d,%d,%d,%d for i0,j0,k0,i1,j1,k1]" );
00085   cl.AddOption( CommandLine::Key( strcat( strcpy( buffer, "crop-world-" ), this->m_Key ) ), &this->m_CropWorld, "Cropping region in world coordinates [parsed as %f,%f,%f,%f,%f,%f for x0,y0,z0,x1,y1,z1]" );
00086   cl.AddOption( CommandLine::Key( strcat( strcpy( buffer, "crop-thresh-" ), this->m_Key ) ), &this->m_AutoCropLevel, "Automatic cropping based on threshold", &this->m_AutoCropFlag );
00087   
00088   cl.EndGroup();
00089 }
00090 
00091 UniformVolume::SmartPtr
00092 ImagePairRegistration::ImagePreprocessor::GetProcessedImage( const UniformVolume* original )
00093 {
00094   UniformVolume::SmartPtr volume( original->Clone() );
00095   TypedArray::SmartPtr data = volume->GetData();
00096 
00097   if ( this->m_DataClassString )
00098     {
00099     this->m_DataClass = StringToDataClass( this->m_DataClassString );
00100     data->SetDataClass( this->m_DataClass );
00101     }
00102 
00103   if ( this->m_PaddingFlag ) 
00104     {
00105     data->SetPaddingValue( this->m_PaddingValue );
00106     }
00107 
00108   if ( this->m_LowerThresholdActive || this->m_UpperThresholdActive )
00109     {
00110     data->Threshold( Types::DataItemRange( this->m_LowerThresholdValue, this->m_UpperThresholdValue ) );
00111     }
00112 
00113   if ( this->m_PruneHistogramBins )
00114     {
00115     data->PruneHistogram( true , false , this->m_PruneHistogramBins );
00116     }
00117   
00118   if ( this->m_HistogramEqualization ) 
00119     {
00120     data->ApplyFunctionObject( TypedArrayFunctionHistogramEqualization( *data ) );
00121     }
00122 
00123   if ( this->m_MedianFilterRadius ) 
00124     {
00125     volume->SetData( DataGridFilter( volume ).GetDataMedianFiltered( this->m_MedianFilterRadius ) );
00126     }
00127   
00128   if ( this->m_SobelFilter ) 
00129     {
00130     volume->SetData( DataGridFilter( volume ).GetDataSobelFiltered() );
00131     }
00132 
00133   if ( this->m_CropIndex )
00134     {
00135     int cropFrom[3], cropTo[3];
00136     if ( 6 != sscanf( this->m_CropIndex, "%d,%d,%d,%d,%d,%d", cropFrom, cropFrom+1, cropFrom+2, cropTo, cropTo+1, cropTo+2 ) ) 
00137       {
00138       StdErr << "Option index coordinate cropping expects six integer parameters but got '" << this->m_CropIndex << "'\n";
00139       exit( 1 );
00140       }
00141     
00142     for ( int dim=0; dim<3; ++dim ) 
00143       {
00144       if ( cropTo[dim] < 0 ) 
00145         {
00146         cropTo[dim] = volume->GetDims()[dim] + cropTo[dim] + 1;
00147         }
00148       }
00149     volume->CropRegion() = DataGrid::RegionType( DataGrid::IndexType( cropFrom ), DataGrid::IndexType( cropTo ) );
00150     }
00151   
00152   if ( this->m_CropWorld )
00153     {
00154     float crop[6];
00155     if ( 6 != sscanf( this->m_CropWorld, "%f,%f,%f,%f,%f,%f", crop, crop+1, crop+2, crop+3, crop+4, crop+5 ) ) 
00156       {
00157       StdErr << "Option world coordinate cropping expects six floating-point parameters but got '" << this->m_CropWorld << "'\n";
00158       exit( 1 );
00159       }
00160     
00161     Types::Coordinate realCropFrom[3], realCropTo[3];
00162     for ( int dim=0; dim<3; ++dim ) 
00163       {
00164       realCropFrom[dim] = crop[dim];
00165       if ( crop[3+dim] < 0 ) 
00166         {
00167         realCropTo[dim] = volume->Size[dim] + crop[3+dim];
00168         }
00169       else
00170         {
00171         realCropTo[dim] = crop[3+dim];
00172         }
00173       }
00174     volume->SetHighResCropRegion( UniformVolume::CoordinateRegionType( UniformVolume::CoordinateRegionType::IndexType( realCropFrom ), UniformVolume::CoordinateRegionType::IndexType( realCropTo ) ) );
00175     }
00176   
00177   if ( this->m_AutoCropFlag )
00178     {
00179     volume->AutoCrop( this->m_AutoCropLevel, true  );
00180     }
00181 
00182   return volume;
00183 }
00184 
00185 void 
00186 ImagePairRegistration::ImagePreprocessor::WriteSettings
00187 ( ClassStream& stream ) const
00188 {
00189   char buffer[64];
00190   stream.Begin( strcat( strcpy( buffer, "preprocessing_" ), this->m_Key ) );
00191   switch ( this->m_DataClass ) 
00192     {
00193     case DATACLASS_GREY:
00194       stream.WriteString( "dataclass", "GreyLevel" );
00195       break;
00196     case DATACLASS_LABEL:
00197       stream.WriteString( "dataclass", "LabelField" );
00198       break;
00199     default:
00200       stream.WriteString( "dataclass", "Unknown" );
00201       break;
00202     }
00203 
00204   if ( this->m_PaddingFlag )
00205     stream.WriteDouble( "padding_value", this->m_PaddingValue );
00206 
00207   if ( this->m_LowerThresholdActive )
00208     stream.WriteDouble( "thresh_lower", this->m_LowerThresholdValue );    
00209     
00210   if ( this->m_UpperThresholdActive )
00211     stream.WriteDouble( "thresh_upper", this->m_UpperThresholdValue );    
00212     
00213   if ( this->m_PruneHistogramBins )
00214     stream.WriteInt( "prune_histogram_bins", this->m_PruneHistogramBins );
00215 
00216   if ( this->m_HistogramEqualization ) 
00217     stream.WriteBool( "histogram_equalization", true );
00218 
00219   if ( this->m_SobelFilter ) 
00220     stream.WriteBool( "sobel_filter", true );
00221 
00222   if ( this->m_CropIndex )
00223     stream.WriteString( "crop_index", this->m_CropIndex );
00224 
00225   if ( this->m_CropWorld )
00226     stream.WriteString( "crop_world", this->m_CropWorld );
00227 
00228   if ( this->m_AutoCropFlag )
00229     stream.WriteDouble( "auto_crop_level", this->m_AutoCropLevel );
00230 
00231   stream.End();
00232 }  
00233 
00234 }