1 /*========================================================================= 2 * 3 * Copyright Insight Software Consortium 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0.txt 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 *=========================================================================*/ 18 #ifndef itkExtractImageFilter_h 19 #define itkExtractImageFilter_h 20 21 #include "itkInPlaceImageFilter.h" 22 #include "itkSmartPointer.h" 23 #include "itkExtractImageFilterRegionCopier.h" 24 25 namespace itk 26 { 27 /** \class ExtractImageFilter 28 * \brief Decrease the image size by cropping the image to the selected 29 * region bounds. 30 * 31 * ExtractImageFilter changes the image boundary of an image by removing 32 * pixels outside the target region. The target region must be specified. 33 * 34 * ExtractImageFilter also collapses dimensions so that the input image 35 * may have more dimensions than the output image (i.e. 4-D input image 36 * to a 3-D output image). To specify what dimensions to collapse, 37 * the ExtractionRegion must be specified. For any dimension dim where 38 * ExtractionRegion.Size[dim] = 0, that dimension is collapsed. The 39 * index to collapse on is specified by ExtractionRegion.Index[dim]. 40 * For example, we have a image 4D = a 4x4x4x4 image, and we want 41 * to get a 3D image, 3D = a 4x4x4 image, specified as [x,y,z,2] from 4D 42 * (i.e. the 3rd "time" slice from 4D). The ExtractionRegion.Size = 43 * [4,4,4,0] and ExtractionRegion.Index = [0,0,0,2]. 44 * 45 * The number of dimension in ExtractionRegion.Size and Index must = 46 * InputImageDimension. The number of non-zero dimensions in 47 * ExtractionRegion.Size must = OutputImageDimension. 48 * 49 * The output image produced by this filter will have the same origin as the 50 * input image, while the ImageRegion of the output image will start at the 51 * starting index value provided in the ExtractRegion parameter. If you are 52 * looking for a filter that will re-compute the origin of the output image, 53 * and provide an output image region whose index is set to zeros, then you may 54 * want to use the RegionOfInterestImageFilter. The output spacing is is 55 * simply the collapsed version of the input spacing. 56 * 57 * Determining the direction of the collapsed output image from an larger 58 * dimensional input space is an ill defined problem in general. It is 59 * required that the application developer select the desired transformation 60 * strategy for collapsing direction cosines. It is REQUIRED that a strategy 61 * be explicitly requested (i.e. there is no working default). 62 * Direction Collapsing Strategies: 63 * 1) DirectionCollapseToUnknown(); 64 * This is the default and the filter can not run when this is set. 65 * The reason is to explicitly force the application developer to 66 * define their desired behavior. 67 * 1) DirectionCollapseToIdentity(); 68 * Output has identity direction no matter what 69 * 2) DirectionCollapseToSubmatrix(); 70 * Output direction is the sub-matrix if it is positive definite, else throw an exception. 71 * 72 * This filter is implemented as a multithreaded filter. It provides a 73 * DynamicThreadedGenerateData() method for its implementation. 74 * 75 * \note This filter is derived from InPlaceImageFilter. When the 76 * input to this filter matched the output requirested region, like 77 * with streaming filter for input, then setting this filter to run 78 * in-place will result in no copying of the bulk pixel data. 79 * 80 * \sa CropImageFilter 81 * \ingroup GeometricTransform 82 * \ingroup ITKCommon 83 * 84 * \wiki 85 * \wikiexample{ImageProcessing/ExtractImageFilter,Crop an image by specifying the region to keep} 86 * \endwiki 87 */ 88 89 template< typename TInputImage, typename TOutputImage > 90 class ITK_TEMPLATE_EXPORT ExtractImageFilter: 91 public InPlaceImageFilter< TInputImage, TOutputImage > 92 { 93 public: 94 ITK_DISALLOW_COPY_AND_ASSIGN(ExtractImageFilter); 95 96 /** Standard class type aliases. */ 97 using Self = ExtractImageFilter; 98 using Superclass = InPlaceImageFilter< TInputImage, TOutputImage >; 99 using Pointer = SmartPointer< Self >; 100 using ConstPointer = SmartPointer< const Self >; 101 102 /** Method for creation through the object factory. */ 103 itkNewMacro(Self); 104 105 /** Run-time type information (and related methods). */ 106 itkTypeMacro(ExtractImageFilter, InPlaceImageFilter); 107 108 /** Image type information. */ 109 using InputImageType = TInputImage; 110 using OutputImageType = TOutputImage; 111 112 /** Typedef to describe the output and input image region types. */ 113 using OutputImageRegionType = typename TOutputImage::RegionType; 114 using InputImageRegionType = typename TInputImage::RegionType; 115 116 /** Typedef to describe the type of pixel. */ 117 using OutputImagePixelType = typename TOutputImage::PixelType; 118 using InputImagePixelType = typename TInputImage::PixelType; 119 120 /** Typedef to describe the output and input image index and size types. */ 121 using OutputImageIndexType = typename TOutputImage::IndexType; 122 using InputImageIndexType = typename TInputImage::IndexType; 123 using OutputImageSizeType = typename TOutputImage::SizeType; 124 using InputImageSizeType = typename TInputImage::SizeType; 125 126 typedef enum DirectionCollapseStrategyEnum { 127 DIRECTIONCOLLAPSETOUNKOWN=0, 128 DIRECTIONCOLLAPSETOIDENTITY=1, 129 DIRECTIONCOLLAPSETOSUBMATRIX=2, 130 DIRECTIONCOLLAPSETOGUESS=3 131 } DIRECTIONCOLLAPSESTRATEGY; 132 133 134 /** 135 * Set the strategy to be used to collapse physical space dimensions. 136 * 137 * itk::itkExtractImageFilter::DIRECTIONCOLLAPSETOIDENTITY 138 * Set the strategy so that all collapsed images have an identity direction. 139 * Use this strategy when you know that retention of the physical space 140 * orientation of the collapsed image is not important. 141 * 142 * itk::itkExtractImageFilter::DIRECTIONCOLLAPSETOGUESS 143 * Set the strategy so that all collapsed images where 144 * output direction is the sub-matrix if it is positive definite, else 145 * return identity. This is backwards compatible with ITKv3, but 146 * is highly discouraged because the results are difficult to 147 * anticipate under differing data scenerios. 148 * 149 * itk::itkExtractImageFilter::DIRECTIONCOLLAPSETOSUBMATRIX 150 * Set the strategy so that all collapsed images where 151 * output direction is the sub-matrix if it is positive definite, 152 * else throw an exception. Use this strategy when it is known 153 * that properly identified physical space sub-volumes can be 154 * reliably extracted from a higher dimensional space. For 155 * example when the application programmer knows that a 4D image 156 * is 3D+time, and that the 3D sub-space is properly defined. 157 */ SetDirectionCollapseToStrategy(const DIRECTIONCOLLAPSESTRATEGY choosenStrategy)158 void SetDirectionCollapseToStrategy(const DIRECTIONCOLLAPSESTRATEGY choosenStrategy) 159 { 160 switch(choosenStrategy) 161 { 162 case DIRECTIONCOLLAPSETOGUESS: 163 case DIRECTIONCOLLAPSETOIDENTITY: 164 case DIRECTIONCOLLAPSETOSUBMATRIX: 165 break; 166 case DIRECTIONCOLLAPSETOUNKOWN: 167 default: 168 itkExceptionMacro( << "Invalid Strategy Chosen for itk::ExtractImageFilter" ); 169 } 170 171 this->m_DirectionCollapseStrategy=choosenStrategy; 172 this->Modified(); 173 } 174 175 /** NOTE: The SetDirectionCollapseToUknown is explicitly not defined. 176 * It is a state that a filter can be in only when it is first instantiate 177 * prior to being initialized. 178 */ 179 180 /** 181 * Get the currently set strategy for collapsing directions of physical space. 182 */ GetDirectionCollapseToStrategy()183 DIRECTIONCOLLAPSESTRATEGY GetDirectionCollapseToStrategy() const 184 { 185 return this->m_DirectionCollapseStrategy; 186 } 187 188 /** \sa SetDirectionCollapseToStrategy */ SetDirectionCollapseToGuess()189 void SetDirectionCollapseToGuess() 190 { 191 this->SetDirectionCollapseToStrategy(DIRECTIONCOLLAPSETOGUESS); 192 } 193 194 /** \sa SetDirectionCollapseToStrategy */ SetDirectionCollapseToIdentity()195 void SetDirectionCollapseToIdentity() 196 { 197 this->SetDirectionCollapseToStrategy(DIRECTIONCOLLAPSETOIDENTITY); 198 } 199 200 /** \sa SetDirectionCollapseToStrategy */ SetDirectionCollapseToSubmatrix()201 void SetDirectionCollapseToSubmatrix() 202 { 203 this->SetDirectionCollapseToStrategy(DIRECTIONCOLLAPSETOSUBMATRIX); 204 } 205 206 207 /** ImageDimension enumeration */ 208 static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension; 209 static constexpr unsigned int OutputImageDimension = TOutputImage::ImageDimension; 210 211 using ExtractImageFilterRegionCopierType = ImageToImageFilterDetail::ExtractImageFilterRegionCopier< 212 Self::InputImageDimension, 213 Self::OutputImageDimension >; 214 215 /** Set/Get the output image region. 216 * If any of the ExtractionRegion.Size = 0 for any particular dimension dim, 217 * we have to collapse dimension dim. This means the output image will have 218 * 'c' dimensions less than the input image, where c = number of 219 * ExtractionRegion.Size = 0. */ 220 void SetExtractionRegion(InputImageRegionType extractRegion); 221 itkGetConstMacro(ExtractionRegion, InputImageRegionType); 222 223 #ifdef ITK_USE_CONCEPT_CHECKING 224 // Begin concept checking 225 itkConceptMacro( InputCovertibleToOutputCheck, 226 ( Concept::Convertible< InputImagePixelType, OutputImagePixelType > ) ); 227 // End concept checking 228 #endif 229 230 protected: 231 ExtractImageFilter(); 232 ~ExtractImageFilter() override = default; 233 void PrintSelf(std::ostream & os, Indent indent) const override; 234 235 /** ExtractImageFilter can produce an image which is a different 236 * resolution than its input image. As such, ExtractImageFilter 237 * needs to provide an implementation for 238 * GenerateOutputInformation() in order to inform the pipeline 239 * execution model. The original documentation of this method is 240 * below. 241 * 242 * \sa ProcessObject::GenerateOutputInformaton() */ 243 void GenerateOutputInformation() override; 244 245 /** This function calls the actual region copier to do the mapping from 246 * output image space to input image space. It uses a 247 * Function object used for dispatching to various routines to 248 * copy an output region (start index and size) to an input region. 249 * For most filters, this is a trivial copy because most filters 250 * require the input dimension to match the output dimension. 251 * However, some filters like itk::ExtractImageFilter can 252 * support output images of a lower dimension that the input. 253 * 254 * \sa ImageToImageFilter::CallCopyRegion() */ 255 void CallCopyOutputRegionToInputRegion(InputImageRegionType & destRegion, 256 const OutputImageRegionType & srcRegion) override; 257 258 /** ExtractImageFilter can be implemented as a multithreaded filter. 259 * Therefore, this implementation provides a DynamicThreadedGenerateData() 260 * routine which is called for each processing thread. The output 261 * image data is allocated automatically by the superclass prior to 262 * calling DynamicThreadedGenerateData(). DynamicThreadedGenerateData can only 263 * write to the portion of the output image specified by the 264 * parameter "outputRegionForThread" 265 * \sa ImageToImageFilter::ThreadedGenerateData(), 266 * ImageToImageFilter::GenerateData() */ 267 void DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override; 268 269 /** Overridden to check if there is no work to be done, before 270 * calling superclass' implementation. */ 271 void GenerateData() override; 272 273 InputImageRegionType m_ExtractionRegion; 274 275 OutputImageRegionType m_OutputImageRegion; 276 277 private: 278 DIRECTIONCOLLAPSESTRATEGY m_DirectionCollapseStrategy; 279 }; 280 } // end namespace itk 281 282 #ifndef ITK_MANUAL_INSTANTIATION 283 #include "itkExtractImageFilter.hxx" 284 #endif 285 286 #endif 287