|
|
Line 1: |
Line 1: |
| This example demonstrates how to write a filter which uses multiple threads.
| | {{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.}} |
| | |
| The image is automatically broken into pieces and the ThreadedGenerateData is called with each piece. For example with this 3x2 image and 2 threads, the filter is called with the following regions: | |
| | |
| Thread 0 given region: ImageRegion (0xbf9e2d0c)
| |
| Dimension: 2
| |
| Index: [0, 0]
| |
| Size: [3, 1]
| |
| | |
| Thread 1 given region: ImageRegion (0xb74b62dc)
| |
| Dimension: 2
| |
| Index: [0, 1]
| |
| Size: [3, 1]
| |
| | |
| In the example, we set the corner (GetIndex()) of each region to the id of the thread that processed the region.
| |
| | |
| The output is (linearly output in raster order) thus: | |
| | |
| 0
| |
| 100
| |
| 100
| |
| 1
| |
| 100
| |
| 100
| |
| | |
| ==MultiThreadedImageFilter.cxx==
| |
| <source lang="cpp">
| |
| #include "itkImage.h"
| |
| #include "itkImageFileReader.h"
| |
| #include "itkImageFileWriter.h"
| |
| | |
| #include "MultiThreadedImageFilter.h"
| |
| | |
| template <typename TImage>
| |
| static void CreateImage(TImage* const image);
| |
| | |
| template <typename TImage>
| |
| static void OutputImage(TImage* const image);
| |
| | |
| int main(int, char*[])
| |
| {
| |
| // Setup types
| |
| typedef itk::Image<int, 2> ImageType;
| |
| typedef itk::MultiThreadedImageFilter<ImageType> FilterType;
| |
| | |
| ImageType::Pointer image = ImageType::New();
| |
| CreateImage(image.GetPointer());
| |
| | |
| // Create and the filter
| |
| FilterType::Pointer filter = FilterType::New();
| |
| filter->SetInput(image);
| |
| // filter->SetNumberOfThreads(3); // There is no need to specify this, it is automatically determined
| |
| filter->Update();
| |
| | |
| std::cout << "Image after filter: " << std::endl;
| |
| OutputImage(image.GetPointer());
| |
| | |
| std::cout << "Output: " << std::endl;
| |
| OutputImage(filter->GetOutput());
| |
| | |
| return EXIT_SUCCESS;
| |
| }
| |
| | |
| | |
| template <typename TImage>
| |
| void CreateImage(TImage* const image)
| |
| {
| |
| // Create an image with 2 connected components
| |
| typename TImage::IndexType corner = {{0,0}};
| |
| | |
| // unsigned int NumRows = 200;
| |
| // unsigned int NumCols = 300;
| |
| | |
| unsigned int NumRows = 3;
| |
| unsigned int NumCols = 2;
| |
| typename TImage::SizeType size = {{NumRows, NumCols}};
| |
| | |
| typename TImage::RegionType region(corner, size);
| |
| | |
| image->SetRegions(region);
| |
| image->Allocate();
| |
| | |
| image->FillBuffer(0);
| |
| }
| |
| | |
| template <typename TImage>
| |
| void OutputImage(TImage* const image)
| |
| {
| |
| itk::ImageRegionConstIterator<TImage> imageIterator(image, image->GetLargestPossibleRegion());
| |
| | |
| while(!imageIterator.IsAtEnd())
| |
| {
| |
| std::cout << imageIterator.Get() << std::endl;
| |
| | |
| ++imageIterator;
| |
| }
| |
| }
| |
| | |
| </source>
| |
| | |
| ==MultiThreadedImageFilter.h==
| |
| <source lang="cpp">
| |
| #ifndef __itkImageFilter_h
| |
| #define __itkImageFilter_h
| |
| | |
| #include "itkImageToImageFilter.h"
| |
| | |
| namespace itk
| |
| {
| |
| template< class TImage>
| |
| class MultiThreadedImageFilter : public ImageToImageFilter< TImage, TImage >
| |
| {
| |
| public:
| |
| /** Standard class typedefs. */
| |
| typedef MultiThreadedImageFilter Self;
| |
| typedef ImageToImageFilter< TImage, TImage > Superclass;
| |
| typedef SmartPointer< Self > Pointer;
| |
| | |
| typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
| |
| | |
| /** Method for creation through the object factory. */
| |
| itkNewMacro(Self);
| |
| | |
| /** Run-time type information (and related methods). */
| |
| itkTypeMacro(ImageFilter, ImageToImageFilter);
| |
| | |
| protected:
| |
| MultiThreadedImageFilter(){}
| |
| ~MultiThreadedImageFilter(){}
| |
| | |
| virtual void ThreadedGenerateData(const OutputImageRegionType &,
| |
| ThreadIdType);
| |
| | |
| private:
| |
| MultiThreadedImageFilter(const Self &); //purposely not implemented
| |
| void operator=(const Self &); //purposely not implemented
| |
| | |
| };
| |
| } //namespace ITK
| |
| | |
| | |
| #ifndef ITK_MANUAL_INSTANTIATION
| |
| #include "MultiThreadedImageFilter.hxx"
| |
| #endif
| |
| | |
| | |
| #endif // __itkMultiThreadedImageFilter_h
| |
| | |
| </source>
| |
| | |
| ==MultiThreadedImageFilter.hxx==
| |
| <source lang="cpp">
| |
| #ifndef __itkMultiThreadedImageFilter_hxx
| |
| #define __itkMultiThreadedImageFilter_hxx
| |
| | |
| #include "MultiThreadedImageFilter.h"
| |
| | |
| #include "itkObjectFactory.h"
| |
| #include "itkImageRegionIterator.h"
| |
| #include "itkImageRegionConstIterator.h"
| |
| | |
| namespace itk
| |
| {
| |
| | |
| template< class TImage>
| |
| void MultiThreadedImageFilter< TImage>
| |
| ::ThreadedGenerateData(const OutputImageRegionType & region, ThreadIdType threadId)
| |
| {
| |
| std::cout << "Thread " << threadId << " given region: " << region << std::endl;
| |
| | |
| typename TImage::ConstPointer input = this->GetInput();
| |
| typename TImage::Pointer output = this->GetOutput();
| |
| | |
| ImageAlgorithm::Copy(input.GetPointer(), output.GetPointer(), region,
| |
| region);
| |
| | |
| itk::Index<2> cornerPixel = region.GetIndex();
| |
| std::cout << "cornerPixel: " << cornerPixel << std::endl;
| |
| typename TImage::PixelType newValue = 3;
| |
| | |
| output->SetPixel( cornerPixel, newValue );
| |
| }
| |
| | |
| }// end namespace
| |
| | |
| | |
| #endif
| |
| </source>
| |
| | |
| {{ITKCMakeLists|{{SUBPAGENAME}}}}
| |