1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
5 - University of LYON http://www.universite-lyon.fr/
6 - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
7 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the copyright notices for more information.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ======================================================================-====*/
20 #include "clitkSetBackgroundImageFilter.h"
21 #include "clitkSliceBySliceRelativePositionFilter.h"
22 #include "clitkCropLikeImageFilter.h"
25 #include <itkConnectedComponentImageFilter.h>
26 #include <itkRelabelComponentImageFilter.h>
27 #include <itkBinaryThresholdImageFilter.h>
28 #include <itkPasteImageFilter.h>
30 //--------------------------------------------------------------------
31 template<class ImageType>
32 void clitk::ComputeBBFromImageRegion(typename ImageType::Pointer image,
33 typename ImageType::RegionType region,
34 typename itk::BoundingBox<unsigned long,
35 ImageType::ImageDimension>::Pointer bb) {
36 typedef typename ImageType::IndexType IndexType;
39 for(unsigned int i=0; i<image->GetImageDimension(); i++) {
40 firstIndex[i] = region.GetIndex()[i];
41 lastIndex[i] = firstIndex[i]+region.GetSize()[i];
44 typedef itk::BoundingBox<unsigned long,
45 ImageType::ImageDimension> BBType;
46 typedef typename BBType::PointType PointType;
49 image->TransformIndexToPhysicalPoint(firstIndex, firstPoint);
50 image->TransformIndexToPhysicalPoint(lastIndex, lastPoint);
52 bb->SetMaximum(lastPoint);
53 bb->SetMinimum(firstPoint);
55 //--------------------------------------------------------------------
58 //--------------------------------------------------------------------
59 template<int Dimension>
60 void clitk::ComputeBBIntersection(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo,
61 typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1,
62 typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2) {
64 typedef itk::BoundingBox<unsigned long, Dimension> BBType;
65 typedef typename BBType::PointType PointType;
69 for(unsigned int i=0; i<Dimension; i++) {
70 firstPoint[i] = std::max(bbi1->GetMinimum()[i],
71 bbi2->GetMinimum()[i]);
72 lastPoint[i] = std::min(bbi1->GetMaximum()[i],
73 bbi2->GetMaximum()[i]);
76 bbo->SetMaximum(lastPoint);
77 bbo->SetMinimum(firstPoint);
79 //--------------------------------------------------------------------
82 //--------------------------------------------------------------------
83 template<class ImageType>
84 void clitk::ComputeRegionFromBB(typename ImageType::Pointer image,
85 const typename itk::BoundingBox<unsigned long,
86 ImageType::ImageDimension>::Pointer bb,
87 typename ImageType::RegionType & region) {
89 typedef typename ImageType::IndexType IndexType;
90 typedef typename ImageType::PointType PointType;
91 typedef typename ImageType::RegionType RegionType;
92 typedef typename ImageType::SizeType SizeType;
94 // Region starting point
95 IndexType regionStart;
96 PointType start = bb->GetMinimum();
97 image->TransformPhysicalPointToIndex(start, regionStart);
101 PointType maxs = bb->GetMaximum();
102 PointType mins = bb->GetMinimum();
103 for(unsigned int i=0; i<ImageType::ImageDimension; i++) {
106 // DD((maxs[i] - mins[i])/image->GetSpacing()[i]);
107 regionSize[i] = lrint((maxs[i] - mins[i])/image->GetSpacing()[i]);
108 // DD(regionSize[i]);
112 region.SetIndex(regionStart);
113 region.SetSize(regionSize);
115 //--------------------------------------------------------------------
117 //--------------------------------------------------------------------
118 template<class ImageType, class TMaskImageType>
119 typename ImageType::Pointer
120 clitk::SetBackground(//typename ImageType::ConstPointer input,
121 const ImageType * input,
122 const TMaskImageType * mask,
123 typename TMaskImageType::PixelType maskBG,
124 typename ImageType::PixelType outValue) {
125 typedef clitk::SetBackgroundImageFilter<ImageType, TMaskImageType, ImageType> SetBackgroundImageFilterType;
126 typename SetBackgroundImageFilterType::Pointer setBackgroundFilter = SetBackgroundImageFilterType::New();
127 setBackgroundFilter->SetInput(input);
128 setBackgroundFilter->SetInput2(mask);
129 setBackgroundFilter->SetMaskValue(maskBG);
130 setBackgroundFilter->SetOutsideValue(outValue);
131 setBackgroundFilter->Update();
132 return setBackgroundFilter->GetOutput();
134 //--------------------------------------------------------------------
137 //--------------------------------------------------------------------
138 template<class ImageType>
139 int clitk::GetNumberOfConnectedComponentLabels(typename ImageType::Pointer input,
140 typename ImageType::PixelType BG,
141 bool isFullyConnected) {
142 // Connected Component label
143 typedef itk::ConnectedComponentImageFilter<ImageType, ImageType> ConnectFilterType;
144 typename ConnectFilterType::Pointer connectFilter = ConnectFilterType::New();
145 connectFilter->SetInput(input);
146 connectFilter->SetBackgroundValue(BG);
147 connectFilter->SetFullyConnected(isFullyConnected);
148 connectFilter->Update();
151 return connectFilter->GetObjectCount();
153 //--------------------------------------------------------------------
155 //--------------------------------------------------------------------
156 template<class ImageType>
157 typename ImageType::Pointer
158 clitk::Labelize(const ImageType * input,
159 typename ImageType::PixelType BG,
160 bool isFullyConnected,
161 int minimalComponentSize) {
162 // InternalImageType for storing large number of component
163 typedef itk::Image<int, ImageType::ImageDimension> InternalImageType;
165 // Connected Component label
166 typedef itk::ConnectedComponentImageFilter<ImageType, InternalImageType> ConnectFilterType;
167 typename ConnectFilterType::Pointer connectFilter = ConnectFilterType::New();
168 connectFilter->SetInput(input);
169 connectFilter->SetBackgroundValue(BG);
170 connectFilter->SetFullyConnected(isFullyConnected);
172 // Sort by size and remove too small area.
173 typedef itk::RelabelComponentImageFilter<InternalImageType, ImageType> RelabelFilterType;
174 typename RelabelFilterType::Pointer relabelFilter = RelabelFilterType::New();
175 relabelFilter->InPlaceOn();
176 relabelFilter->SetInput(connectFilter->GetOutput());
177 relabelFilter->SetMinimumObjectSize(minimalComponentSize);
178 relabelFilter->Update();
181 return relabelFilter->GetOutput();
183 //--------------------------------------------------------------------
186 //--------------------------------------------------------------------
187 template<class ImageType>
188 typename ImageType::Pointer
189 clitk::RemoveLabels(typename ImageType::Pointer input,
190 typename ImageType::PixelType BG,
191 std::vector<typename ImageType::PixelType> & labelsToRemove) {
192 typename ImageType::Pointer working_image = input;
193 for (unsigned int i=0; i <labelsToRemove.size(); i++) {
194 typedef clitk::SetBackgroundImageFilter<ImageType, ImageType> SetBackgroundImageFilterType;
195 typename SetBackgroundImageFilterType::Pointer setBackgroundFilter = SetBackgroundImageFilterType::New();
196 setBackgroundFilter->SetInput(input);
197 setBackgroundFilter->SetInput2(input);
198 setBackgroundFilter->SetMaskValue(labelsToRemove[i]);
199 setBackgroundFilter->SetOutsideValue(BG);
200 setBackgroundFilter->Update();
201 working_image = setBackgroundFilter->GetOutput();
203 return working_image;
205 //--------------------------------------------------------------------
208 //--------------------------------------------------------------------
209 template<class ImageType>
210 typename ImageType::Pointer
211 clitk::KeepLabels(const ImageType * input,
212 typename ImageType::PixelType BG,
213 typename ImageType::PixelType FG,
214 typename ImageType::PixelType firstKeep,
215 typename ImageType::PixelType lastKeep,
217 typedef itk::BinaryThresholdImageFilter<ImageType, ImageType> BinarizeFilterType;
218 typename BinarizeFilterType::Pointer binarizeFilter = BinarizeFilterType::New();
219 binarizeFilter->SetInput(input);
220 binarizeFilter->SetLowerThreshold(firstKeep);
221 if (useLastKeep) binarizeFilter->SetUpperThreshold(lastKeep);
222 binarizeFilter->SetInsideValue(FG);
223 binarizeFilter->SetOutsideValue(BG);
224 binarizeFilter->Update();
225 return binarizeFilter->GetOutput();
227 //--------------------------------------------------------------------
230 //--------------------------------------------------------------------
231 template<class ImageType>
232 typename ImageType::Pointer
233 clitk::LabelizeAndSelectLabels(typename ImageType::Pointer input,
234 typename ImageType::PixelType BG,
235 typename ImageType::PixelType FG,
236 bool isFullyConnected,
237 int minimalComponentSize,
238 LabelizeParameters<typename ImageType::PixelType> * param)
240 typename ImageType::Pointer working_image;
241 working_image = Labelize<ImageType>(input, BG, isFullyConnected, minimalComponentSize);
242 working_image = RemoveLabels<ImageType>(working_image, BG, param->GetLabelsToRemove());
243 working_image = KeepLabels<ImageType>(working_image,
245 param->GetFirstKeep(),
246 param->GetLastKeep(),
247 param->GetUseLastKeep());
248 return working_image;
250 //--------------------------------------------------------------------
253 //--------------------------------------------------------------------
254 template<class ImageType>
255 typename ImageType::Pointer
256 clitk::ResizeImageLike(typename ImageType::Pointer input,
257 typename ImageType::Pointer like,
258 typename ImageType::PixelType backgroundValue)
260 typedef clitk::CropLikeImageFilter<ImageType> CropFilterType;
261 typename CropFilterType::Pointer cropFilter = CropFilterType::New();
262 cropFilter->SetInput(input);
263 cropFilter->SetCropLikeImage(like);
264 cropFilter->SetBackgroundValue(backgroundValue);
265 cropFilter->Update();
266 return cropFilter->GetOutput();
268 //--------------------------------------------------------------------
271 //--------------------------------------------------------------------
272 template<class MaskImageType>
273 typename MaskImageType::Pointer
274 clitk::SliceBySliceRelativePosition(const MaskImageType * input,
275 const MaskImageType * object,
278 std::string orientation,
279 bool uniqueConnectedComponent,
283 typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
284 typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
285 sliceRelPosFilter->VerboseStepOff();
286 sliceRelPosFilter->WriteStepOff();
287 sliceRelPosFilter->SetInput(input);
288 sliceRelPosFilter->SetInputObject(object);
289 sliceRelPosFilter->SetDirection(direction);
290 sliceRelPosFilter->SetFuzzyThreshold(threshold);
291 sliceRelPosFilter->SetOrientationTypeString(orientation);
292 sliceRelPosFilter->SetResampleBeforeRelativePositionFilter((spacing != -1));
293 sliceRelPosFilter->SetIntermediateSpacing(spacing);
294 sliceRelPosFilter->SetUniqueConnectedComponentBySlice(uniqueConnectedComponent);
295 sliceRelPosFilter->SetNotFlag(notflag);
296 // sliceRelPosFilter->SetAutoCropFlag(true); ??
297 sliceRelPosFilter->Update();
298 return sliceRelPosFilter->GetOutput();
300 //--------------------------------------------------------------------
302 //--------------------------------------------------------------------
303 template<class SliceType>
304 typename SliceType::PointType
305 clitk::FindExtremaPointInAGivenDirection(const SliceType * input,
306 typename SliceType::PixelType bg,
309 typename SliceType::PointType point,
313 loop over input pixels, store the index in the fg that is max
314 according to the given direction.
316 typedef itk::ImageRegionConstIteratorWithIndex<SliceType> IteratorType;
317 IteratorType iter(input, input->GetLargestPossibleRegion());
319 typename SliceType::IndexType max = input->GetLargestPossibleRegion().GetIndex();
320 if (notFlag) max = max+input->GetLargestPossibleRegion().GetSize();
321 while (!iter.IsAtEnd()) {
322 if (iter.Get() != bg) {
323 bool test = iter.GetIndex()[direction] > max[direction];
324 if (notFlag) test = !test;
326 typename SliceType::PointType p;
327 input->TransformIndexToPhysicalPoint(iter.GetIndex(), p);
328 if ((distanceMax==0) || (p.EuclideanDistanceTo(point) < distanceMax)) {
329 max = iter.GetIndex();
335 typename SliceType::PointType p;
336 input->TransformIndexToPhysicalPoint(max, p);
339 //--------------------------------------------------------------------
341 //--------------------------------------------------------------------
342 template<class ImageType>
343 typename ImageType::Pointer
344 clitk::CropImageAlongOneAxis(typename ImageType::Pointer image,
345 int dim, double min, double max,
347 typename ImageType::PixelType BG)
349 // Compute region size
350 typename ImageType::RegionType region;
351 typename ImageType::SizeType size = image->GetLargestPossibleRegion().GetSize();
352 typename ImageType::PointType p = image->GetOrigin();
354 typename ImageType::IndexType start;
355 image->TransformPhysicalPointToIndex(p, start);
357 typename ImageType::IndexType end;
358 image->TransformPhysicalPointToIndex(p, end);
359 size[dim] = fabs(end[dim]-start[dim]);
360 region.SetIndex(start);
361 region.SetSize(size);
363 typedef itk::RegionOfInterestImageFilter<ImageType, ImageType> CropFilterType;
364 typename CropFilterType::Pointer cropFilter = CropFilterType::New();
365 cropFilter->SetInput(image);
366 cropFilter->SetRegionOfInterest(region);
367 cropFilter->Update();
368 typename ImageType::Pointer result = cropFilter->GetOutput();
371 result = clitk::AutoCrop<ImageType>(result, BG);
375 //--------------------------------------------------------------------