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 <Registration/cmtkVoxelRegistration.h>
00034
00035 #include <System/cmtkCommandLine.h>
00036
00037 #include <Base/cmtkTypedArrayFunctionHistogramEqualization.h>
00038 #include <Base/cmtkDataGridFilter.h>
00039
00040 namespace
00041 cmtk
00042 {
00043
00044 VoxelRegistration::ImagePreprocessor::ImagePreprocessor( const char* name, const char* key )
00045 : m_DataClassString( NULL ),
00046 m_DataClass( DATACLASS_GREY ),
00047 m_PaddingFlag( false ),
00048 m_PaddingValue( 0 ),
00049 m_LowerThresholdActive( false ),
00050 m_LowerThresholdValue( -CMTK_ITEM_MAX ),
00051 m_UpperThresholdActive( false ),
00052 m_UpperThresholdValue( CMTK_ITEM_MAX ),
00053 m_UsePruneHistogramBins( false ),
00054 m_PruneHistogramBins( 0 ),
00055 m_HistogramEqualization( false ),
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 VoxelRegistration::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.AddSwitch( CommandLine::Key( strcat( strcpy( buffer, "sobel-filter-" ), this->m_Key ) ), &this->m_SobelFilter, true, "Apply Sobel edge detection filter" );
00082
00083 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]" );
00084 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]" );
00085
00086 cl.EndGroup();
00087 }
00088
00089 UniformVolume::SmartPtr
00090 VoxelRegistration::ImagePreprocessor::GetProcessedImage( const UniformVolume* original )
00091 {
00092 UniformVolume::SmartPtr volume( original->Clone() );
00093 TypedArray::SmartPtr data = volume->GetData();
00094
00095 if ( this->m_DataClassString )
00096 {
00097 this->m_DataClass = StringToDataClass( this->m_DataClassString );
00098 data->SetDataClass( this->m_DataClass );
00099 }
00100
00101 if ( this->m_PaddingFlag )
00102 {
00103 data->SetPaddingValue( this->m_PaddingValue );
00104 }
00105
00106 if ( this->m_LowerThresholdActive || this->m_UpperThresholdActive )
00107 {
00108 data->Threshold( Types::DataItemRange( this->m_LowerThresholdValue, this->m_UpperThresholdValue ) );
00109 }
00110
00111 if ( this->m_PruneHistogramBins )
00112 {
00113 data->PruneHistogram( true , false , this->m_PruneHistogramBins );
00114 }
00115
00116 if ( this->m_HistogramEqualization )
00117 {
00118 data->ApplyFunctionObject( TypedArrayFunctionHistogramEqualization( *data ) );
00119 }
00120
00121 if ( this->m_SobelFilter )
00122 {
00123 volume->SetData( DataGridFilter( volume ).GetDataSobelFiltered() );
00124 }
00125
00126 if ( this->m_CropIndex )
00127 {
00128 int cropFrom[3], cropTo[3];
00129 if ( 6 != sscanf( this->m_CropIndex, "%d,%d,%d,%d,%d,%d", cropFrom, cropFrom+1, cropFrom+2, cropTo, cropTo+1, cropTo+2 ) )
00130 {
00131 StdErr << "Option index coordinate cropping expects six integer parameters but got '" << this->m_CropIndex << "'\n";
00132 exit( 1 );
00133 }
00134
00135 for ( int dim=0; dim<3; ++dim )
00136 {
00137 if ( cropTo[dim] < 0 )
00138 {
00139 cropTo[dim] = volume->GetDims()[dim] + cropTo[dim] + 1;
00140 }
00141 }
00142 volume->CropRegion() = DataGrid::RegionType( DataGrid::IndexType( cropFrom ), DataGrid::IndexType( cropTo ) );
00143 }
00144
00145 if ( this->m_CropWorld )
00146 {
00147 float crop[6];
00148 if ( 6 != sscanf( this->m_CropWorld, "%f,%f,%f,%f,%f,%f", crop, crop+1, crop+2, crop+3, crop+4, crop+5 ) )
00149 {
00150 StdErr << "Option world coordinate cropping expects six floating-point parameters but got '" << this->m_CropWorld << "'\n";
00151 exit( 1 );
00152 }
00153
00154 Types::Coordinate realCropFrom[3], realCropTo[3];
00155 for ( int dim=0; dim<3; ++dim )
00156 {
00157 realCropFrom[dim] = crop[dim];
00158 if ( crop[3+dim] < 0 )
00159 {
00160 realCropTo[dim] = volume->Size[dim] + crop[3+dim];
00161 }
00162 else
00163 {
00164 realCropTo[dim] = crop[3+dim];
00165 }
00166 }
00167 volume->SetHighResCropRegion( UniformVolume::CoordinateRegionType( UniformVolume::CoordinateRegionType::IndexType( realCropFrom ), UniformVolume::CoordinateRegionType::IndexType( realCropTo ) ) );
00168 }
00169
00170 if ( this->m_AutoCropFlag )
00171 {
00172 volume->AutoCrop( this->m_AutoCropLevel, true );
00173 }
00174
00175 return volume;
00176 }
00177
00178 void
00179 VoxelRegistration::ImagePreprocessor::WriteSettings
00180 ( ClassStream& stream ) const
00181 {
00182 char buffer[64];
00183 stream.Begin( strcat( strcpy( buffer, "preprocessing_" ), this->m_Key ) );
00184 switch ( this->m_DataClass )
00185 {
00186 case DATACLASS_GREY:
00187 stream.WriteString( "dataclass", "GreyLevel" );
00188 break;
00189 case DATACLASS_LABEL:
00190 stream.WriteString( "dataclass", "LabelField" );
00191 break;
00192 default:
00193 stream.WriteString( "dataclass", "Unknown" );
00194 break;
00195 }
00196
00197 if ( this->m_PaddingFlag )
00198 stream.WriteDouble( "padding_value", this->m_PaddingValue );
00199
00200 if ( this->m_LowerThresholdActive )
00201 stream.WriteDouble( "thresh_lower", this->m_LowerThresholdValue );
00202
00203 if ( this->m_UpperThresholdActive )
00204 stream.WriteDouble( "thresh_upper", this->m_UpperThresholdValue );
00205
00206 if ( this->m_PruneHistogramBins )
00207 stream.WriteInt( "prune_histogram_bins", this->m_PruneHistogramBins );
00208
00209 if ( this->m_HistogramEqualization )
00210 stream.WriteBool( "histogram_equalization", true );
00211
00212 if ( this->m_SobelFilter )
00213 stream.WriteBool( "sobel_filter", true );
00214
00215 if ( this->m_CropIndex )
00216 stream.WriteString( "crop_index", this->m_CropIndex );
00217
00218 if ( this->m_CropWorld )
00219 stream.WriteString( "crop_world", this->m_CropWorld );
00220
00221 if ( this->m_AutoCropFlag )
00222 stream.WriteDouble( "auto_crop_level", this->m_AutoCropLevel );
00223
00224 stream.End();
00225 }
00226
00227 }