|
|
(One intermediate revision by one other user not shown) |
Line 1: |
Line 1: |
| 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).
| | {{warning|1=The media wiki content on this page is no longer maintained. The examples presented on the https://itk.org/Wiki/* pages likely require ITK version 4.13 or earlier releases. In many cases, the examples on this page no longer conform to the best practices for modern ITK versions.}} |
| | |
| ==OilPaintingImageFilter.cxx==
| |
| <source lang="cpp">
| |
| #include "itkImage.h"
| |
| #include "itkImageFileReader.h"
| |
|
| |
| #include "itkOilPaintingImageFilter.h"
| |
|
| |
| #include "QuickView.h"
| |
| | |
| int main(int argc, char*argv[])
| |
| { | |
| if (argc < 2)
| |
| {
| |
| std::cerr << "Usage: " << argv[0] << " inputFile [bins [radius]]" << std::endl;
| |
| return EXIT_FAILURE;
| |
| }
| |
| unsigned int numberOfBins = 50;
| |
| if (argc > 3)
| |
| {
| |
| numberOfBins = atoi(argv[2]);
| |
| }
| |
| | |
| unsigned int radius = 2;
| |
| if (argc > 4)
| |
| {
| |
| radius = atoi(argv[3]);
| |
| }
| |
| | |
| typedef itk::Image<unsigned char, 2> ImageType;
| |
| typedef itk::OilPaintingImageFilter<ImageType> FilterType;
| |
|
| |
| typedef itk::ImageFileReader<ImageType> ReaderType;
| |
| ReaderType::Pointer reader = ReaderType::New();
| |
| reader->SetFileName(argv[1]);
| |
| reader->Update();
| |
|
| |
| FilterType::Pointer filter = FilterType::New();
| |
| filter->SetInput(reader->GetOutput());
| |
| filter->SetNumberOfBins(numberOfBins);
| |
| filter->SetRadius(radius);
| |
| filter->Update();
| |
|
| |
| QuickView viewer;
| |
| viewer.AddImage(
| |
| reader->GetOutput(),
| |
| true,
| |
| itksys::SystemTools::GetFilenameName(reader->GetFileName()));
| |
| | |
| std::stringstream desc;
| |
| desc << "OilPaintingImageFilter, bins = " << numberOfBins
| |
| << " radius = " << radius;
| |
| viewer.AddImage(
| |
| filter->GetOutput(),
| |
| true,
| |
| desc.str());
| |
| | |
| viewer.Visualize();
| |
| | |
| return EXIT_SUCCESS;
| |
| }
| |
| </source>
| |
| | |
| ==itkOilPaintingImageFilter.h==
| |
| <source lang="cpp">
| |
| #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, ThreadIdType 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
| |
| </source>
| |
| | |
| ==itkOilPaintingImageFilter.txx==
| |
| <source lang="cpp">
| |
| #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()
| |
| {
| |
| this->m_NumberOfBins=20;
| |
| this->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, ThreadIdType 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
| |
| </source>
| |
| | |
| {{ITKVTKCMakeLists|ImageFilterExample}}
| |