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
00032
00033 #include <algorithm>
00034
00035 #ifdef HAVE_IEEEFP_H
00036 # include <ieeefp.h>
00037 #endif
00038
00039 #include <Base/cmtkTypedArrayFunctionHistogramMatching.h>
00040
00041 namespace
00042 cmtk
00043 {
00044
00047
00048 template<class T>
00049 double
00050 TemplateArray<T>
00051 ::GetEntropy( const bool fractional, const int numberOfBins ) const
00052 {
00053 double entropy = 0;
00054 if ( fractional )
00055 {
00056 Histogram<double> histogram( numberOfBins );
00057 histogram.SetRange( this->GetRange() );
00058
00059 for ( size_t idx = 0; idx < DataSize; ++idx )
00060 if ( !PaddingFlag || (Data[idx] != Padding) )
00061 histogram.IncrementFractional( histogram.ValueToBinFractional( Data[idx] ) );
00062 entropy = histogram.GetEntropy();
00063 }
00064 else
00065 {
00066 Histogram<unsigned int> histogram( numberOfBins );
00067 histogram.SetRange( this->GetRange() );
00068
00069 for ( size_t idx = 0; idx < DataSize; ++idx )
00070 if ( !PaddingFlag || (Data[idx] != Padding) )
00071 histogram.Increment( histogram.ValueToBin( Data[idx] ) );
00072 entropy = histogram.GetEntropy();
00073 }
00074 return entropy;
00075 }
00076
00077 template<class T>
00078 double
00079 TemplateArray<T>
00080 ::GetEntropy( Histogram<unsigned int>& histogram ) const
00081 {
00082 histogram.Reset();
00083 for ( size_t idx = 0; idx < DataSize; ++idx )
00084 if ( !PaddingFlag || (Data[idx] != Padding) )
00085 histogram.Increment( histogram.ValueToBin( Data[idx] ) );
00086 return histogram.GetEntropy();
00087 }
00088
00089 template<class T> double
00090 TemplateArray<T>
00091 ::GetEntropy( Histogram<double>& histogram, const bool fractional ) const
00092 {
00093 histogram.Reset();
00094 if ( fractional )
00095 {
00096 for ( size_t idx = 0; idx < DataSize; ++idx )
00097 if ( !PaddingFlag || (Data[idx] != Padding) )
00098 histogram.IncrementFractional( histogram.ValueToBinFractional( Data[idx] ) );
00099 }
00100 else
00101 {
00102 for ( size_t idx = 0; idx < DataSize; ++idx )
00103 if ( !PaddingFlag || (Data[idx] != Padding) )
00104 histogram.Increment( histogram.ValueToBin( Data[idx] ) );
00105 }
00106 return histogram.GetEntropy();
00107 }
00108
00109 template<class T> double
00110 TemplateArray<T>
00111 ::GetEntropy( Histogram<double>& histogram, const double* kernel, const size_t kernelRadius ) const
00112 {
00113 histogram.Reset();
00114 for ( size_t idx = 0; idx < DataSize; ++idx )
00115 if ( !PaddingFlag || (Data[idx] != Padding) )
00116 histogram.AddWeightedSymmetricKernelFractional( histogram.ValueToBinFractional( Data[idx] ), kernelRadius, kernel );
00117 return histogram.GetEntropy();
00118 }
00119
00120 template<class T>
00121 const Types::DataItemRange
00122 TemplateArray<T>
00123 ::GetRange() const
00124 {
00125 return Types::DataItemRange( this->GetRangeTemplate() );
00126 }
00127
00128 template<class T>
00129 const Types::Range<T>
00130 TemplateArray<T>
00131 ::GetRangeTemplate()
00132 const
00133 {
00134 Types::Range<T> range( 0, 0 );
00135
00136
00137 size_t idx = 0;
00138 if ( PaddingFlag )
00139 {
00140 while ( (idx < DataSize) && ((Data[idx] == Padding) || !finite(Data[idx])) )
00141 ++idx;
00142 }
00143 else
00144 {
00145 while ( (idx < DataSize) && !finite(Data[idx]) )
00146 ++idx;
00147 }
00148
00149
00150 if ( idx < DataSize)
00151 {
00152
00153 range.m_LowerBound = range.m_UpperBound = Data[idx];
00154
00155 if ( PaddingFlag )
00156 {
00157 for ( ; idx < DataSize; ++idx )
00158 {
00159 if ( (Data[idx] != Padding) && finite(Data[idx]) )
00160 {
00161 if (Data[idx] > range.m_UpperBound)
00162 range.m_UpperBound = Data[idx];
00163 if (Data[idx] < range.m_LowerBound)
00164 range.m_LowerBound = Data[idx];
00165 }
00166 }
00167 }
00168 else
00169 {
00170 for ( ; idx < DataSize; ++idx )
00171 {
00172 if ( finite(Data[idx]) )
00173 {
00174 if (Data[idx] > range.m_UpperBound)
00175 range.m_UpperBound = Data[idx];
00176 if (Data[idx] < range.m_LowerBound)
00177 range.m_LowerBound = Data[idx];
00178 }
00179 }
00180 }
00181 }
00182
00183 return range;
00184 }
00185
00189 template<class T>
00190 TypedArray::SmartPtr
00191 TemplateArray<T>
00192 ::Convert( const ScalarDataType dtype ) const
00193 {
00194 void* data = this->ConvertArray( dtype );
00195 return TypedArray::Create( dtype, data, DataSize, true );
00196 }
00197
00198 template<class T>
00199 void*
00200 TemplateArray<T>
00201 ::ConvertSubArray
00202 ( const ScalarDataType dtype, const size_t fromIdx, const size_t len ) const
00203 {
00204 void* data = Memory::AllocateArray<char>( len * TypeItemSize( dtype ) );
00205 this->ConvertSubArray( data, dtype, fromIdx, len );
00206 return data;
00207 }
00208
00209 template<class T>
00210 void
00211 TemplateArray<T>
00212 ::GammaCorrection( const Types::DataItem gamma )
00213 {
00214 if ( gamma > 0 )
00215 {
00216 Types::Range<T> range = this->GetRangeTemplate();
00217
00218 const T diff = range.m_UpperBound - range.m_LowerBound;
00219 const double scale = 1.0 / diff;
00220
00221 #pragma omp parallel for if (DataSize>1e5)
00222 for ( size_t i = 0; i < DataSize; ++i )
00223 if ( ! PaddingFlag || (Data[i] != Padding ) )
00224 {
00225 if ( Data[i] > range.m_LowerBound )
00226 {
00227 Data[i] = range.m_LowerBound + TypeTraits::Convert( diff * exp( log( scale * (Data[i]-range.m_LowerBound) ) / gamma ) );
00228 }
00229 }
00230 }
00231 }
00232
00233 template<class T>
00234 void
00235 TemplateArray<T>
00236 ::ApplyFunctionFloat( typename Self::FunctionTypeFloat f )
00237 {
00238 #pragma omp parallel for if (DataSize>1e5)
00239 for ( size_t i = 0; i < DataSize; ++i )
00240 if ( ! PaddingFlag || (Data[i] != Padding ) )
00241 {
00242 Data[i] = TypeTraits::Convert( f( (float)Data[i] ) );
00243 }
00244 }
00245
00246 template<class T>
00247 void
00248 TemplateArray<T>
00249 ::ApplyFunctionDouble( typename Self::FunctionTypeDouble f )
00250 {
00251 #pragma omp parallel for if (DataSize>1e5)
00252 for ( size_t i = 0; i < DataSize; ++i )
00253 if ( ! PaddingFlag || (Data[i] != Padding ) )
00254 {
00255 Data[i] = TypeTraits::Convert( f( (double)Data[i] ) );
00256 }
00257 }
00258
00259 template<class T>
00260 void TemplateArray<T>
00261 ::ConvertSubArray
00262 ( void *const destination, const ScalarDataType dtype, const size_t fromIdx, const size_t len ) const
00263 {
00264 if ( dtype == this->GetType() )
00265 memcpy( destination, Data + fromIdx, len * this->GetItemSize() );
00266 else
00267 {
00268 switch ( dtype )
00269 {
00270 case TYPE_BYTE:
00271 #pragma omp parallel for if (len>1e5)
00272 for ( size_t idx = 0; idx < len; ++idx )
00273 ((byte*)destination)[idx] = DataTypeTraits<byte>::Convert( Data[ idx + fromIdx ] );
00274 break;
00275 case TYPE_CHAR:
00276 #pragma omp parallel for if (len>1e5)
00277 for ( size_t idx = 0; idx < len; ++idx )
00278 ((char*)destination)[idx] = DataTypeTraits<char>::Convert( Data[ idx + fromIdx ] );
00279 break;
00280 case TYPE_USHORT:
00281 #pragma omp parallel for if (len>1e5)
00282 for ( size_t idx = 0; idx < len; ++idx )
00283 ((unsigned short*)destination)[idx] = DataTypeTraits<unsigned short>::Convert( Data[ idx + fromIdx ] );
00284 break;
00285 case TYPE_SHORT:
00286 #pragma omp parallel for if (len>1e5)
00287 for ( size_t idx = 0; idx < len; ++idx )
00288 ((short*)destination)[idx] = DataTypeTraits<short>::Convert( Data[ idx + fromIdx ] );
00289 break;
00290 case TYPE_INT:
00291 #pragma omp parallel for if (len>1e5)
00292 for ( size_t idx = 0; idx < len; ++idx )
00293 ((int*)destination)[idx] = DataTypeTraits<int>::Convert( Data[ idx + fromIdx ] );
00294 break;
00295 case TYPE_FLOAT:
00296 #pragma omp parallel for if (len>1e5)
00297 for ( size_t idx = 0; idx < len; ++idx )
00298 ((float*)destination)[idx] = DataTypeTraits<float>::Convert( Data[ idx + fromIdx ] );
00299 break;
00300 case TYPE_DOUBLE:
00301 #pragma omp parallel for if (len>1e5)
00302 for ( size_t idx = 0; idx < len; ++idx )
00303 ((double*)destination)[idx] = DataTypeTraits<double>::Convert( Data[ idx + fromIdx ] );
00304 break;
00305 default:
00306
00307 break;
00308 }
00309 }
00310 }
00311
00312 template<class T>
00313 void
00314 TemplateArray<T>
00315 ::ChangeEndianness()
00316 {
00317 size_t itemSize = this->GetItemSize();
00318 if ( itemSize < 2 ) return;
00319 size_t dataBytes = DataSize * itemSize;
00320
00321
00322
00323 size_t f, l;
00324 for ( f=0, l=itemSize-1; f<dataBytes; f+=itemSize,l+=itemSize )
00325 for ( size_t j=0; j<itemSize/2; ++j )
00326 {
00327 char d = ((char*)Data)[l-j];
00328 ((char*)Data)[l-j] = ((char*)Data)[f+j];
00329 ((char*)Data)[f+j] = d;
00330 }
00331 }
00332
00333 template<class T>
00334 void
00335 TemplateArray<T>
00336 ::ApplyFunctionObject( const TypedArrayFunction& f )
00337 {
00338 #pragma omp parallel for
00339 for ( size_t i = 0; i < this->DataSize; ++i )
00340 {
00341 if ( !this->PaddingFlag || (this->Data[i] != this->Padding) )
00342 this->Data[i] = static_cast<T>( f( this->Data[i] ) );
00343 }
00344 }
00345
00346 template<class T>
00347 void
00348 TemplateArray<T>
00349 ::BlockSet
00350 ( const Types::DataItem value, const size_t fromOffset, const size_t toOffset )
00351 {
00352 T valueT = TypeTraits::Convert( value );
00353
00354 #pragma omp parallel for
00355 for ( size_t i = fromOffset; i < toOffset; ++i )
00356 Data[i] = valueT;
00357 }
00358
00359 }