Download presentation
Presentation is loading. Please wait.
Published byJustin Perkins Modified over 9 years ago
1
1 ITK Lecture 7 - Writing Filters, Part 1 Methods in Image Analysis CMU Robotics Institute 16-725 U. Pitt Bioengineering 2630 Spring Term, 2006 Methods in Image Analysis CMU Robotics Institute 16-725 U. Pitt Bioengineering 2630 Spring Term, 2006 Damion Shelton
2
2 Where we are You should understand What the pipeline is and how to connect filters together to perform sequential processing How to move through images using iterators How to access specific pixels based on their location in data space or physical space You should understand What the pipeline is and how to connect filters together to perform sequential processing How to move through images using iterators How to access specific pixels based on their location in data space or physical space
3
3 What we’ll cover How to write your own filter that can fit into the pipeline For reference, read Chapter 10 from the ITK Guide How to write your own filter that can fit into the pipeline For reference, read Chapter 10 from the ITK Guide
4
4 Is it hard or easy? Today: writing filters is really, really easy Next lecture: well… it can be tricky at times Remember, don’t panic! Today: writing filters is really, really easy Next lecture: well… it can be tricky at times Remember, don’t panic!
5
5 Cheat as much as possible! Never, ever, ever, write a filter from scratch Unless you’re doing something really odd, find a filter close to what you want and work from there Recycling the general framework will save you a lot of time and reduce errors Never, ever, ever, write a filter from scratch Unless you’re doing something really odd, find a filter close to what you want and work from there Recycling the general framework will save you a lot of time and reduce errors
6
6 Much of the filter is already written Most of the interface for an ImageToImageFilter is already coded by the base classes For example, SetInput and GetOutput are not functions you have to write You should never have to worry about particulars of the pipeline Most of the interface for an ImageToImageFilter is already coded by the base classes For example, SetInput and GetOutput are not functions you have to write You should never have to worry about particulars of the pipeline
7
7 The simple case You can write a filter with only one * function! (* well, sort of) Overload GenerateData(void) to produce output given some input We’ll look at ReflectImageFilter as an example (look in /Code/BasicFilters) You can write a filter with only one * function! (* well, sort of) Overload GenerateData(void) to produce output given some input We’ll look at ReflectImageFilter as an example (look in /Code/BasicFilters)
8
8 The header - stuff that’s “always there” itkNewMacro sets up the object factory (for reference counted smart pointers) itkTypeMacro allows you to use run time type information itkGetMacro and itkSetMacro are used to access private member variables itkNewMacro sets up the object factory (for reference counted smart pointers) itkTypeMacro allows you to use run time type information itkGetMacro and itkSetMacro are used to access private member variables
9
9 The header cont. Prototypes for functions you will overload: void PrintSelf(std::ostream& os, Indent indent) const; void GenerateData(void); Prototypes for functions you will overload: void PrintSelf(std::ostream& os, Indent indent) const; void GenerateData(void);
10
10 More header code You will also see: Many typedefs: Self, Superclass, Pointer, and ConstPointer are particularly important Constructor and destructor prototypes Member variables (in this example, only one) You will also see: Many typedefs: Self, Superclass, Pointer, and ConstPointer are particularly important Constructor and destructor prototypes Member variables (in this example, only one)
11
11 Pay attention to... #ifdef, #define, #endif are used to enforce single inclusion of header code Use of namespace itk The three lines starting with #ifndef ITK_MANUAL_INSTANTIATION control inclusion of the.txx file, since compilers don’t recognize the.txx as compilable source #ifdef, #define, #endif are used to enforce single inclusion of header code Use of namespace itk The three lines starting with #ifndef ITK_MANUAL_INSTANTIATION control inclusion of the.txx file, since compilers don’t recognize the.txx as compilable source
12
12 Does this seem complex? That’s why I suggested always starting with an existing class You may want to use find and replace to change the class name and edit from there Moving on to the.txx file... That’s why I suggested always starting with an existing class You may want to use find and replace to change the class name and edit from there Moving on to the.txx file...
13
13 The constructor In ReflectImageFilter, the constructor doesn’t do much Tell the pipeline framework that we want one and only one input Initialize the member variable In ReflectImageFilter, the constructor doesn’t do much Tell the pipeline framework that we want one and only one input Initialize the member variable
14
14 GenerateData() This is where most of the action occurs GenerateData() is called during the pipeline update process It’s responsible for allocating the output image (though the pointer already exists) and filling the image with interesting data This is where most of the action occurs GenerateData() is called during the pipeline update process It’s responsible for allocating the output image (though the pointer already exists) and filling the image with interesting data
15
15 Accessing the input and output First, we get the pointers to the input and ouput images typename Superclass::InputImageConstPointer inputPtr = this->GetInput(); typename Superclass::OutputImagePointer outputPtr = this->GetOutput(0); First, we get the pointers to the input and ouput images typename Superclass::InputImageConstPointer inputPtr = this->GetInput(); typename Superclass::OutputImagePointer outputPtr = this->GetOutput(0); Filters can have multiple outputs, in this case we only have one
16
16 Allocating the output image outputPtr->SetRequestedRegion( inputPtr- >GetRequestedRegion() ); outputPtr->SetBufferedRegion( inputPtr- >GetBufferedRegion() ); outputPtr->SetLargestPossibleRegion( inputPtr->GetLargestPossibleRegion() ); outputPtr->Allocate(); outputPtr->SetRequestedRegion( inputPtr- >GetRequestedRegion() ); outputPtr->SetBufferedRegion( inputPtr- >GetBufferedRegion() ); outputPtr->SetLargestPossibleRegion( inputPtr->GetLargestPossibleRegion() ); outputPtr->Allocate(); Question: How big is output image compared to the input?
17
17 The meat of GenerateData() Iterate “forwards” through input image and “backwards” through the output image Set the output pixel equal to the input pixel We can globally reverse the direction of iteration with m_Direction - i.e. forwards becomes backwards and vice-versa Iterate “forwards” through input image and “backwards” through the output image Set the output pixel equal to the input pixel We can globally reverse the direction of iteration with m_Direction - i.e. forwards becomes backwards and vice-versa
18
18 PrintSelf PrintSelf is a function present in all classes derived from itk::Object which permits easy display of the “state” of an object (i.e. all of its member variables) The testing framework requires that you implement this function, otherwise it will fail the “PrintSelf test” PrintSelf is a function present in all classes derived from itk::Object which permits easy display of the “state” of an object (i.e. all of its member variables) The testing framework requires that you implement this function, otherwise it will fail the “PrintSelf test”
19
19 PrintSelf, cont. First, we call the base class implementation Superclass::PrintSelf(os,indent); And second we print all of our member variables os << indent << "Direction: " << m_Direction << std::endl; First, we call the base class implementation Superclass::PrintSelf(os,indent); And second we print all of our member variables os << indent << "Direction: " << m_Direction << std::endl;
20
20 What we’ve just done We now have a filter that: Is single threaded (executes on one processor) Produces an output image the same size as the input Assumes a one-to-one mapping between input and output pixels This works, but seems a bit limiting... We now have a filter that: Is single threaded (executes on one processor) Produces an output image the same size as the input Assumes a one-to-one mapping between input and output pixels This works, but seems a bit limiting...
21
21 Questions? How can we make multithreaded filters? What if the input and output images are not the same size? E.g., convolution edge effects, subsampling, etc. What about requested regions? How can we make multithreaded filters? What if the input and output images are not the same size? E.g., convolution edge effects, subsampling, etc. What about requested regions?
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.