ITK/Examples/Developer/OilPaintingImageFilter
From KitwarePublic
This example demonstrates a simple multi-threaded filter, creating the effect of oil painting. You can also use this class as-is (copy .h and .txx files into your project and use them).
Contents |
ImageFilterExample.cxx
#include "itkImage.h" #include "itkImageFileReader.h" #include "itkImageFileWriter.h" #include "itkOilPaintingImageFilter.h" int main(int, char*[]) { typedef itk::Image<unsigned char, 2> ImageType; typedef itk::OilPaintingImageFilter<ImageType> FilterType; typedef itk::ImageFileReader<ImageType> ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName("LenaGrayscale.jpg"); reader->Update(); FilterType::Pointer filter = FilterType::New(); filter->SetInput(reader->GetOutput()); filter->SetNumberOfBins(50); filter->SetRadius(2); filter->Update(); typedef itk::ImageFileWriter< ImageType > WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetFileName("LenaOil.jpg"); writer->SetInput(filter->GetOutput()); writer->Update(); return EXIT_SUCCESS; }
itkOilPaintingImageFilter.h
#ifndef __itkOilPaintingImageFilter_h #define __itkOilPaintingImageFilter_h #include "itkImageToImageFilter.h" #include "itkNeighborhoodIterator.h" namespace itk { /** \class OilPaintingImageFilter * \brief Implements oil painting artistic image filter. * * Default number of bins is 20. * Default radius is 5, meaning a window of 11x11x11 for 3D images. * * \ingroup ImageFilters */ template< class TImage> class OilPaintingImageFilter:public ImageToImageFilter< TImage, TImage > { public: /** Standard class typedefs. */ typedef OilPaintingImageFilter Self; typedef ImageToImageFilter< TImage, TImage > Superclass; typedef SmartPointer< Self > Pointer; typedef typename NeighborhoodIterator<TImage>::RadiusType RadiusType; /** Method for creation through the object factory. */ itkNewMacro(Self); /** Run-time type information (and related methods). */ itkTypeMacro(OilPaintingImageFilter, ImageToImageFilter); itkSetMacro(NumberOfBins, unsigned int); itkGetConstMacro(NumberOfBins, const unsigned int); itkSetMacro(Radius, RadiusType); itkGetConstMacro(Radius, const RadiusType); void SetRadius(unsigned int radius); protected: OilPaintingImageFilter(); ~OilPaintingImageFilter(){} virtual void BeforeThreadedGenerateData(); /** Does the real work. */ virtual void ThreadedGenerateData(const typename Superclass::OutputImageRegionType& outputRegionForThread, int threadId); private: OilPaintingImageFilter(const Self &); //purposely not implemented void operator=(const Self &); //purposely not implemented typename TImage::ValueType m_Maximum, m_Minimum; typename NeighborhoodIterator<TImage>::RadiusType m_Radius; unsigned int m_NumberOfBins; }; } //namespace ITK #ifndef ITK_MANUAL_INSTANTIATION #include "itkOilPaintingImageFilter.txx" #endif #endif // __itkOilPaintingImageFilter_h
itkOilPaintingImageFilter.txx
#ifndef __itkOilPaintingImageFilter_txx #define __itkOilPaintingImageFilter_txx #include "itkOilPaintingImageFilter.h" #include "itkObjectFactory.h" #include "itkImageRegionIterator.h" #include "itkImageRegionConstIterator.h" #include "itkNeighborhoodIterator.h" #include "itkMinimumMaximumImageCalculator.h" namespace itk { template<class TImage> OilPaintingImageFilter<TImage>::OilPaintingImageFilter() { m_NumberOfBins=20; SetRadius(5); } template<class TImage> void OilPaintingImageFilter<TImage>::SetRadius(unsigned int radius) { for (unsigned int i = 0; i < TImage::ImageDimension; ++i) m_Radius[i] = radius; } template<class TImage> void OilPaintingImageFilter<TImage>::BeforeThreadedGenerateData() { typedef itk::MinimumMaximumImageCalculator< TImage > CalculatorType; typename CalculatorType::Pointer calculatorI = CalculatorType::New(); calculatorI->SetImage( this->GetInput() ); calculatorI->Compute(); m_Maximum = calculatorI->GetMaximum(); m_Minimum = calculatorI->GetMinimum(); } template<class TImage> void OilPaintingImageFilter<TImage> ::ThreadedGenerateData(const typename Superclass::OutputImageRegionType& outputRegionForThread, int threadId) { typename TImage::ConstPointer input = this->GetInput(); typename TImage::Pointer output = this->GetOutput(); itk::ImageRegionIterator<TImage> out(output, outputRegionForThread); itk::ConstNeighborhoodIterator<TImage> it(m_Radius, input, outputRegionForThread); unsigned long long *bins=new unsigned long long[m_NumberOfBins]; while(!out.IsAtEnd()) { for (unsigned int i=0; i<m_NumberOfBins; i++) bins[i]=0; //reset histogram //create histogram of values within the radius for (unsigned int i = 0; i < it.Size(); ++i) { typename TImage::ValueType val=it.GetPixel(i); bins[int((m_NumberOfBins-0.001)*(val-m_Minimum)/(m_Maximum-m_Minimum))]++; //casting to int rounds towards zero //without -0.001, when val=max then we would go over the upper bound (index m_NumberOfBins) } //find the peak unsigned maxIndex=0; unsigned long long maxBin=bins[0]; for (unsigned int i=1; i<m_NumberOfBins; i++) if (bins[i]>maxBin) { maxBin=bins[i]; maxIndex=i; } //set middle value of a bin's range as intensity out.Set((maxIndex+0.5)*(m_Maximum-m_Minimum)/m_NumberOfBins); ++it; ++out; } delete bins; //dealloc array } }// end namespace #endif //__itkOilPaintingImageFilter_txx
CMakeLists.txt
cmake_minimum_required(VERSION 2.8) project(ImageFilterExample) find_package(ITK REQUIRED) include(${ITK_USE_FILE}) add_executable(ImageFilterExample ImageFilterExample.cxx) if( "${ITK_VERSION_MAJOR}" LESS 4 ) target_link_libraries(ImageFilterExample ITKReview ${ITK_LIBRARIES}) else( "${ITK_VERSION_MAJOR}" LESS 4 ) target_link_libraries(ImageFilterExample ${ITK_LIBRARIES}) endif( "${ITK_VERSION_MAJOR}" LESS 4 )