diff --git a/Modules/MitkExt/Algorithms/mitkSimpleHistogram.cpp b/Modules/MitkExt/Algorithms/mitkSimpleHistogram.cpp index 9806be62e4..72d6e6bc60 100644 --- a/Modules/MitkExt/Algorithms/mitkSimpleHistogram.cpp +++ b/Modules/MitkExt/Algorithms/mitkSimpleHistogram.cpp @@ -1,234 +1,244 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkSimpleHistogram.h" #include "mitkSimpleUnstructuredGridHistogram.h" #include "mitkUnstructuredGrid.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 std::type_info* typ=source->GetPixelType().GetTypeId(); if (*typ == typeid(unsigned char )) typInt=0; else if(*typ == typeid(signed char )) typInt=1; else if(*typ == typeid(unsigned short)) typInt=2; else if(*typ == typeid(signed 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); void *src=source->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()) 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(); } } diff --git a/Modules/MitkExt/Algorithms/mitkSimpleHistogram.h b/Modules/MitkExt/Algorithms/mitkSimpleHistogram.h index d089f3a05a..1c2b92ec7a 100644 --- a/Modules/MitkExt/Algorithms/mitkSimpleHistogram.h +++ b/Modules/MitkExt/Algorithms/mitkSimpleHistogram.h @@ -1,155 +1,166 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKSIMPLEHISTOGRAM_H #define MITKSIMPLEHISTOGRAM_H #include "MitkExtExports.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 MitkExt_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 MitkExt_EXPORT SimpleImageHistogram : public SimpleHistogram { public: 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 MitkExt_EXPORT SimpleHistogramCache { public: static const unsigned int maxCacheSize = 64; class Element { public: mitk::WeakPointer baseData; itk::TimeStamp m_LastUpdateTime; 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 diff --git a/Modules/MitkExt/Testing/files.cmake b/Modules/MitkExt/Testing/files.cmake index 6b2ca9ac79..0d77aae0d5 100644 --- a/Modules/MitkExt/Testing/files.cmake +++ b/Modules/MitkExt/Testing/files.cmake @@ -1,39 +1,40 @@ -SET(MODULE_TESTS +SET(MODULE_TESTS mitkAutoCropImageFilterTest.cpp mitkBoundingObjectCutterTest.cpp mitkContourMapper2DTest.cpp mitkContourTest.cpp mitkCoreExtObjectFactoryTest mitkDataNodeExtTest.cpp mitkExternalToolsTest.cpp mitkMeshTest.cpp mitkMultiStepperTest.cpp mitkOrganTypePropertyTest.cpp mitkPipelineSmartPointerCorrectnessTest.cpp mitkPlaneFitTest.cpp mitkPointLocatorTest.cpp # mitkSegmentationInterpolationTest.cpp # mitkTestTemplate.cpp mitkToolManagerTest.cpp + mitkSimpleHistogramTest.cpp ) SET(MODULE_IMAGE_TESTS mitkUnstructuredGridVtkWriterTest.cpp - mitkCompressedImageContainerTest.cpp + mitkCompressedImageContainerTest.cpp mitkCylindricToCartesianFilterTest.cpp - #mitkExtractImageFilterTest.cpp + #mitkExtractImageFilterTest.cpp mitkManualSegmentationToSurfaceFilterTest.cpp - mitkOverwriteSliceImageFilterTest.cpp + mitkOverwriteSliceImageFilterTest.cpp mitkSurfaceToImageFilterTest.cpp ) -SET(MODULE_CUSTOM_TESTS +SET(MODULE_CUSTOM_TESTS mitkLabeledImageToSurfaceFilterTest.cpp ) SET(MODULE_TESTIMAGES US4DCyl.pic.gz Pic3D.pic.gz Pic2DplusT.pic.gz BallBinary30x30x30.pic.gz Png2D-bw.png binary.stl ball.stl -) +) \ No newline at end of file diff --git a/Modules/MitkExt/Testing/mitkSimpleHistogramTest.cpp b/Modules/MitkExt/Testing/mitkSimpleHistogramTest.cpp new file mode 100644 index 0000000000..68bb96e027 --- /dev/null +++ b/Modules/MitkExt/Testing/mitkSimpleHistogramTest.cpp @@ -0,0 +1,47 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include +#include +#include + +int mitkSimpleHistogramTest(int /*argc*/, char* /*argv*/[]) +{ + MITK_TEST_BEGIN("mitkSimpleHistogram"); + + mitk::SimpleImageHistogram* myTestSimpleImageHistogram = new mitk::SimpleImageHistogram(); + + MITK_TEST_CONDITION_REQUIRED(myTestSimpleImageHistogram!=NULL,"Testing instanciation."); + MITK_TEST_CONDITION_REQUIRED(myTestSimpleImageHistogram->GetMax()==1,"Testing GetMax()."); + MITK_TEST_CONDITION_REQUIRED(myTestSimpleImageHistogram->GetMin()==0,"Testing GetMin()."); + MITK_TEST_CONDITION_REQUIRED(myTestSimpleImageHistogram->GetRelativeBin(1.0,5.0) ==0,"Testing GetRelativeBin()."); + bool success = true; + try + { + myTestSimpleImageHistogram->ComputeFromBaseData(NULL); + myTestSimpleImageHistogram->ComputeFromBaseData(mitk::Image::New()); //an empty image + myTestSimpleImageHistogram->ComputeFromBaseData(mitk::Surface::New()); //an invalid value + } + catch(...) + { + success = false; + } + MITK_TEST_CONDITION_REQUIRED(success,"Testing ComputeFromBaseData() with invalid input values."); + MITK_TEST_CONDITION_REQUIRED(!myTestSimpleImageHistogram->GetValid(),"Testing if histogram is invalid after invalid input."); + + MITK_TEST_END(); +} \ No newline at end of file