GOFIGURE2  0.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
QGoSegmentationAlgo.h
Go to the documentation of this file.
1 /*=========================================================================
2  Authors: The GoFigure Dev. Team.
3  at Megason Lab, Systems biology, Harvard Medical school, 2009-11
4 
5  Copyright (c) 2009-11, President and Fellows of Harvard College.
6  All rights reserved.
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions are met:
10 
11  Redistributions of source code must retain the above copyright notice,
12  this list of conditions and the following disclaimer.
13  Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16  Neither the name of the President and Fellows of Harvard College
17  nor the names of its contributors may be used to endorse or promote
18  products derived from this software without specific prior written
19  permission.
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
26  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 =========================================================================*/
34 #ifndef __QGoSegmentationAlgo_h
35 #define __QGoSegmentationAlgo_h
36 
37 #include "QGoAlgorithmWidget.h"
38 #include "QGoGUILibConfigure.h"
39 #include "vtkSmartPointer.h"
40 #include "vtkPolyData.h"
41 #include "vtkImageData.h"
42 #include "QGoGUILibConfigure.h"
43 
44 // convert VTK to ITK
45 #include "itkImage.h"
46 #include "itkVTKImageImport.h"
47 #include "vtkImageExport.h"
48 #include "vtkitkAdaptor.h"
49 
50 // convert itk to vtk
52 
53 // extract 2d from 2d or 3d from 3d
54 #include "itkRegionOfInterestImageFilter.h"
55 
56 // extract 2d from 3d
57 #include "itkExtractImageFilter.h"
58 
59 // change info
60 #include "itkChangeInformationImageFilter.h"
61 
62 class GoImageProcessor;
63 
69 class QGOGUILIB_EXPORT QGoSegmentationAlgo:public QObject
70 {
71  Q_OBJECT
72 public:
73  explicit QGoSegmentationAlgo(QWidget *iParent = 0);
74  virtual ~QGoSegmentationAlgo();
75 
79  QGoAlgorithmWidget* GetAlgoWidget();
80 
84  /*virtual std::vector<vtkPolyData*> ApplyAlgo(
85  GoImageProcessor* iImages,
86  std::string iChannel,
87  bool iIsInvertedOn = false) = 0;*/
88 
89  /*
90  * \note Nicolas-shouldnt be public-move to protected
91  */
92  /*
93  * \brief Extract region of interest, given a bounding box and a list of vtk images
94  * \param[in] iBounds bounding box (xmin, xmax, ymin, ymax, zmin, zmax)
95  * \param[in] iImages vector of vtkimagedata
96  * \return list of roi
97  */
98  std::vector<vtkImageData*> VTKExtractROI(
99  const std::vector<double>& iBounds,
100  const std::vector< vtkSmartPointer< vtkImageData > >& iImages);
101  /*
102  * \brief Extract region of interest, given a bounding box and a vtk image
103  * \param[in] iBounds bounding box (xmin, xmax, ymin, ymax, zmin, zmax)
104  * \param[in] iImage vtkimagedata
105  * \return roi
106  */
107  vtkImageData* VTKExtractROI(
108  const std::vector<double>& iBounds,
109  const vtkSmartPointer< vtkImageData > & iImage);
110 
111  /*
112  * \brief Convert a vtkImage to a itkImage. If we call after "ExtractROI",
113  * the dimension should be 3 all the time.
114  * (Even if we extract a2D region from a 3d image)
115  * \tparam PixelType type of pixel (unsigned char, etc.)
116  * \tparam VImageDimension dimension of the image (2 or 3)
117  * \param[in] iInput Pointer to a vtkImageData
118  * \return Pointer to an itkImage
119  */
120  template< class PixelType, unsigned int VImageDimension >
121  typename itk::Image< PixelType, VImageDimension >::Pointer
122  ConvertVTK2ITK(vtkImageData *iInput)
123  {
124  // make sure there is an input
125  assert ( iInput );
126 
127  //Export VTK image to ITK
128  vtkSmartPointer<vtkImageExport> exporter =
129  vtkSmartPointer<vtkImageExport>::New();
130  exporter->SetInput(iInput);
131  exporter->Update();
132 
133  // ImageType
134  typedef itk::Image< PixelType, VImageDimension > ImageType;
135  // Import VTK Image to ITK
136  typedef itk::VTKImageImport< ImageType > ImageImportType;
137  typedef typename ImageImportType::Pointer ImageImportPointer;
138  ImageImportPointer importer = ImageImportType::New();
139 
140  ConnectPipelines< vtkImageExport, ImageImportPointer >(
141  exporter,
142  importer);
143 
144  typename ImageType::Pointer itkImage = importer->GetOutput();
145  itkImage->DisconnectPipeline();
146 
147  return itkImage;
148  }
149 
150  /*
151  * \brief Convert a itkImage to a vtkImage. If we call after "ExtractROI",
152  * the dimension should be 3 all the time.
153  * (Even if we extract a2D region from a 3d image)
154  * \tparam PixelType type of pixel (unsigned char, etc.)
155  * \tparam VImageDimension dimension of the image (2 or 3)
156  * \param[in] iInput Pointer to an itkImage
157  * \return Pointer to an vtkImageData
158  */
159  template< class PixelType, unsigned int VImageDimension >
160  vtkImageData*
161  ConvertITK2VTK(typename itk::Image< PixelType, VImageDimension >::Pointer iInput)
162  {
163  typedef itk::Image< PixelType, VImageDimension > InternalImageType;
165  typedef typename ConverterType::Pointer ConverterPointer;
166 
167  ConverterPointer converter = ConverterType::New();
168  converter->SetInput(iInput);
169 
170  try
171  {
172  converter->Update();
173  }
174  catch (itk::ExceptionObject & err)
175  {
176  std::cerr << "converter Exception:" << err << std::endl;
177  }
178 
179  vtkImageData* output_image = vtkImageData::New();
180  output_image->DeepCopy( converter->GetOutput() );
181 
182  return output_image;
183  }
184 
185  //-------------------------------------------------------------------------
186  template< class PixelType, unsigned int VImageDimension >
187  typename itk::Image< PixelType, VImageDimension >::Pointer
189  const std::vector< double > & iBounds,
190  typename itk::Image< PixelType, VImageDimension >::Pointer iInput )
191  {
192  typedef itk::Image< PixelType, VImageDimension > ImageType;
193  typedef typename ImageType::PointType ImagePointType;
194  typedef typename ImageType::IndexType ImageIndexType;
195  typedef typename ImageType::IndexValueType ImageIndexValueType;
196  typedef typename ImageType::SizeType ImageSizeType;
197  typedef typename ImageType::SizeValueType ImageSizeValueType;
198  typedef typename ImageType::RegionType ImageRegionType;
199  typedef typename ImageType::SpacingType ImageSpacingType;
200 
201  assert( iBounds.size() == 2 * VImageDimension );
202 
203  if ( iInput.IsNull() )
204  {
205  std::cerr << "iInput is Null" << std::endl;
206  }
207 
208  ImagePointType t_min, t_max;
209 
210  unsigned int k = 0;
211  for( unsigned int dim = 0; dim < VImageDimension; dim++ )
212  {
213  t_min[dim] = iBounds[k++];
214  t_max[dim] = iBounds[k++];
215  }
216 
217  ImageIndexType startOfROI, endOfROI;
218  iInput->TransformPhysicalPointToIndex( t_min, startOfROI );
219  iInput->TransformPhysicalPointToIndex( t_max, endOfROI );
220 
221  ImageSizeType sizeOfLargeImage =
222  iInput->GetLargestPossibleRegion().GetSize();
223 
224  ImageSizeType size;
225  size.Fill( 0 );
226 
227  for( unsigned int dim = 0; dim < VImageDimension; dim++ )
228  {
229  if( startOfROI[dim] < 0 )
230  {
231  startOfROI[dim] = 0;
232  }
233  if( static_cast< ImageSizeValueType >( startOfROI[dim] ) > sizeOfLargeImage[dim] )
234  {
235  startOfROI[dim] = sizeOfLargeImage[dim] - 1;
236  }
237 
238  if( endOfROI[dim] < 0 )
239  {
240  endOfROI[dim] = 0;
241  }
242  if( static_cast< ImageSizeValueType >( endOfROI[dim] ) > sizeOfLargeImage[dim] )
243  {
244  endOfROI[dim] = sizeOfLargeImage[dim] - 1;
245  }
246 
247  if( endOfROI[dim] - startOfROI[dim] < 0 )
248  {
249  size[dim] = 0;
250  }
251  else
252  {
253  size[dim] = endOfROI[dim] - startOfROI[dim];
254  }
255  }
256 
257  ImageRegionType region;
258  region.SetSize(size);
259  region.SetIndex(startOfROI);
260 
261  typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > ROIFilterType;
262  typedef typename ROIFilterType::Pointer ROIFilterPointer;
263 
264  ROIFilterPointer roi = ROIFilterType::New();
265  roi->SetInput(iInput);
266  roi->SetRegionOfInterest(region);
267  try
268  {
269  roi->Update();
270  }
271  catch (itk::ExceptionObject & err)
272  {
273  std::cerr << "roi Exception:" << err << std::endl;
274  }
275  return roi->GetOutput();
276  }
277 
278  template< class PixelType>
279  typename itk::Image< PixelType, 2>::Pointer
281  const std::vector< double > & iBounds,
282  typename itk::Image< PixelType, 3 >::Pointer iInput )
283  {
284  typedef itk::Image< PixelType, 3 > InputImageType;
285  typedef itk::Image< PixelType, 2 > OutputImageType;
286 
287  typedef typename InputImageType::PointType ImagePointType;
288  typedef typename InputImageType::IndexType ImageIndexType;
289  typedef typename InputImageType::IndexValueType ImageIndexValueType;
290  typedef typename InputImageType::SizeType ImageSizeType;
291  typedef typename InputImageType::SizeValueType ImageSizeValueType;
292  typedef typename InputImageType::RegionType ImageRegionType;
293  typedef typename InputImageType::SpacingType ImageSpacingType;
294 
295  typedef typename OutputImageType::PointType oImagePointType;
296  typedef typename OutputImageType::OffsetType oImageOffsetType;
297 
298  ImagePointType t_min, t_max;
299  oImagePointType new_origin;
300 
301  // create ROI
302  unsigned int k = 0;
303  for( unsigned int dim = 0; dim < 3; dim++ )
304  {
305  t_min[dim] = iBounds[k++];
306  t_max[dim] = iBounds[k++];
307  }
308 
309  ImageIndexType startOfROI, endOfROI;
310  iInput->TransformPhysicalPointToIndex( t_min, startOfROI );
311  iInput->TransformPhysicalPointToIndex( t_max, endOfROI );
312 
313  ImageSizeType sizeOfLargeImage =
314  iInput->GetLargestPossibleRegion().GetSize();
315 
316  ImageSizeType size;
317  size.Fill( 0 );
318 #ifdef ITKv4
319  oImageOffsetType new_offset;
320 #else
321  long int* new_offset = new long int[3];
322 #endif
323 
324 
325  int l = 0;
326 
327  for( unsigned int dim = 0; dim < 3; dim++ )
328  {
329  if( startOfROI[dim] < 0 )
330  {
331  startOfROI[dim] = 0;
332  }
333  if( static_cast< ImageSizeValueType >( startOfROI[dim] ) > sizeOfLargeImage[dim] )
334  {
335  startOfROI[dim] = sizeOfLargeImage[dim] - 1;
336  }
337 
338  if( endOfROI[dim] < 0 )
339  {
340  endOfROI[dim] = 0;
341  }
342  if( static_cast< ImageSizeValueType >( endOfROI[dim] ) > sizeOfLargeImage[dim] )
343  {
344  endOfROI[dim] = sizeOfLargeImage[dim] - 1;
345  }
346 
347  size[dim] = endOfROI[dim] - startOfROI[dim];
348 
349  if( size[dim] < 0 )
350  {
351  size[dim] = 0;
352  }
353 
354  // new origin
355  if( size[dim] > 0 )
356  {
357  new_origin[l] = t_min[dim];
358  double sizeTest = startOfROI[dim];
359  new_offset[l] = -sizeTest;
360  ++l;
361  }
362  }
363 
364  ImageRegionType region;
365  region.SetSize(size);
366  region.SetIndex(startOfROI);
367 
368  typedef itk::ExtractImageFilter< InputImageType, OutputImageType > FilterType;
369  typedef typename FilterType::Pointer FilterTypePointer;
370  FilterTypePointer filter = FilterType::New();
371  filter->SetExtractionRegion( region );
372  filter->SetInput( iInput );
373 #ifdef ITKv4
374  filter->SetDirectionCollapseToIdentity();
375 #endif
376 
377  try
378  {
379  filter->Update();
380  }
381  catch (itk::ExceptionObject & err)
382  {
383  std::cerr << "extract slice Exception:" << err << std::endl;
384  }
385 
386  // change information
387  typedef typename itk::ChangeInformationImageFilter<OutputImageType > CenterFilterType;
388  typedef typename CenterFilterType::Pointer CenterFilterTypePointer;
389 
390  CenterFilterTypePointer center = CenterFilterType::New();
391  center->SetInput(filter->GetOutput());
392  center->ChangeOriginOn();
393  center->SetOutputOrigin(new_origin);
394  center->ChangeRegionOn();
395  center->SetOutputOffset(new_offset);
396 
397  try
398  {
399  center->Update();
400  }
401  catch (itk::ExceptionObject & err)
402  {
403  std::cerr << "change information slice Exception:" << err << std::endl;
404  }
405  return center->GetOutput();
406  }
407 
408  /*
409  * \brief Generate list of polydata given a list of vtkimages and a threshold
410  * \param[in] iInputImage list of images
411  * \param[in] iThreshold threshold
412  * \return list of polydatas
413  */
414  std::vector<vtkPolyData*> ExtractPolyData(
415  std::vector<vtkImageData*>& iInputImage,
416  const double & iThreshold);
417  /*
418  * \brief Generate a polydata given a vtkimage and a threshold
419  * \param[in] iInputImage vtk image
420  * \param[in] iThreshold threshold
421  * \return polydata
422  */
423  vtkSmartPointer<vtkPolyData> ExtractPolyData(
424  vtkImageData *iInputImage,
425  const double & iThreshold);
426 
427  /*
428  * \brief Decimate a polydata
429  * \param[in] iPolyData polyData to be decimated
430  * \param[in] iNumberOfPoints target number of points
431  * \return Decimated polyData
432  */
433  vtkSmartPointer<vtkPolyData> DecimatePolyData(
434  vtkSmartPointer<vtkPolyData>& iPolyData,
435  const unsigned int& iNumberOfPoints);
436 
437  /*
438  * \brief Enable decimation during polydata extraction.
439  * \param[in] iDecimate yes (true), no (false)
440  */
441  void SetDecimate(bool& iDecimate);
442  /*
443  * \brief Is decimation enabled?
444  * \return true (yes), false (no)
445  */
446  bool GetDecimate();
447 
448  /*
449  * \brief Set target number of points for polydata extraction
450  * \param[in] iNumberOfPoints number of points
451  */
452  void SetNumberOfPoints( const unsigned int& iNumberOfPoints);
453  /*
454  * \brief Get target number of points for polydata extraction
455  * \return number of points
456  */
457  unsigned int GetNumberOfPoints() const;
458 
459 private:
460 
461  /*
462  * \brief Reconstruct a contour from a vtkImageData and a threshold
463  * \param[in] iInputImage vtkImageData
464  * \param[in] iThreshold threshold
465  * \return Pointer to a vtkPolyData
466  */
467  vtkSmartPointer<vtkPolyData> ExtractContour(
468  vtkSmartPointer<vtkImageData> iInputImage,
469  const double & iThreshold);
470 
471  /*
472  * \brief Reorganize points within a contour
473  * Required if we want to reedit this contour after.
474  * 1-reorganize
475  * \param[in] iInputImage vtkImageData
476  * \return Pointer to a vtkPolyData
477  */
478  vtkSmartPointer<vtkPolyData> ReorganizeContour(
479  vtkSmartPointer<vtkPolyData> iInputImage);
480 
481  /*
482  * \brief Reconstruct a mesh from a vtkImageData and a threshold
483  * \param[in] iInputImage vtkImageData
484  * \param[in] iThreshold threshold
485  * \return Pointer to a vtkPolyData
486  */
487  vtkSmartPointer<vtkPolyData> ExtractMesh(
488  vtkSmartPointer<vtkImageData> iInputImage,
489  const double & iThreshold);
490 
491  /*
492  * \brief Decimate a contour (line)
493  * \param[in] iPolyData polyData to be decimated
494  * \param[in] iNumberOfPoints target number of points
495  * \return Decimated polyData
496  */
497  vtkSmartPointer<vtkPolyData> DecimateContour(
498  vtkSmartPointer<vtkPolyData> iPolyData, unsigned int iNumberOfPoints);
499 
500  /*
501  * \brief Decimate a mesh
502  * \param[in] iPolyData polyData to be decimated
503  * \param[in] iNumberOfPoints target number of points
504  * \return Decimated polyData
505  */
506  vtkSmartPointer<vtkPolyData> DecimateMesh(
507  vtkSmartPointer<vtkPolyData> iPolyData, unsigned int iNumberOfPoints);
508 
510  unsigned int m_NumberOfPoints;
511 
512 protected:
514 
518  virtual void SetAlgoWidget(QWidget* iParent = 0) = 0;
519 
523  virtual void DeleteParameters() = 0;
524 
525  /*
526  * \todo Arnaud has something for itkimage to vtkpolydata in 3d
527  */
528  //add a method std::vector<PolyData*> ConvertITKImagesToPolyData(std::vector<itk::Image> iImages)
529  //add a method std::vector<TraceAttribut> GetAttribut(std::vector<vtkPolyData*> iNewTraces)
530  //add a method itkImage ConvertVTKToITK(vtkImageIData iImage)
531 };
532 
533 #endif
QGoAlgorithmWidget * m_AlgoWidget
abstract class to be the interface between the algorithms for meshes and contours and GoFigure ...
itk::Image< PixelType, VImageDimension >::Pointer ConvertVTK2ITK(vtkImageData *iInput)
Converts an ITK image into a VTK image and plugs a itk data pipeline to a VTK datapipeline.
itk::Image< PixelType, 2 >::Pointer ITKExtractSlice(const std::vector< double > &iBounds, typename itk::Image< PixelType, 3 >::Pointer iInput)
itk::Image< PixelType, VImageDimension >::Pointer ITKExtractROI(const std::vector< double > &iBounds, typename itk::Image< PixelType, VImageDimension >::Pointer iInput)
Interface between image reader and vtkImageData.
vtkImageData * ConvertITK2VTK(typename itk::Image< PixelType, VImageDimension >::Pointer iInput)