diff --git a/Modules/MitkAlgorithmsExt/mitkSimpleHistogram.cpp b/Modules/MitkAlgorithmsExt/mitkSimpleHistogram.cpp index ffda3f4bea..e68c0ac3af 100644 --- a/Modules/MitkAlgorithmsExt/mitkSimpleHistogram.cpp +++ b/Modules/MitkAlgorithmsExt/mitkSimpleHistogram.cpp @@ -1,248 +1,252 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSimpleHistogram.h" #include "mitkSimpleUnstructuredGridHistogram.h" #include "mitkUnstructuredGrid.h" #include "mitkImageReadAccessor.h" namespace mitk { void SimpleImageHistogram::ComputeFromBaseData( BaseData* src ) { valid = false; //check if input is valid if (src==NULL) return; Image* source = dynamic_cast(src); if (source==NULL) return; else if (source->IsEmpty()) return; // dummy histogram { min=0; max=1; first=0; last=1; } { int typInt=0; { const int typ=source->GetPixelType().GetComponentType(); if (typ == itk::ImageIOBase::UCHAR) typInt=0; else if(typ == itk::ImageIOBase::CHAR) typInt=1; else if(typ == itk::ImageIOBase::USHORT) typInt=2; else if(typ == itk::ImageIOBase::SHORT) typInt=3; else { MITK_WARN << "SimpleImageHistogram currently only supports un/signed char/short"; return; } } first=-32768; last=65535; // support at least full signed and unsigned short range if(histogram) delete histogram; histogram = new CountType[last-first+1]; memset(histogram,0,sizeof(CountType)*(last-first+1)); highest = 0; max = first - 1; min = last + 1; unsigned int num=1; for(unsigned int r=0;rGetDimension();r++) num*=source->GetDimension(r); // MITK_INFO << "building histogramm of integer image: 0=" << source->GetDimension(0) << " 1=" << source->GetDimension(1) << " 2=" << source->GetDimension(2) << " 3=" << source->GetDimension(3); ImageReadAccessor sourceAcc(source); const void *src = sourceAcc.GetData(); do { int value; switch(typInt) { case 0: { unsigned char *t=(unsigned char *)src; value=*t++; src=(void*)t; } break; case 1: { signed char *t=( signed char *)src; value=*t++; src=(void*)t; } break; case 2: { unsigned short *t=(unsigned short*)src; value=*t++; src=(void*)t; } break; case 3: { signed short *t=( signed short*)src; value=*t++; src=(void*)t; } break; } if(value >= first && value <= last) { if(value < min) min = value; if(value > max) max = value; CountType tmp = ++histogram[value-first]; if(tmp > highest) highest = tmp; } } while(--num); MITK_INFO << "histogramm computed: min=" << min << " max=" << max << " highestBin=" << highest << " samples=" << num; } invLogHighest = 1.0/log(double(highest)); valid = true; } bool SimpleImageHistogram::GetValid() { return valid; } float SimpleImageHistogram::GetRelativeBin( double left, double right ) const { if( !valid ) return 0.0f; int iLeft = floorf(left); int iRight = ceilf(right); /* double sum = 0; for( int r = 0 ; r < 256 ; r++) { int pos = left + (right-left) * r/255.0; int posInArray = floorf(pos+0.5f) - first; sum += float(log(double(histogram[posInArray]))); } sum /= 256.0; return float(sum*invLogHighest); */ CountType maximum = 0; for( int i = iLeft; i <= iRight ; i++) { int posInArray = i - first; if( histogram[posInArray] > maximum ) maximum = histogram[posInArray]; } return float(log(double(maximum))*invLogHighest); } class ImageHistogramCacheElement : public SimpleHistogramCache::Element { public: void ComputeFromBaseData(BaseData* baseData) { histogram.ComputeFromBaseData(baseData); } SimpleHistogram* GetHistogram() { return &histogram; } SimpleImageHistogram histogram; }; class UnstructuredGridHistogramCacheElement : public SimpleHistogramCache::Element { public: void ComputeFromBaseData(BaseData* baseData) { histogram.ComputeFromBaseData(baseData); } SimpleHistogram* GetHistogram() { return &histogram; } SimpleUnstructuredGridHistogram histogram; }; SimpleHistogram* SimpleHistogramCache::operator[](BaseData::Pointer sp_BaseData) { BaseData *p_BaseData = sp_BaseData.GetPointer(); if(!p_BaseData) { MITK_WARN << "SimpleHistogramCache::operator[] with null base data called"; return 0; } Element *elementToUpdate = 0; bool first = true; for(CacheContainer::iterator iter = cache.begin(); iter != cache.end(); iter++) { Element *e = *iter; BaseData *p_tmp = e->baseData.GetPointer(); if(p_tmp == p_BaseData) { if(!first) { cache.erase(iter); cache.push_front(e); } if( p_BaseData->GetMTime() > e->m_LastUpdateTime.GetMTime()) { elementToUpdate = e; goto recomputeElement; } //MITK_INFO << "using a cached histogram"; return e->GetHistogram(); } first = false; } if (dynamic_cast(p_BaseData)) { elementToUpdate = new ImageHistogramCacheElement(); } else if (dynamic_cast(p_BaseData)) { elementToUpdate = new UnstructuredGridHistogramCacheElement(); } else { MITK_WARN << "not supported: " << p_BaseData->GetNameOfClass(); } elementToUpdate->baseData = p_BaseData; cache.push_front(elementToUpdate); TrimCache(); recomputeElement: //MITK_INFO << "computing a new histogram"; elementToUpdate->ComputeFromBaseData(p_BaseData); elementToUpdate->m_LastUpdateTime.Modified(); return elementToUpdate->GetHistogram(); } +SimpleHistogramCache::Element::~Element() +{ +} + } diff --git a/Modules/MitkAlgorithmsExt/mitkSimpleHistogram.h b/Modules/MitkAlgorithmsExt/mitkSimpleHistogram.h index a6da6dbcba..7143c0c21d 100644 --- a/Modules/MitkAlgorithmsExt/mitkSimpleHistogram.h +++ b/Modules/MitkAlgorithmsExt/mitkSimpleHistogram.h @@ -1,172 +1,174 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKSIMPLEHISTOGRAM_H #define MITKSIMPLEHISTOGRAM_H #ifndef __itkHistogram_h #include #endif #include "MitkAlgorithmsExtExports.h" #include #include #include #include namespace mitk { //##Documentation //## @brief Abstract superclass for histograms with double values. //## Classes which are deriving from this class can be cached //## in the same way. class MitkAlgorithmsExt_EXPORT SimpleHistogram { public: /** @brief Returns the minimal value of the histogram. */ virtual double GetMin() const = 0; /** @brief Returns the maximum value of the histogram. */ virtual double GetMax() const = 0; /** @brief Creates a new histogram out the source. */ virtual void ComputeFromBaseData( BaseData* source ) = 0; /** @brief TODO: (What should this method do?)*/ virtual float GetRelativeBin( double start, double end ) const = 0; }; class MitkAlgorithmsExt_EXPORT SimpleImageHistogram : public SimpleHistogram { public: typedef itk::Statistics::Histogram HistogramType; SimpleImageHistogram() { valid=false; histogram=0; } ~SimpleImageHistogram() { if(histogram) delete histogram; } /** @return Returns if the current histogram is valid, false if not. */ bool GetValid(); typedef itk::Image CTImage; typedef itk::ImageRegionIterator< CTImage > CTIteratorType; typedef itk::ImageRegionIteratorWithIndex< CTImage > CTIteratorIndexType; typedef itk::Image BinImage; typedef itk::ImageRegionIterator< BinImage > BinIteratorType; typedef itk::ImageRegionIteratorWithIndex< BinImage > BinIteratorIndexType; typedef unsigned long CountType; protected: CountType *histogram; bool valid; int first; int last; int min; int max; CountType highest; double invLogHighest; public: double GetMin() const { if(!valid) return 0; return min; } double GetMax() const { if(!valid) return 1; return max; } /** @brief Creates a new histogram out the source which must be an image. Method does nothing if the image is invalid, NULL, etc.. */ void ComputeFromBaseData( BaseData* source ); float GetRelativeBin( double start, double end ) const; }; class MitkAlgorithmsExt_EXPORT SimpleHistogramCache { public: static const unsigned int maxCacheSize = 64; class Element { public: mitk::WeakPointer baseData; itk::TimeStamp m_LastUpdateTime; + virtual ~Element(); + virtual void ComputeFromBaseData(BaseData* baseData) = 0; virtual SimpleHistogram* GetHistogram() = 0; }; typedef std::list CacheContainer; CacheContainer cache; SimpleHistogramCache() { } ~SimpleHistogramCache() { TrimCache(true); } SimpleHistogram *operator[](BaseData::Pointer sp_BaseData); protected: void TrimCache(bool full=false) { unsigned int targetSize = full?0:maxCacheSize; while(cache.size()>targetSize) { delete cache.back(); cache.pop_back(); } } }; } #endif // MITKSIMPLEHISTOGRAM_H