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 <Segmentation/cmtkOverlapMeasures.h>
00034
00035 #include <System/cmtkProgress.h>
00036
00037 #ifdef _OPENMP
00038 # include <omp.h>
00039 #endif
00040
00041 namespace
00042 cmtk
00043 {
00044
00047
00048 OverlapMeasures::OverlapMeasures( const std::vector<TypedArray::SmartPtr>& dataArrays )
00049 {
00050 this->m_DataArrays = dataArrays;
00051 this->m_MaxLabelValue = 0;
00052 for ( size_t i = 0; i < this->m_DataArrays.size(); ++i )
00053 {
00054 const Types::DataItemRange range = this->m_DataArrays[i]->GetRange();
00055 this->m_MaxLabelValue = std::max<unsigned int>( this->m_MaxLabelValue, static_cast<unsigned int>( range.m_UpperBound ) );
00056 }
00057
00058
00059 this->m_NumberOfImages = this->m_DataArrays.size();
00060
00061 this->m_NumberOfPixels = this->m_DataArrays[0]->GetDataSize();
00062 for ( size_t i = 1; i < this->m_NumberOfImages; ++i )
00063 {
00064 this->m_NumberOfPixels = std::min( this->m_NumberOfPixels, this->m_DataArrays[i]->GetDataSize() );
00065 }
00066 }
00067
00068 size_t
00069 OverlapMeasures::ComputeGroupwiseOverlap
00070 ( const int firstLabel, const int numberOfLabels, double& overlapEqualWeighted, double& overlapVolumeWeighted, double& overlapInverseWeighted ) const
00071 {
00072
00073 std::vector< std::vector< unsigned int > > volumeTable( numberOfLabels );
00074 for ( int label = 0; label < numberOfLabels; ++label )
00075 {
00076 volumeTable[label].resize( this->m_NumberOfImages, 0 );
00077 }
00078
00079 std::vector<bool> labelExists( numberOfLabels );
00080 std::fill( labelExists.begin(), labelExists.end(), false );
00081
00082 for ( size_t i = 0; i < this->m_NumberOfImages; ++i )
00083 {
00084 for ( size_t px = 0; px < this->m_NumberOfPixels; ++px )
00085 {
00086 Types::DataItem l;
00087 if ( this->m_DataArrays[i]->Get( l, px ) )
00088 {
00089 const int thisLabel = static_cast<int>(l) - firstLabel;
00090 if ( (thisLabel >= 0) && (thisLabel < numberOfLabels) )
00091 {
00092 ++volumeTable[thisLabel][i];
00093 labelExists[thisLabel] = true;
00094 }
00095 }
00096 }
00097 }
00098
00099 size_t numberOfLabelsIncluded = 0;
00100 for ( int label = 0; label < numberOfLabels; ++label )
00101 {
00102 if ( labelExists[label] )
00103 ++numberOfLabelsIncluded;
00104 }
00105 if ( ! numberOfLabelsIncluded )
00106 return numberOfLabelsIncluded;
00107
00108
00109 const size_t progressPixels = 100000;
00110 Progress::Begin( 0, this->m_NumberOfPixels, progressPixels, "Overlap computation" );
00111
00112 #ifdef _OPENMP
00113 const size_t numberOfThreads = omp_get_max_threads();
00114 #else
00115 const size_t numberOfThreads = 1;
00116 #endif
00117
00118 std::vector<int> labelsPerPixel( numberOfThreads * this->m_NumberOfImages );
00119
00120 const size_t sumsPerThread = numberOfLabels * this->m_NumberOfImages * (this->m_NumberOfImages-1) / 2;
00121 std::vector<double> sumsMin( numberOfThreads * sumsPerThread, 0.0 );
00122 std::vector<double> sumsMax( numberOfThreads * sumsPerThread, 0.0 );
00123
00124 #pragma omp parallel for
00125 for ( size_t px = 0; px < this->m_NumberOfPixels; ++px )
00126 {
00127 if ( (px % progressPixels) == 0 )
00128 #ifdef _OPENMP
00129 if ( !omp_get_thread_num() )
00130 #endif
00131 Progress::SetProgress( px );
00132
00133 #ifdef _OPENMP
00134 const size_t labelsPerPixelOfs = this->m_NumberOfImages * omp_get_thread_num();
00135 #else
00136 const size_t labelsPerPixelOfs = 0;
00137 #endif
00138
00139 Types::DataItem l;
00140 for ( size_t i = 0; i < this->m_NumberOfImages; ++i )
00141 {
00142 labelsPerPixel[labelsPerPixelOfs+i] = -1;
00143 if ( this->m_DataArrays[i]->Get( l, px ) )
00144 {
00145 const int thisLabel = static_cast<int>(l) - firstLabel;
00146 if ( (thisLabel >= 0) && (thisLabel < numberOfLabels) )
00147 labelsPerPixel[labelsPerPixelOfs+i] = thisLabel;
00148 }
00149 }
00150
00151 #ifdef _OPENMP
00152 size_t ofs = sumsPerThread * omp_get_thread_num();
00153 #else
00154 size_t ofs = 0;
00155 #endif
00156 for ( int label = 0; label < numberOfLabels; ++label )
00157 {
00158 if ( labelExists[label] )
00159 {
00160 for ( size_t i = 0; i < this->m_NumberOfImages; ++i )
00161 {
00162 const int wi = (labelsPerPixel[labelsPerPixelOfs+i] == label)?1:0;
00163 for ( size_t j = 0; j < i; ++j, ++ofs )
00164 {
00165 const int wj = (labelsPerPixel[labelsPerPixelOfs+j] == label)?1:0;
00166
00167 sumsMin[ofs] += std::min( wi, wj );
00168 sumsMax[ofs] += std::max( wi, wj );
00169 }
00170 }
00171 }
00172 }
00173 }
00174
00175 #ifdef _OPENMP
00176 size_t dstOfs = sumsPerThread;
00177 for ( size_t thread = 1; thread < numberOfThreads; ++thread )
00178 {
00179 size_t thrOfs = 0;
00180 for ( size_t i = 0; i < sumsPerThread; ++i, ++thrOfs, ++dstOfs )
00181 {
00182 sumsMin[thrOfs] += sumsMin[dstOfs];
00183 sumsMax[thrOfs] += sumsMax[dstOfs];
00184 }
00185 }
00186 #endif
00187
00188 Progress::Done();
00189
00190 double overlap_min_equal = 0, overlap_max_equal = 0;
00191 double overlap_min_volume = 0, overlap_max_volume = 0;
00192 double overlap_min_inverse = 0, overlap_max_inverse = 0;
00193
00194 size_t ofs = 0;
00195 for ( int label = 0; label < numberOfLabels; ++label )
00196 {
00197 if ( labelExists[label] )
00198 {
00199 for ( size_t i = 0; i < this->m_NumberOfImages; ++i )
00200 {
00201 const unsigned int vi = volumeTable[label][i];
00202 for ( size_t j = 0; j < i; ++j, ++ofs )
00203 {
00204 overlap_min_volume += sumsMin[ofs];
00205 overlap_max_volume += sumsMax[ofs];
00206
00207 const unsigned int vij = vi + volumeTable[label][j];
00208 if ( vij )
00209 {
00210 overlap_min_equal += sumsMin[ofs] / vij;
00211 overlap_max_equal += sumsMax[ofs] / vij;
00212
00213 overlap_min_inverse += (sumsMin[ofs] / vij) / vij;
00214 overlap_max_inverse += (sumsMax[ofs] / vij) / vij;
00215 }
00216 }
00217 }
00218 }
00219 }
00220
00221 if ( overlap_max_equal )
00222 overlapEqualWeighted = overlap_min_equal / overlap_max_equal;
00223 if ( overlap_max_volume )
00224 overlapVolumeWeighted = overlap_min_volume / overlap_max_volume;
00225 if ( overlap_max_inverse )
00226 overlapInverseWeighted = overlap_min_inverse / overlap_max_inverse;
00227
00228 return numberOfLabelsIncluded;
00229 }
00230
00231 double
00232 OverlapMeasures::ComputePairwiseOverlapMinMax
00233 ( double& overlap_min, double& overlap_max, const TypedArray::SmartPtr& data0, const TypedArray::SmartPtr& data1, const int label ) const
00234 {
00235 overlap_min = overlap_max = 0;
00236 for ( size_t i = 0; i < this->m_NumberOfPixels; ++i )
00237 {
00238 Types::DataItem l0, l1;
00239 if ( ! data0->Get( l0, i ) ) l0 = -1;
00240 if ( ! data1->Get( l1, i ) ) l1 = -1;
00241
00242 const int w0 = (l0 == label)?1:0;
00243 const int w1 = (l1 == label)?1:0;
00244
00245 overlap_min += std::min( w0, w1 );
00246 overlap_max += std::max( w0, w1 );
00247 }
00248 return 0;
00249 }
00250
00251 }
00252