-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathitkMyResampleImageFilter.h
367 lines (301 loc) · 16.5 KB
/
itkMyResampleImageFilter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
//**********************************************************
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//**********************************************************
//
//
#ifndef ITKMYRESAMPLEIMAGEFILTER_H
#define ITKMYRESAMPLEIMAGEFILTER_H
#include "itkFixedArray.h"
#include "itkTransform.h"
#include "itkImageRegionIterator.h"
#include "itkImageToImageFilter.h"
#include "itkExtrapolateImageFunction.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkSize.h"
#include "itkDefaultConvertPixelTraits.h"
#include "itkDataObjectDecorator.h"
namespace itk
{
/** \class MyResampleImageFilter
* \brief Resample an image via a coordinate transform
*
* ResampleImageFilter resamples an existing image through some coordinate
* transform, interpolating via some image function. The class is templated
* over the types of the input and output images.
*
* Note that the choice of interpolator function can be important.
* This function is set via SetInterpolator(). The default is
* LinearInterpolateImageFunction<InputImageType,
* TInterpolatorPrecisionType>, which
* is reasonable for ordinary medical images. However, some synthetic
* images have pixels drawn from a finite prescribed set. An example
* would be a mask indicating the segmentation of a brain into a small
* number of tissue types. For such an image, one does not want to
* interpolate between different pixel values, and so
* NearestNeighborInterpolateImageFunction< InputImageType,
* TCoordRep > would be a better choice.
*
* If an sample is taken from outside the image domain, the default behavior is
* to use a default pixel value. If different behavior is desired, an
* extrapolator function can be set with SetExtrapolator().
*
* Output information (spacing, size and direction) for the output
* image should be set. This information has the normal defaults of
* unit spacing, zero origin and identity direction. Optionally, the
* output information can be obtained from a reference image. If the
* reference image is provided and UseReferenceImage is On, then the
* spacing, origin and direction of the reference image will be used.
*
* Since this filter produces an image which is a different size than
* its input, it needs to override several of the methods defined
* in ProcessObject in order to properly manage the pipeline execution model.
* In particular, this filter overrides
* ProcessObject::GenerateInputRequestedRegion() and
* ProcessObject::GenerateOutputInformation().
*
* This filter is implemented as a multithreaded filter. It provides a
* DynamicThreadedGenerateData() method for its implementation.
* \warning For multithreading, the TransformPoint method of the
* user-designated coordinate transform must be threadsafe.
*
* \ingroup GeometricTransform
* \ingroup ITKImageGrid
*
* \wiki
* \wikiexample{SimpleOperations/TranslationTransform,Translate an image}
* \wikiexample{ImageProcessing/Upsampling,Upsampling an image}
* \wikiexample{ImageProcessing/ResampleImageFilter,Resample (stretch or compress) an image}
* \endwiki
*/
template< typename TInputImage,
typename TOutputImage,
typename TInterpolatorPrecisionType = double,
typename TTransformPrecisionType = TInterpolatorPrecisionType>
class ITK_TEMPLATE_EXPORT MyResampleImageFilter :
public ImageToImageFilter< TInputImage, TOutputImage >
{
public:
ITK_DISALLOW_COPY_AND_ASSIGN(MyResampleImageFilter);
/** Standard class type aliases. */
using Self = MyResampleImageFilter;
using Superclass = ImageToImageFilter< TInputImage, TOutputImage >;
using Pointer = SmartPointer< Self >;
using ConstPointer = SmartPointer< const Self >;
using InputImageType = TInputImage;
using OutputImageType = TOutputImage;
using InputImagePointer = typename InputImageType::Pointer;
using InputImageConstPointer = typename InputImageType::ConstPointer;
using OutputImagePointer = typename OutputImageType::Pointer;
using InputImageRegionType = typename InputImageType::RegionType;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(MyResampleImageFilter, ImageToImageFilter);
/** Number of dimensions. */
static constexpr unsigned int OutputImageDimension = TOutputImage::ImageDimension;
static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;
/** base type for images of the current OutputImageDimension */
using ImageBaseType = ImageBase< Self::OutputImageDimension >;
/**
* Transform type alias.
*/
using TransformType = Transform< TTransformPrecisionType,
Self::OutputImageDimension,
Self::InputImageDimension >;
using TransformPointerType = typename TransformType::ConstPointer;
using DecoratedTransformType = DataObjectDecorator<TransformType>;
using DecoratedTransformPointer = typename DecoratedTransformType::Pointer;
/** Interpolator type alias. */
using InterpolatorType = InterpolateImageFunction< InputImageType,
TInterpolatorPrecisionType >;
using InterpolatorPointerType = typename InterpolatorType::Pointer;
using InterpolatorOutputType = typename InterpolatorType::OutputType;
using InterpolatorConvertType = DefaultConvertPixelTraits< InterpolatorOutputType >;
using ComponentType = typename InterpolatorConvertType::ComponentType;
using LinearInterpolatorType = LinearInterpolateImageFunction< InputImageType,
TInterpolatorPrecisionType >;
using LinearInterpolatorPointerType = typename LinearInterpolatorType::Pointer;
/** Extrapolator type alias. */
using ExtrapolatorType = ExtrapolateImageFunction< InputImageType,
TInterpolatorPrecisionType >;
using ExtrapolatorPointerType = typename ExtrapolatorType::Pointer;
/** Image size type alias. */
using SizeType = Size< Self::OutputImageDimension >;
/** Image index type alias. */
using IndexType = typename TOutputImage::IndexType;
/** Image point type alias. */
using InputPointType = typename InterpolatorType::PointType;
using OutputPointType = typename TOutputImage::PointType;
/** Image pixel value type alias. */
using PixelType = typename TOutputImage::PixelType;
using InputPixelType = typename TInputImage::PixelType;
using PixelConvertType = DefaultConvertPixelTraits<PixelType>;
using PixelComponentType = typename PixelConvertType::ComponentType;
/** Input pixel continuous index typdef */
using ContinuousInputIndexType =
ContinuousIndex< TInterpolatorPrecisionType, InputImageDimension >;
/** Typedef to describe the output image region type. */
using OutputImageRegionType = typename TOutputImage::RegionType;
/** Image spacing,origin and direction type alias */
using SpacingType = typename TOutputImage::SpacingType;
using OriginPointType = typename TOutputImage::PointType;
using DirectionType = typename TOutputImage::DirectionType;
/** Typedef the reference image type to be the ImageBase of the OutputImageType */
using ReferenceImageBaseType = ImageBase<OutputImageDimension>;
/** Get/Set the coordinate transformation.
* Set the coordinate transform to use for resampling. Note that this must
* be in physical coordinates and it is the output-to-input transform, NOT
* the input-to-output transform that you might naively expect. By default
* the filter uses an Identity transform. You must provide a different
* transform here, before attempting to run the filter, if you do not want to
* use the default Identity transform. */
itkSetGetDecoratedObjectInputMacro(Transform, TransformType);
/** Get/Set the interpolator function. The default is
* LinearInterpolateImageFunction<InputImageType,
* TInterpolatorPrecisionType>. Some
* other options are NearestNeighborInterpolateImageFunction
* (useful for binary masks and other images with a small number of
* possible pixel values), and BSplineInterpolateImageFunction
* (which provides a higher order of interpolation). */
itkSetObjectMacro(Interpolator, InterpolatorType);
itkGetModifiableObjectMacro(Interpolator, InterpolatorType);
/** Get/Set the extrapolator function. The default behavior when sampling outside
* of the input image is to use the DefaultPixelValue. Some other options
* include NearestNeighborExtrapolateImageFunction. */
itkSetObjectMacro(Extrapolator, ExtrapolatorType);
itkGetModifiableObjectMacro(Extrapolator, ExtrapolatorType);
/** Get/Set the size of the output image. */
itkSetMacro(Size, SizeType);
itkGetConstReferenceMacro(Size, SizeType);
/** Get/Set the pixel value when a transformed pixel is outside of the
* image. The default default pixel value is 0. */
itkSetMacro(DefaultPixelValue, PixelType);
itkGetConstReferenceMacro(DefaultPixelValue, PixelType);
/** Set the output image spacing. */
itkSetMacro(OutputSpacing, SpacingType);
virtual void SetOutputSpacing(const double *values);
/** Get the output image spacing. */
itkGetConstReferenceMacro(OutputSpacing, SpacingType);
/** Set the output image origin. */
itkSetMacro(OutputOrigin, OriginPointType);
virtual void SetOutputOrigin(const double *values);
/** Get the output image origin. */
itkGetConstReferenceMacro(OutputOrigin, OriginPointType);
/** Set the output direciton cosine matrix. */
itkSetMacro(OutputDirection, DirectionType);
itkGetConstReferenceMacro(OutputDirection, DirectionType);
/** Helper method to set the output parameters based on this image. */
void SetOutputParametersFromImage(const ImageBaseType *image);
/** Set the start index of the output largest possible region.
* The default is an index of all zeros. */
itkSetMacro(OutputStartIndex, IndexType);
/** Get the start index of the output largest possible region. */
itkGetConstReferenceMacro(OutputStartIndex, IndexType);
/** Set a reference image to use to define the output information.
* By default, output information is specificed through the
* SetOutputSpacing, Origin, and Direction methods. Alternatively,
* this method can be used to specify an image from which to
* copy the information. UseReferenceImageOn must be set to utilize the
* reference image. */
itkSetInputMacro(ReferenceImage, ReferenceImageBaseType);
/** Get the reference image that is defining the output information. */
itkGetInputMacro(ReferenceImage, ReferenceImageBaseType);
/** Turn on/off whether a specified reference image should be used to define
* the output information. */
itkSetMacro(UseReferenceImage, bool);
itkBooleanMacro(UseReferenceImage);
itkGetConstMacro(UseReferenceImage, bool);
#ifdef ITK_USE_CONCEPT_CHECKING
// Begin concept checking
itkConceptMacro( OutputHasNumericTraitsCheck,
( Concept::HasNumericTraits< PixelComponentType > ) );
// End concept checking
#endif
protected:
MyResampleImageFilter();
~MyResampleImageFilter() override = default;
void PrintSelf(std::ostream & os, Indent indent) const override;
/** Override VeriyInputInformation() since this filter's inputs do
* not need to occoupy the same physical space.
*
* \sa ProcessObject::VerifyInputInformation
*/
void VerifyInputInformation() ITKv5_CONST override { }
/** ResampleImageFilter produces an image which is a different size
* than its input. As such, it needs to provide an implementation
* for GenerateOutputInformation() in order to inform the pipeline
* execution model. The original documentation of this method is
* below. \sa ProcessObject::GenerateOutputInformaton() */
void GenerateOutputInformation() override;
/** ResampleImageFilter needs a different input requested region than
* the output requested region. As such, ResampleImageFilter needs
* to provide an implementation for GenerateInputRequestedRegion()
* in order to inform the pipeline execution model.
* \sa ProcessObject::GenerateInputRequestedRegion() */
void GenerateInputRequestedRegion() override;
/** Set up state of filter before multi-threading.
* InterpolatorType::SetInputImage is not thread-safe and hence
* has to be set up before DynamicThreadedGenerateData */
void BeforeThreadedGenerateData() override;
/** Set the state of the filter after multi-threading. */
void AfterThreadedGenerateData() override;
/** Compute the Modified Time based on the changed components. */
ModifiedTimeType GetMTime() const override;
/** ResampleImageFilter can be implemented as a multithreaded filter.
* Therefore, this implementation provides a DynamicThreadedGenerateData()
* routine which is called for each processing thread. The output
* image data is allocated automatically by the superclass prior
* to calling DynamicThreadedGenerateData().
* DynamicThreadedGenerateData can only write to the portion of the output image
* specified by the parameter "outputRegionForThread"
* \sa ImageToImageFilter::ThreadedGenerateData(),
* ImageToImageFilter::GenerateData() */
void DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;
/** Default implementation for resampling that works for any
* transformation type. */
virtual void NonlinearThreadedGenerateData(const OutputImageRegionType & outputRegionForThread);
/** Implementation for resampling that works for with linear
* transformation types. */
virtual void LinearThreadedGenerateData(const OutputImageRegionType & outputRegionForThread);
/** Cast pixel from interpolator output to PixelType. */
itkLegacyMacro(
virtual PixelType CastPixelWithBoundsChecking( const InterpolatorOutputType value,
const ComponentType minComponent,
const ComponentType maxComponent) const);
private:
static PixelComponentType CastComponentWithBoundsChecking(const PixelComponentType value);
template <typename TComponent>
static PixelComponentType CastComponentWithBoundsChecking(const TComponent value);
static PixelType CastPixelWithBoundsChecking(const ComponentType value);
template <typename TPixel>
static PixelType CastPixelWithBoundsChecking(const TPixel value);
SizeType m_Size; // Size of the output image
InterpolatorPointerType m_Interpolator; // Image function for
// interpolation
ExtrapolatorPointerType m_Extrapolator; // Image function for
// extrapolation
PixelType m_DefaultPixelValue; // default pixel value
// if the point is
// outside the image
SpacingType m_OutputSpacing; // output image spacing
OriginPointType m_OutputOrigin; // output image origin
DirectionType m_OutputDirection; // output image direction cosines
IndexType m_OutputStartIndex; // output image start index
bool m_UseReferenceImage{ false };
};
} // end namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkMyResampleImageFilter.hxx"
#endif
#endif //ITKMYRESAMPLEIMAGEFILTER_H