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 }