]> Creatis software - clitk.git/commitdiff
Merge branch 'master' of git.creatis.insa-lyon.fr:clitk
authorRomulo Pinho <romulo.pinho@lyon.unicancer.fr>
Mon, 5 Nov 2012 16:44:14 +0000 (17:44 +0100)
committerRomulo Pinho <romulo.pinho@lyon.unicancer.fr>
Mon, 5 Nov 2012 16:44:14 +0000 (17:44 +0100)
39 files changed:
common/CMakeLists.txt
common/clitkIO.cxx
common/clitkImageUtilities.h [deleted file]
common/clitkImageUtilities.txx [deleted file]
itk/clitkAutoCropFilter.txx
itk/clitkCropLikeImageFilter.txx
itk/clitkLabelImageOverlapMeasureFilter.h
itk/clitkLabelImageOverlapMeasureFilter.txx
itk/clitkSegmentationUtils.txx
itk/clitkSliceBySliceRelativePositionFilter.txx
segmentation/CMakeLists.txt
segmentation/clitkExtractLungFilter.txx
segmentation/clitkRegionGrowing.cxx [moved from common/clitkImageUtilities.cxx with 55% similarity]
segmentation/clitkRegionGrowing.ggo [new file with mode: 0644]
segmentation/clitkRegionGrowingGenericFilter.cxx [new file with mode: 0644]
segmentation/clitkRegionGrowingGenericFilter.h [new file with mode: 0644]
segmentation/clitkRegionGrowingGenericFilter.txx [new file with mode: 0644]
tools/clitkCropImageGenericFilter.cxx
tools/clitkImageStatistics.cxx
tools/clitkImageStatistics.ggo
tools/clitkImageStatisticsGenericFilter.cxx
tools/clitkImageStatisticsGenericFilter.h
tools/clitkImageStatisticsGenericFilter.txx
vv/CMakeLists.txt
vv/qt_ui/vvToolSegmentation.ui
vv/vvClipPolyData.cxx [new file with mode: 0644]
vv/vvClipPolyData.h [new file with mode: 0644]
vv/vvLandmarks.cxx
vv/vvLandmarks.h
vv/vvMainWindow.cxx
vv/vvROIActor.cxx
vv/vvSlicer.cxx
vv/vvSlicer.h
vv/vvSlicerManager.cxx
vv/vvSlicerManager.h
vv/vvSlicerManagerCommand.cxx
vv/vvToolROIManager.cxx
vv/vvToolSegmentation.cxx
vv/vvToolSegmentation.h

index 91f53e5f5dcabe35d3f3011ab3175dfa1a429429..76c19e6802bac93807ac73e3230f93118a6b7b0c 100644 (file)
@@ -39,6 +39,8 @@ IF(CLITK_PRIVATE_FEATURES)
     ${PROJECT_SOURCE_DIR}/private_features/clitkUsfImageIOFactory.cxx
     ${PROJECT_SOURCE_DIR}/private_features/clitkUSVoxImageIO.cxx
     ${PROJECT_SOURCE_DIR}/private_features/clitkUSVoxImageIOFactory.cxx
+    ${PROJECT_SOURCE_DIR}/private_features/clitkSvlImageIO.cxx
+    ${PROJECT_SOURCE_DIR}/private_features/clitkSvlImageIOFactory.cxx
     )
 ENDIF(CLITK_PRIVATE_FEATURES)
 
index cfa8e86ff994fa59492f9d95064a2cf7cc9c4a98..79aa9584cd8489de6645040901c41ddedf9d2d7e 100644 (file)
@@ -37,6 +37,7 @@
 #if CLITK_PRIVATE_FEATURES
   #include "clitkUsfImageIOFactory.h"
   #include "clitkUSVoxImageIOFactory.h"
+  #include "clitkSvlImageIOFactory.h"
 #endif
 
 //--------------------------------------------------------------------
@@ -46,6 +47,7 @@ void clitk::RegisterClitkFactories()
 #if CLITK_PRIVATE_FEATURES
   clitk::UsfImageIOFactory::RegisterOneFactory();
   clitk::USVoxImageIOFactory::RegisterOneFactory();
+  clitk::SvlImageIOFactory::RegisterOneFactory();
 #endif
   clitk::GateAsciiImageIOFactory::RegisterOneFactory();
   clitk::DicomRTDoseIOFactory::RegisterOneFactory();
diff --git a/common/clitkImageUtilities.h b/common/clitkImageUtilities.h
deleted file mode 100644 (file)
index ab12d21..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*=========================================================================
-  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
-
-  Authors belong to: 
-  - University of LYON              http://www.universite-lyon.fr/
-  - Léon Bérard cancer center       http://www.centreleonberard.fr
-  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
-
-  This software is distributed WITHOUT ANY WARRANTY; without even
-  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-  PURPOSE.  See the copyright notices for more information.
-
-  It is distributed under dual licence
-
-  - BSD        See included LICENSE.txt file
-  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
-===========================================================================**/
-#ifndef CLITKIMAGEUTILITIES_H
-#define CLITKIMAGEUTILITIES_H
-/**
- ===================================================================
- * @file   clitkImageUtilities.h
- * @author David Sarrut <David.Sarrut@creatis.insa-lyon.fr>
- * @date   22 Sep 2006 10:38:36
-
- * @brief  
-
- ===================================================================*/
-
-// clitk
-#include "clitkCommon.h"
-#include "clitkImageCommon.h"
-
-// std
-#include <vector>
-#include <map>
-#include <set>
-
-// itk
-#include "itkImageRegionConstIterator.h"
-
-namespace clitk {
-  
-  template<class ImageType>
-  int ComputeHowManyDifferentIntensity(const typename ImageType::Pointer & image, 
-                                                                          std::vector<typename ImageType::PixelType> & listOfIntensities);
-  #include "clitkImageUtilities.txx"
-
-} // end namespace
-
-#endif /* end #define CLITKIMAGEUTILITIES_H */
-
diff --git a/common/clitkImageUtilities.txx b/common/clitkImageUtilities.txx
deleted file mode 100644 (file)
index 8f42551..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*=========================================================================
-  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
-
-  Authors belong to:
-  - University of LYON              http://www.universite-lyon.fr/
-  - Léon Bérard cancer center       http://www.centreleonberard.fr
-  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
-
-  This software is distributed WITHOUT ANY WARRANTY; without even
-  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-  PURPOSE.  See the copyright notices for more information.
-
-  It is distributed under dual licence
-
-  - BSD        See included LICENSE.txt file
-  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
-===========================================================================**/
-#ifndef CLITKIMAGEUTILITIES_TXX
-#define CLITKIMAGEUTILITIES_TXX
-/**
- =================================================
- * @file   clitkImageUtilities.txx
- * @author David Sarrut <david.sarrut@creatis.insa-lyon.fr>
- * @date   22 Sep 2006 10:39:48
- *
- * @brief
- *
- *
- =================================================*/
-
-//====================================================================
-// Compute the number of different intensities in an image
-template<class ImageType>
-int ComputeHowManyDifferentIntensity(const typename ImageType::Pointer & image,
-                                     std::vector<typename ImageType::PixelType> & l)
-{
-  //std::set<typename ImageType::PixelType> listOfIntensities;
-  std::map<typename ImageType::PixelType, bool> listOfIntensities;
-  //  listOfIntensities.resize(0);
-  typedef itk::ImageRegionConstIterator<ImageType> ConstIteratorType;
-  ConstIteratorType pi(image, image->GetLargestPossibleRegion());
-  pi.Begin();
-  while (!pi.IsAtEnd()) {
-    if (!listOfIntensities[pi.Get()]) listOfIntensities[pi.Get()] = true;
-    // if (std::find(listOfIntensities.begin(),
-//                               listOfIntensities.end(),
-//                               pi.Get()) == listOfIntensities.end()) {
-//       listOfIntensities.insert(pi.Get());
-//     }
-    ++pi;
-  }
-
-  //typename std::set<typename ImageType::PixelType>::const_iterator ppi = listOfIntensities.begin();
-  typename std::map<typename ImageType::PixelType, bool>::const_iterator ppi = listOfIntensities.begin();
-  while (ppi != listOfIntensities.end()) {
-    l.push_back(ppi->first);
-    ++ppi;
-  }
-
-  return listOfIntensities.size();
-}
-//====================================================================
-
-//====================================================================
-template<class InputImageType, class MaskImageType>
-void ComputeWeightsOfEachClasses(const typename InputImageType::Pointer & input,
-                                 const typename MaskImageType::Pointer & mask,
-                                 const std::vector<typename MaskImageType::PixelType> & listOfIntensities,
-                                 std::map<typename MaskImageType::PixelType,
-                                 std::map<typename InputImageType::PixelType, double> > & mapOfLabelsAndWeights)
-{
-  // Check size
-  if (input->GetLargestPossibleRegion() != mask->GetLargestPossibleRegion()) {
-    itkGenericExceptionMacro(<< "Input and mask images have not the same size"
-                             << std::endl
-                             << "Input = " << input->GetLargestPossibleRegion()
-                             << std::endl
-                             << "Mask = " << mask->GetLargestPossibleRegion());
-  }
-
-  // reset weights list
-  mapOfLabelsAndWeights.clear();
-
-  // loop
-  typedef itk::ImageRegionConstIterator<InputImageType> ConstInputIteratorType;
-  ConstInputIteratorType pi(input, input->GetLargestPossibleRegion());
-  typedef itk::ImageRegionConstIterator<MaskImageType> ConstMaskIteratorType;
-  ConstMaskIteratorType pm(mask, mask->GetLargestPossibleRegion());
-  pi.Begin();
-  pm.Begin();
-  while (!pi.IsAtEnd()) {
-    mapOfLabelsAndWeights[pm.Get()][pi.Get()]++;
-    ++pi;
-    ++pm;
-  }
-}
-//====================================================================
-
-// //====================================================================
-// template<class ImageType>
-// typename ImageType::Pointer NewImage3D(int x, int y, int z, float dx, float dy, float dz) {
-//   typename ImageType::Pointer output = ImageType::New();
-//   typename ImageType::RegionType region;
-//   typename ImageType::SizeType size;
-//   size[0] = x;
-//   size[1] = y;
-//   size[2] = z;
-//   region.SetSize(size);
-//   output->SetRegions(region);
-//   output->Allocate();
-//   typename ImageType::SpacingType spacing;
-//   spacing[0] = dx;
-//   spacing[1] = dy;
-//   spacing[2] = dz;
-//   output->SetSpacing(spacing);
-//   return output;
-// }
-// //====================================================================
-
-
-#endif /* end #define CLITKIMAGEUTILITIES_TXX */
-
index 71f9ab08b0f07e93e3c3ec3495cef208e104c563..e31e424d43bb2ce99d25889edf74b25464aa048b 100644 (file)
@@ -97,8 +97,9 @@ namespace clitk {
     autoCropFilter->SetInput(imageToLabelFilter->GetOutput());
     //    autoCropFilter->ReleaseDataFlagOff(); 
     if (GetUseBorder()) {
-      DD("UseBorder seems buggy ?");
-      exit(0);
+      DD("Crop UseBorder : not correctly implemented do not use (use PadLabelMapFilter)");
+      // http://www.itk.org/Doxygen/html/classitk_1_1AutoCropLabelMapFilter.html#a54f49fdff8d9f2d2313134109d510285
+      exit(0); 
       typename ImageType::SizeType s;
       for(uint i=0; i<ImageType::ImageDimension; i++) s[i] = 1;
       autoCropFilter->SetCropBorder(s);
index 519c5fd4e6a8f3015112e081c152dc4c9844f595..6399ec6ac7e5419ca870e6e7cd61bf6b072810ef 100644 (file)
@@ -269,7 +269,10 @@ clitk::ResizeImageLike(const ImageType * input,
 {
   typename ImageType::Pointer output = ImageType::New();
   output->CopyInformation(input);
-  output->SetRegions(region);
+  typename ImageType::RegionType reg;
+  reg.SetIndex(region->GetIndex());
+  reg.SetSize(region->GetSize());
+  output->SetRegions(reg);
   output->Allocate();
   return clitk::ResizeImageLike<ImageType>(input, output, backgroundValue);
 }
index 17581f633ad9bb94d815b1e549ca19615dabaa58..17b7c21fce67e7f95f5b44e004d4e598caeda384 100644 (file)
@@ -29,6 +29,8 @@
 #include <itkImageToImageFilter.h>
 #include <itkLabelStatisticsImageFilter.h>
 
+#include <iomanip>
+
 namespace clitk {
   
   //--------------------------------------------------------------------
index 57516bb41634db8996e3822aa0d91ad748b2c110..a29aa6a3f810eb1987a8adbd2f62b82bc7d1e4a2 100644 (file)
@@ -121,8 +121,13 @@ GenerateData()
   statFilter->Update();
   int in2 = statFilter->GetCount(GetLabel1());
 
-  std::cout << in1 << " " << in2 << " " << inter << " " << u << " " 
-            << 2.0*(double)inter/(double)(in1+in2) << std::endl;
+  double dice = 2.0*(double)inter/(double)(in1+in2);
+  int width = 6;
+  std::cout << std::setw(width) << in1 << " "
+            << std::setw(width) << in2 << " "
+            << std::setw(width) << inter  << " "
+            << std::setw(width) << u  << " "
+            << std::setw(width) << dice << " "; //std::endl;
 }
 //--------------------------------------------------------------------
 
index b7a5de50693c5f078b19ea2245076f3c384c4657..a57d8136becb4b919b1b1bc9360f6343c6547028 100644 (file)
@@ -1321,11 +1321,11 @@ namespace clitk {
       // Compute dmap for S1 *TO PUT IN FONCTION*
       dmap = clitk::DistanceMap<SliceType>(slices_s1[i], BG);
       dmaps1.push_back(dmap);
-      writeImage<FloatImageType>(dmap, "dmap1.mha");
+      //writeImage<FloatImageType>(dmap, "dmap1.mha");
       // Compute dmap for S2
       dmap = clitk::DistanceMap<SliceType>(slices_s2[i], BG);
       dmaps2.push_back(dmap);
-      writeImage<FloatImageType>(dmap, "dmap2.mha");
+      //writeImage<FloatImageType>(dmap, "dmap2.mha");
       
       // Look in S2 for the point the closest to S1
       typename SliceType::PointType p = ComputeClosestPoint<SliceType>(slices_s1[i], dmaps2[i], BG);
index db3c677c0e8701c2a424676fcd72117e26576b12..e68514da031c0f6f1a6725a2df78f97d0c189fe7 100644 (file)
@@ -78,7 +78,7 @@ clitk::SliceBySliceRelativePositionFilter<ImageType>::
 PrintOptions(std::ostream & os) 
 {
   os << "Slice direction = " << this->GetDirection() << std::endl
-     << "BG value        = " << this->GetBackgroundValue() << std::endl;
+     << "BG value        = " << (int)this->GetBackgroundValue() << std::endl;
   for(int i=0; i<this->GetNumberOfAngles(); i++) {
     os << "Orientation     = " << this->GetOrientationTypeString()[i] << std::endl;
     os << "Angles     = " << clitk::rad2deg(this->GetAngle1InRad(i)) 
index e5ec8d4ca01dcbe5943aa104ad871bac9fa1bb70..f26ec74c203d0ee38e5df3dba5192b250d459a44 100644 (file)
@@ -1,7 +1,7 @@
 #=========================================================
 
 # Add Libraries used in vv and clitk to avoid recompilation
-FOREACH(clitkTool clitkExtractLung clitkExtractPatient)
+FOREACH(clitkTool clitkExtractLung clitkExtractPatient clitkConnectedComponentLabeling clitkRegionGrowing)
     WRAP_GGO(${clitkTool}_GGO_C ${clitkTool}.ggo)
     SET(GGO_C_FILES ${GGO_C_FILES} ${${clitkTool}_GGO_C})
 ENDFOREACH(clitkTool)
@@ -46,6 +46,10 @@ IF(CLITK_BUILD_SEGMENTATION)
     TARGET_LINK_LIBRARIES(clitkMotionMask clitkCommon ${ITK_LIBRARIES})
     SET(SEGMENTATION_INSTALL ${SEGMENTATION_INSTALL} clitkMotionMask)
     
+    WRAP_GGO(clitkRegionGrowing_GGO_C clitkRegionGrowing.ggo)
+    ADD_EXECUTABLE(clitkRegionGrowing clitkRegionGrowing.cxx ${clitkRegionGrowing_GGO_C} ${clitkRelativePosition_GGO_C})
+    TARGET_LINK_LIBRARIES(clitkRegionGrowing clitkCommon ${ITK_LIBRARIES})
+
     SET_TARGET_PROPERTIES(${SEGMENTATION_INSTALL} PROPERTIES INSTALL_RPATH "${VTK_DIR}:${ITK_DIR}" )  
     INSTALL (TARGETS ${SEGMENTATION_INSTALL} DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE)
 
index ffca1df50276062599cbcd22e76666cc25ce9a07..f84a0956fb61d1bc48cf202c5481267e132bf2cd 100644 (file)
@@ -47,6 +47,8 @@
 #include "itkOrientImageFilter.h"
 #include "itkSpatialOrientationAdapter.h"
 #include "itkImageDuplicator.h"
+#include "itkRelabelComponentImageFilter.h"
+
 #include <fcntl.h>
 
 //--------------------------------------------------------------------
@@ -67,6 +69,7 @@ ExtractLungFilter():
   SetForegroundValue(1);
   SetMinimalComponentSize(100);
   VerboseRegionGrowingFlagOff();
+  RemoveSmallLabelBeforeSeparationFlagOn();
 
   // Step 1 default values
   SetUpperThreshold(-300);
@@ -436,7 +439,7 @@ GenerateOutputInformation()
     //--------------------------------------------------------------------
     //--------------------------------------------------------------------
     StartNewStep("Separate Left/Right lungs");
-      PrintMemory(GetVerboseMemoryFlag(), "Before Separate");
+    PrintMemory(GetVerboseMemoryFlag(), "Before Separate");
     // Initial label
     working_mask = Labelize<MaskImageType>(working_mask, 
                                           GetBackgroundValue(), 
@@ -451,9 +454,33 @@ GenerateOutputInformation()
     statisticsImageFilter->SetInput(working_mask);
     statisticsImageFilter->Update();
     unsigned int initialNumberOfLabels = statisticsImageFilter->GetMaximum();
-    working_mask = statisticsImageFilter->GetOutput(); 
-    
+    working_mask = statisticsImageFilter->GetOutput();     
     PrintMemory(GetVerboseMemoryFlag(), "After count label");
+
+    // If already 2 labels, but a too big differences, remove the
+    // smalest one (sometimes appends with the stomach
+    if (initialNumberOfLabels >1) {
+      if (GetRemoveSmallLabelBeforeSeparationFlag()) {
+        DD(GetRemoveSmallLabelBeforeSeparationFlag());
+        typedef itk::RelabelComponentImageFilter<MaskImageType, MaskImageType> RelabelFilterType;
+        typename RelabelFilterType::Pointer relabelFilter = RelabelFilterType::New();
+        relabelFilter->SetInput(working_mask);
+        relabelFilter->SetMinimumObjectSize(10);
+        relabelFilter->Update();
+        const std::vector<float> & a = relabelFilter->GetSizeOfObjectsInPhysicalUnits();
+        std::vector<MaskImagePixelType> remove_label;
+        for(unsigned int i=1; i<a.size(); i++) {
+          if (a[i] < 0.5*a[0]) { // more than 0.5 difference
+            remove_label.push_back(i+1); // label zero is BG
+          }
+        }
+        working_mask = 
+          clitk::RemoveLabels<MaskImageType>(working_mask, GetBackgroundValue(), remove_label);
+        statisticsImageFilter->SetInput(working_mask);
+        statisticsImageFilter->Update();
+        initialNumberOfLabels = statisticsImageFilter->GetMaximum();
+      }
+    }
   
     // Decompose the first label
     if (initialNumberOfLabels<2) {
similarity index 55%
rename from common/clitkImageUtilities.cxx
rename to segmentation/clitkRegionGrowing.cxx
index eb3d1bcd792ee870aff9e7e6c745c09657d9e550..d24d2f72d9f3ec21ec4eb6708a0f4c297eac8519 100644 (file)
@@ -1,7 +1,7 @@
 /*=========================================================================
   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
 
-  Authors belong to:
+  Authors belong to: 
   - University of LYON              http://www.universite-lyon.fr/
   - Léon Bérard cancer center       http://www.centreleonberard.fr
   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
   - BSD        See included LICENSE.txt file
   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
 ===========================================================================**/
-#ifndef CLITKIMAGEUTILITIES_CXX
-#define CLITKIMAGEUTILITIES_CXX
-/**
- =================================================
- * @file   clitkImageUtilities.cxx
- * @author David Sarrut <david.sarrut@creatis.insa-lyon.fr>
- * @date   22 Sep 2006 10:39:40
- *
- * @brief
- *
- *
- =================================================*/
-
-#include "clitkImageUtilities.h"
-
-#endif /* end #define CLITKIMAGEUTILITIES_CXX */
 
+// clitk
+#include "clitkRegionGrowing_ggo.h"
+#include "clitkIO.h"
+#include "clitkRegionGrowingGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkRegionGrowing, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::RegionGrowingGenericFilter<args_info_clitkRegionGrowing> FilterType;
+  FilterType::Pointer genericFilter = FilterType::New();
+  
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/segmentation/clitkRegionGrowing.ggo b/segmentation/clitkRegionGrowing.ggo
new file mode 100644 (file)
index 0000000..cd2d03e
--- /dev/null
@@ -0,0 +1,34 @@
+#File clitkRegionGrowing.ggo
+package "clitkRegionGrowing"
+version "1.0"
+purpose "Region growing from a seed point using various types of conditions to control the growing"
+
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+section "I/O"
+
+option "input"         i       "Input image filename"            string        yes
+option "output"        o       "Output image filename"           string        yes
+
+
+section "Parameters"
+
+option "type"          t       "Region growing filter type: 0=threshold , 1=neighborhood-threshold , 2=confidence , 3= locally-adaptive-threshold, 4= explosion-controlled-threshold" int      no      default="0"
+option "lower"         l       "1,2,3,4: Lower threshold value"                  double        no      default="310"
+option "upper"         u       "1,2,3,4: Upper threshold value"                  double        no      default="4000"
+option "maxUpper"      -       "4: Maximum upper threshold value"                double        no      default="2000"
+option "minLower"      -       "4: Minimum lower threshold value"                double        no      default="-1000"
+option "step"          -       "4: Threshold step size"                          double        no      default="64.0"
+option "minStep"       -       "4: Minimum threshold step size"                  double        no      default="1"
+option "adaptLower"    -       "3,4: (locally) adapt lower thresholding"         flag          off
+option "adaptUpper"    -       "3,4: (locally) adapt upper thresholding"         flag          off
+option "multiplier"            m       "2-4: (2-3) accept if within mean+-mutiplier*SD, (4) explosion if size increases multiplier times"      double  no      default="2.0"
+option "seed"          s       "Seed index postion (in voxels)"                  int           multiple        no      default="0"     
+option "seedRadius"            -       "Radius used for seed dilatation(in voxel)"       int           multiple        no      default="0"     
+option "pad"           p       "The replace padding value"                       double        no              default="1.0"   
+option "radius"        r       "1-3: The radius of the neighborhood"             int           no              multiple        default="1"
+option "maxSD"         -       "3: Limit to SD"                                  double        no       
+option "full"          -       "4: use full connectivity (not implemented yet)"  flag          off      
+option "iter"          -       "2: Iterations"                                   int           no      default="5"
+                
diff --git a/segmentation/clitkRegionGrowingGenericFilter.cxx b/segmentation/clitkRegionGrowingGenericFilter.cxx
new file mode 100644 (file)
index 0000000..f5092ba
--- /dev/null
@@ -0,0 +1,72 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+#ifndef clitkRegionGrowingGenericFilter_cxx
+#define clitkRegionGrowingGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkRegionGrowingGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkRegionGrowingGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  RegionGrowingGenericFilter::RegionGrowingGenericFilter()
+  {
+    m_Verbose=false;
+    m_InputFileName="";
+  }
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void RegionGrowingGenericFilter::Update()
+  {
+    // Read the Dimension and PixelType
+    int Dimension;
+    std::string PixelType;
+    ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType);
+
+    
+    // Call UpdateWithDim
+    if(Dimension==2) UpdateWithDim<2>(PixelType);
+    else if(Dimension==3) UpdateWithDim<3>(PixelType);
+    // else if (Dimension==4)UpdateWithDim<4>(PixelType); 
+    else 
+      {
+       std::cout<<"Error, Only for 2 or 3  Dimensions!!!"<<std::endl ;
+       return;
+      }
+  }
+
+
+} //end clitk
+
+#endif  //#define clitkRegionGrowingGenericFilter_cxx
diff --git a/segmentation/clitkRegionGrowingGenericFilter.h b/segmentation/clitkRegionGrowingGenericFilter.h
new file mode 100644 (file)
index 0000000..225619d
--- /dev/null
@@ -0,0 +1,76 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+
+#ifndef CLITKREGIONGROWINGGENERICFILTER_H
+#define CLITKREGIONGROWINGGENERICFILTER_H
+
+// clitk include
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkLocallyAdaptiveThresholdConnectedImageFilter.h"
+#include "clitkExplosionControlledThresholdConnectedImageFilter.h"
+
+//itk include
+#include "itkLightObject.h"
+#include "itkConnectedThresholdImageFilter.h"
+#include "itkNeighborhoodConnectedImageFilter.h"
+#include "itkConfidenceConnectedImageFilter.h"
+#include "itkConfidenceConnectedImageFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk 
+{
+  template<class ArgsInfoType>
+  class ITK_EXPORT RegionGrowingGenericFilter: 
+    public ImageToImageGenericFilter<RegionGrowingGenericFilter<ArgsInfoType> >
+  {
+
+  public:
+    //----------------------------------------
+    RegionGrowingGenericFilter();
+
+    //----------------------------------------
+    typedef RegionGrowingGenericFilter         Self;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    //----------------------------------------
+    itkNewMacro(Self);  
+    itkTypeMacro( RegionGrowingGenericFilter, LightObject );
+
+    //--------------------------------------------------------------------
+    void SetArgsInfo(const ArgsInfoType & a);
+
+    //--------------------------------------------------------------------
+    // Main function called each time the filter is updated
+    template<class ImageType>  
+    void UpdateWithInputImageType();
+
+  protected:
+    void Modified() {} // Need for using itkMacros
+    template<unsigned int Dim> void InitializeImageType();
+    ArgsInfoType mArgsInfo;
+
+  }; // end class
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkRegionGrowingGenericFilter.txx"
+#endif
+
+#endif // #define CLITKREGIONGROWINGGENERICFILTER_H
diff --git a/segmentation/clitkRegionGrowingGenericFilter.txx b/segmentation/clitkRegionGrowingGenericFilter.txx
new file mode 100644 (file)
index 0000000..e8f3653
--- /dev/null
@@ -0,0 +1,300 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+#ifndef CLITKREGIONGROWINGGENERICFILTER_TXX
+#define CLITKREGIONGROWINGGENERICFILTER_TXX
+
+#include <itkBinaryBallStructuringElement.h>
+#include <itkConstShapedNeighborhoodIterator.h>
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::RegionGrowingGenericFilter<ArgsInfoType>::RegionGrowingGenericFilter():
+  ImageToImageGenericFilter<Self>("RegionGrowing") 
+{
+  InitializeImageType<2>();
+  InitializeImageType<3>();
+  //InitializeImageType<4>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::RegionGrowingGenericFilter<ArgsInfoType>::InitializeImageType() 
+{  
+  ADD_IMAGE_TYPE(Dim, uchar);
+  ADD_IMAGE_TYPE(Dim, short);
+  // ADD_IMAGE_TYPE(Dim, int);
+  ADD_IMAGE_TYPE(Dim, float);
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::RegionGrowingGenericFilter<ArgsInfoType>::SetArgsInfo(const ArgsInfoType & a) 
+{
+  mArgsInfo=a;
+  this->SetIOVerbose(mArgsInfo.verbose_flag);
+  if (mArgsInfo.input_given)   this->AddInputFilename(mArgsInfo.input_arg);
+  if (mArgsInfo.output_given)  this->SetOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::RegionGrowingGenericFilter<ArgsInfoType>::UpdateWithInputImageType() 
+{ 
+  DD("UpdateWithInputImageType");
+  const int Dimension = ImageType::ImageDimension;
+
+  // ImageTypes
+  typedef ImageType InputImageType;
+  typedef ImageType OutputImageType;
+  typedef typename ImageType::PixelType PixelType;
+    
+  // Reading input
+  typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
+
+  // Seed
+  typedef typename  std::vector<typename InputImageType::IndexType> SeedsType;
+  SeedsType seeds(1);
+  if (mArgsInfo.seed_given==Dimension)
+    for (unsigned int i=0; i<Dimension;i++)
+      seeds[0][i]=mArgsInfo.seed_arg[i];
+    
+  else if ( mArgsInfo.seed_given==1)
+    seeds[0].Fill(mArgsInfo.seed_arg[0]);
+    
+  else seeds[0].Fill(mArgsInfo.seed_arg[0]);
+  if (mArgsInfo.verbose_flag) std::cout<<"Setting seed seeds to "<<seeds[0]<<"..."<<std::endl;
+
+  if (mArgsInfo.seedRadius_given)
+    {
+      typedef itk::BinaryBallStructuringElement<PixelType, Dimension> BallType;
+      typename BallType::RadiusType r;
+
+      if (mArgsInfo.seedRadius_given == Dimension)
+        for (unsigned i = 0; i < Dimension; i++)
+          r[i] = mArgsInfo.seedRadius_arg[i];
+      else
+        r.Fill(mArgsInfo.seedRadius_arg[0]);
+
+      BallType ball;
+      ball.SetRadius(r);
+      ball.CreateStructuringElement();
+
+      typedef itk::ConstShapedNeighborhoodIterator<InputImageType> IteratorType;
+      IteratorType it(ball.GetRadius(),
+                      input,
+                      input->GetLargestPossibleRegion());
+#if ITK_VERSION_MAJOR < 4
+      typename BallType::ConstIterator nit;
+      unsigned idx = 0;
+      for (nit = ball.Begin(); nit != ball.End(); ++nit, ++idx)
+        {
+          if (*nit)
+            {
+              it.ActivateOffset(it.GetOffset(idx));
+            }
+          else
+            {
+              it.DeactivateOffset(it.GetOffset(idx));
+            }
+        }
+#else
+      it.CreateActiveListFromNeighborhood(ball);
+      it.NeedToUseBoundaryConditionOff();
+#endif
+
+      it.SetLocation(seeds[0]);
+      for (typename IteratorType::ConstIterator i = it.Begin(); !i.IsAtEnd(); ++i)
+        {
+          typename InputImageType::IndexType id = seeds[0] + i.GetNeighborhoodOffset();
+          if (id != seeds[0] && input->GetLargestPossibleRegion().IsInside(id))
+            seeds.push_back(id);
+        }
+    }
+
+  // Filter
+  typedef itk::ImageToImageFilter<InputImageType, OutputImageType> ImageToImageFilterType;
+  typename ImageToImageFilterType::Pointer filter;
+
+  switch (mArgsInfo.type_arg)
+    {
+    case 0: {
+               
+      typedef itk::ConnectedThresholdImageFilter<InputImageType, OutputImageType> ImageFilterType;
+      typename ImageFilterType::Pointer f= ImageFilterType::New();
+       
+      f->SetLower(mArgsInfo.lower_arg);
+      f->SetUpper(mArgsInfo.upper_arg);
+      f->SetReplaceValue(static_cast<PixelType>(mArgsInfo.pad_arg));
+      for (typename SeedsType::const_iterator it = seeds.begin(); it != seeds.end(); ++it)
+        f->AddSeed(*it);
+      filter=f;
+      if (mArgsInfo.verbose_flag) std::cout<<"Using the connected threshold image filter..."<<std::endl;
+
+      break;
+    }
+
+    case 1: {
+               
+      typedef itk::NeighborhoodConnectedImageFilter<InputImageType, OutputImageType> ImageFilterType;
+      typename ImageFilterType::Pointer f= ImageFilterType::New();
+       
+      // Radius
+      typename  InputImageType::SizeType size;
+      if (mArgsInfo.radius_given==Dimension)
+        for (unsigned int i=0; i<Dimension;i++)
+          size[i]=mArgsInfo.radius_arg[i];
+       
+      else if ( mArgsInfo.radius_given==1)
+        size.Fill(mArgsInfo.radius_arg[0]);
+       
+      else size.Fill(mArgsInfo.radius_arg[0]);
+      if (mArgsInfo.verbose_flag) std::cout<<"Setting neighborhood radius to "<<size<<"..."<<std::endl;
+
+      f->SetLower(mArgsInfo.lower_arg);
+      f->SetUpper(mArgsInfo.upper_arg);
+      f->SetReplaceValue(static_cast<PixelType>(mArgsInfo.pad_arg));
+      for (typename SeedsType::const_iterator it = seeds.begin(); it != seeds.end(); ++it)
+        f->AddSeed(*it);
+      f->SetRadius(size);
+      filter=f;
+      if (mArgsInfo.verbose_flag) std::cout<<"Using the neighborhood threshold connected image filter..."<<std::endl;
+
+      break;
+    }
+
+    case 2: {
+       
+      typedef itk::ConfidenceConnectedImageFilter<InputImageType, OutputImageType> ImageFilterType;
+      typename ImageFilterType::Pointer f= ImageFilterType::New();
+       
+      // Radius
+      typename  InputImageType::SizeType size;
+      if (mArgsInfo.radius_given==Dimension)
+        for (unsigned int i=0; i<Dimension;i++)
+          size[i]=mArgsInfo.radius_arg[i];
+       
+      else if ( mArgsInfo.radius_given==1)
+        size.Fill(mArgsInfo.radius_arg[0]);
+       
+      else size.Fill(mArgsInfo.radius_arg[0]);
+      if (mArgsInfo.verbose_flag) std::cout<<"Setting neighborhood radius to "<<size<<"..."<<std::endl;
+
+      f->SetMultiplier( mArgsInfo.multiplier_arg );
+      f->SetNumberOfIterations( mArgsInfo.multiplier_arg );
+      for (typename SeedsType::const_iterator it = seeds.begin(); it != seeds.end(); ++it)
+        f->AddSeed(*it);
+      f->SetNumberOfIterations( mArgsInfo.iter_arg);
+      f->SetReplaceValue(static_cast<PixelType>(mArgsInfo.pad_arg));
+      f->SetInitialNeighborhoodRadius(size[0]);
+      filter=f;
+      if (mArgsInfo.verbose_flag) std::cout<<"Using the confidence threshold connected image filter..."<<std::endl;
+       
+      break;
+    }
+
+    case 3: {
+               
+      typedef clitk::LocallyAdaptiveThresholdConnectedImageFilter<InputImageType, OutputImageType> ImageFilterType;
+      typename ImageFilterType::Pointer f= ImageFilterType::New();
+       
+      // Radius
+      typename  InputImageType::SizeType size;
+      if (mArgsInfo.radius_given==Dimension)
+        for (unsigned int i=0; i<Dimension;i++)
+          size[i]=mArgsInfo.radius_arg[i];
+      else size.Fill(mArgsInfo.radius_arg[0]);
+      if (mArgsInfo.verbose_flag) std::cout<<"Setting neighborhood radius to "<<size<<"..."<<std::endl;
+
+      // params
+      f->SetLower(mArgsInfo.lower_arg);
+      f->SetUpper(mArgsInfo.upper_arg);
+      f->SetLowerBorderIsGiven(mArgsInfo.adaptLower_flag);
+      f->SetLowerBorderIsGiven(mArgsInfo.adaptUpper_flag);
+      f->SetReplaceValue(static_cast<PixelType>(mArgsInfo.pad_arg));
+      f->SetMultiplier(mArgsInfo.multiplier_arg);
+      f->SetMaximumSDIsGiven(mArgsInfo.maxSD_given);
+      if (mArgsInfo.maxSD_given) f->SetMaximumSD(mArgsInfo.maxSD_arg);
+      for (typename SeedsType::const_iterator it = seeds.begin(); it != seeds.end(); ++it)
+        f->AddSeed(*it);
+      f->SetRadius(size);
+      filter=f;
+      if (mArgsInfo.verbose_flag) std::cout<<"Using the locally adaptive threshold connected image filter..."<<std::endl;
+
+      break;
+    }
+  
+    case 4: {
+               
+      typedef clitk::ExplosionControlledThresholdConnectedImageFilter<InputImageType, OutputImageType> ImageFilterType;
+      typename ImageFilterType::Pointer f= ImageFilterType::New();
+       
+      //       // Radius
+      //       typename  InputImageType::SizeType size;
+      //       if (mArgsInfo.radius_given==Dimension)
+      //         for (unsigned int i=0; i<Dimension;i++)
+      //           size[i]=mArgsInfo.radius_arg[i];
+      //       else size.Fill(mArgsInfo.radius_arg[0]);
+      //       if (mArgsInfo.verbose_flag) std::cout<<"Setting neighborhood radius to "<<size<<"..."<<std::endl;
+       
+      // params
+      f->SetVerbose(mArgsInfo.verbose_flag);
+      f->SetLower(mArgsInfo.lower_arg);
+      f->SetUpper(mArgsInfo.upper_arg);
+      f->SetMinimumLowerThreshold(mArgsInfo.minLower_arg);
+      f->SetMaximumUpperThreshold(mArgsInfo.maxUpper_arg);
+      f->SetAdaptLowerBorder(mArgsInfo.adaptLower_flag);
+      f->SetAdaptUpperBorder(mArgsInfo.adaptUpper_flag);
+      f->SetReplaceValue(static_cast<PixelType>(mArgsInfo.pad_arg));
+      f->SetMultiplier(mArgsInfo.multiplier_arg);
+      f->SetThresholdStepSize(mArgsInfo.step_arg);
+      f->SetMinimumThresholdStepSize(mArgsInfo.minStep_arg);
+      f->SetFullyConnected(mArgsInfo.full_flag);
+      for (typename SeedsType::const_iterator it = seeds.begin(); it != seeds.end(); ++it)
+        f->AddSeed(*it);
+      filter=f;
+      if (mArgsInfo.verbose_flag) std::cout<<"Using the explosion controlled threshold connected image filter..."<<std::endl;
+
+      break;
+    }
+  
+    }
+
+
+  filter->SetInput(input);
+  filter->Update();
+  typename OutputImageType::Pointer output=filter->GetOutput();
+
+  // Write/Save results
+  this->template SetNextOutput<OutputImageType>(output); 
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKREGIONGROWINGGENERICFILTER_TXX
index d46f20e461a02f8a90c4e07784049b03b1ad6225..ede400746d028373718d3f3d45444ab6865a3468 100644 (file)
 #ifndef clitkCropImageGenericFilter_cxx
 #define clitkCropImageGenericFilter_cxx
 
-/* =================================================
- * @file   clitkCropImageGenericFilter.cxx
- * @author 
- * @date   
- * 
- * @brief 
- * 
- ===================================================*/
-
 #include "clitkCropImageGenericFilter.h"
 
-
 //-----------------------------------------------------------
 // Constructor
 //-----------------------------------------------------------
index 265871f0f63ca91aa7c85f2787013eb0c48d97d3..818a88c04c2ad693249db64231553a16176043df 100644 (file)
   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
 ===========================================================================**/
 
-/* =================================================
- * @file   clitkImageStatistics.cxx
- * @author 
- * @date   
- * 
- * @brief 
- * 
- ===================================================*/
-
-
 // clitk
 #include "clitkImageStatistics_ggo.h"
 #include "clitkIO.h"
@@ -43,7 +33,7 @@ int main(int argc, char * argv[]) {
   clitk::ImageStatisticsGenericFilter::Pointer genericFilter=clitk::ImageStatisticsGenericFilter::New();
   
   genericFilter->SetArgsInfo(args_info);
-  genericFilter->Update();
+  CLITK_TRY_CATCH_EXIT(genericFilter->Update());
 
   return EXIT_SUCCESS;
 }// end main
index bbb127b6fbdd30be1543c55a2b320ebf6c2bd37e..d2e55f36572162d451c80567924c92ba610eb68e 100644 (file)
@@ -15,3 +15,5 @@ option "histogram"    -       "Compute histogram, allows median calculation"  string  no
 option "bins"          -       "Number of histogram bins"                      int     no      default="100"
 option "lower"         -       "Lower histogram bound" double  no default="-1000"      
 option "upper"         -       "Upper histogram bound" double  no default="1000"               
+
+option "allow_resize"          r       "Resize mask if different from input"                     flag          off
index ddfe5e0293661220055a8aabd95259273d759403..931e1bfe7c12b8002cc2e18eeb5ba5181fb044e8 100644 (file)
 #ifndef clitkImageStatisticsGenericFilter_cxx
 #define clitkImageStatisticsGenericFilter_cxx
 
-/* =================================================
- * @file   clitkImageStatisticsGenericFilter.cxx
- * @author 
- * @date   
- * 
- * @brief 
- * 
- ===================================================*/
-
 #include "clitkImageStatisticsGenericFilter.h"
 
-
 namespace clitk
 {
 
@@ -42,7 +32,8 @@ namespace clitk
     m_Verbose=false;
     m_InputFileName="";
   }
-
+  //-----------------------------------------------------------
+  
 
   //-----------------------------------------------------------
   // Update
index 6511c0e0a0bcc30114f5606a5cc3a016e5a31dc3..00cfff8e9fad3908a391936199ab219ca909247e 100644 (file)
 #ifndef clitkImageStatisticsGenericFilter_h
 #define clitkImageStatisticsGenericFilter_h
 
-/* =================================================
- * @file   clitkImageStatisticsGenericFilter.h
- * @author 
- * @date   
- * 
- * @brief 
- * 
- ===================================================*/
-
-
 // clitk include
 #include "clitkIO.h"
 #include "clitkCommon.h"
@@ -41,7 +31,6 @@
 namespace clitk 
 {
 
-
   class ITK_EXPORT ImageStatisticsGenericFilter : public itk::LightObject
   {
   public:
index a0d2abfc609e101ece56b5b1e6606f13939f0064..7b9c78b1cb233a394cef58753e6f8a4d21374313 100644 (file)
 #include "itkNthElementImageAdaptor.h"
 #include "itkJoinSeriesImageFilter.h"
 
-/* =================================================
- * @file   clitkImageStatisticsGenericFilter.txx
- * @author 
- * @date   
- * 
- * @brief 
- * 
- ===================================================*/
 #include "clitkImageStatisticsGenericFilter.h"
-
+#include "clitkCropLikeImageFilter.h"
+#include "clitkResampleImageWithOptionsFilter.h"
 
 namespace clitk
 {
@@ -114,6 +107,7 @@ namespace clitk
       int maskDimension, maskComponents;
       std::string maskPixelType;
       ReadImageDimensionAndPixelType(m_ArgsInfo.mask_arg, maskDimension, maskPixelType, maskComponents);
+
       if (maskDimension == Dimension - 1) {
         // Due to a limitation of filter itk::LabelStatisticsImageFilter, InputImageType and LabelImageType
         // must have the same image dimension. However, we want to support label images with Dl = Di - 1,
@@ -143,6 +137,30 @@ namespace clitk
         labelImageReader->SetFileName(m_ArgsInfo.mask_arg);
         labelImageReader->Update();
         labelImage= labelImageReader->GetOutput();
+
+        // Check mask sampling/size
+        if (!HaveSameSizeAndSpacing<LabelImageType, InputImageType>(labelImage, input)) {
+          if (m_ArgsInfo.allow_resize_flag) {
+            if (m_ArgsInfo.verbose_flag) {
+              std::cout << "Resize mask image like input" << std::endl;
+            }
+            typedef clitk::ResampleImageWithOptionsFilter<LabelImageType> ResamplerType;
+            typename ResamplerType::Pointer resampler = ResamplerType::New();
+            resampler->SetInput(labelImage);
+            resampler->SetOutputSpacing(input->GetSpacing());
+            resampler->Update();
+            labelImage = resampler->GetOutput();
+
+            typename itk::ImageBase<LabelImageType::ImageDimension>::RegionType reg 
+              = input->GetLargestPossibleRegion();
+            labelImage = ResizeImageLike<LabelImageType>(labelImage, &reg, 0);
+          }
+          else {
+            std::cerr << "Mask image has a different size/spacing than input. Abort" << std::endl;
+            exit(-1);
+          }
+        }
+
       }
 
     }
index 8fb0ac5c5c45234e2b24c66e42b18d08a88f1691..5bb6f00af7acfca49429624343abfefc91fc82fe 100644 (file)
@@ -23,6 +23,7 @@ SET(vv_TOOLS
   vvToolMIP
   vvToolConvert ## with dummy vvToolConvert.ui
   vvToolROIManager
+  vvToolSegmentation
 
   ## these ones are for tests (not working)
   # vvToolFoo
@@ -79,6 +80,7 @@ SET(vv_SRCS
   vvSlicer.cxx
   vvLandmarks.cxx
   vvLandmarksGlyph.cxx
+  vvClipPolyData.cxx
   vvGlyphSource.cxx
   vvGlyph2D.cxx
   vvSlicerManager.cxx
index 4931841a1dd45545acf8528ad0702774f0a38890..625b4faec06cfc48a88f38f134092b06ae62524d 100644 (file)
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>408</width>
-    <height>285</height>
+    <width>401</width>
+    <height>489</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Binarize image</string>
   </property>
-  <widget class="QPushButton" name="pushButton">
-   <property name="geometry">
-    <rect>
-     <x>140</x>
-     <y>120</y>
-     <width>86</width>
-     <height>27</height>
-    </rect>
-   </property>
-   <property name="text">
-    <string>PushButton</string>
-   </property>
-  </widget>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QFrame" name="frame">
+     <property name="frameShape">
+      <enum>QFrame::StyledPanel</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Raised</enum>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="0">
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>Ref mask size</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLabel" name="mRefMaskSizeLabel">
+        <property name="text">
+         <string>12303 voxels (65464 mm3)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="label_3">
+        <property name="text">
+         <string>Current mask size</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QLabel" name="mCurrentMaskSizeLabel">
+        <property name="text">
+         <string>12303 voxels (65464 mm3)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QLabel" name="label_4">
+        <property name="text">
+         <string>Label mask sizes</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QTextEdit" name="textEdit">
+        <property name="maximumSize">
+         <size>
+          <width>16777215</width>
+          <height>50</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QFrame" name="frame_2">
+     <property name="frameShape">
+      <enum>QFrame::StyledPanel</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Raised</enum>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="1">
+       <widget class="QLabel" name="label_10">
+        <property name="text">
+         <string>12 56 32</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="label_12">
+        <property name="text">
+         <string>Current pos (mm)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QLabel" name="label_11">
+        <property name="text">
+         <string>12.3 56.6 32.9</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QLabel" name="label_14">
+        <property name="text">
+         <string>Image value</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QLabel" name="label_13">
+        <property name="text">
+         <string>236</string>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="0">
+       <widget class="QLabel" name="label_15">
+        <property name="text">
+         <string>Ref mask</string>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <widget class="QLabel" name="label_16">
+        <property name="text">
+         <string>Inside</string>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="0">
+       <widget class="QLabel" name="label_18">
+        <property name="text">
+         <string>Current mask</string>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="1">
+       <widget class="QLabel" name="label_17">
+        <property name="text">
+         <string>Outside</string>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="0">
+       <widget class="QLabel" name="label_19">
+        <property name="text">
+         <string>Label mask</string>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="1">
+       <widget class="QLabel" name="label_20">
+        <property name="text">
+         <string>Outside</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="0">
+       <widget class="QLabel" name="label_9">
+        <property name="text">
+         <string>Current pos (pix)</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Log</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QTextEdit" name="mLogText">
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QPushButton" name="pushButton_2">
+     <property name="text">
+      <string>Save current mask</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QPushButton" name="pushButton">
+     <property name="text">
+      <string>Quit</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
  </widget>
  <resources/>
  <connections/>
diff --git a/vv/vvClipPolyData.cxx b/vv/vvClipPolyData.cxx
new file mode 100644 (file)
index 0000000..91f391b
--- /dev/null
@@ -0,0 +1,80 @@
+#include "vvClipPolyData.h"
+
+#include "vtkObjectFactory.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkInformationVector.h"
+#include "vtkInformation.h"
+#include "vtkDataObject.h"
+#include "vtkSmartPointer.h"
+#include "vtkImplicitFunction.h"
+#include "vtkStringArray.h"
+#include "vtkPointData.h"
+
+
+vtkStandardNewMacro(vvClipPolyData);
+
+vvClipPolyData::vvClipPolyData()
+{
+  this->SetNumberOfInputPorts(1);
+  this->SetNumberOfOutputPorts(1);
+}
+
+vvClipPolyData::~vvClipPolyData()
+{
+
+}
+
+int vvClipPolyData::RequestData(vtkInformation *vtkNotUsed(request),
+                                            vtkInformationVector **inputVector,
+                                            vtkInformationVector *outputVector)
+{
+    // get the info objects
+    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
+    vtkInformation *outInfo = outputVector->GetInformationObject(0);
+    // get the input and ouptut
+    vtkPolyData *input = vtkPolyData::SafeDownCast(
+                            inInfo->Get(vtkDataObject::DATA_OBJECT()));
+    vtkStringArray* inputLabels = vtkStringArray::SafeDownCast(input->GetPointData()->GetAbstractArray("labels"));
+    vtkPolyData *output = vtkPolyData::SafeDownCast(
+                           outInfo->Get(vtkDataObject::DATA_OBJECT()));
+    //
+    vtkImplicitFunction* currentImpliciteFunction = this->GetClipFunction();
+    int insideOutValue = this->GetInsideOut();
+    //if insideOutValue=0; we want to retrieve ouside points
+    //if insideOutValue=1; we want to retrieve inside points
+    vtkSmartPointer<vtkPoints> outputPoints = vtkSmartPointer<vtkPoints>::New();
+    vtkSmartPointer<vtkStringArray> outputStrings = vtkSmartPointer<vtkStringArray>::New();
+    outputStrings->SetName("labels");
+    for(vtkIdType i=0;i<input->GetNumberOfPoints();i++) {
+       //
+       double* currentPoint = input->GetPoint(i);
+       double currentIFvalue = currentImpliciteFunction->FunctionValue(currentPoint);
+       //if currentIFvalue>0, current point is outside the clip
+       if (currentIFvalue>0 && insideOutValue==0) {
+           outputPoints->InsertNextPoint(currentPoint);
+           vtkStdString label = inputLabels->GetValue(i);
+           outputStrings->InsertNextValue(label);
+       }
+       //currentIFvalue<=0, current point is inside the clip
+       else if (currentIFvalue<=0 && insideOutValue==1) {
+           outputPoints->InsertNextPoint(currentPoint);
+           vtkStdString label = inputLabels->GetValue(i);
+           outputStrings->InsertNextValue(label);
+       }
+       else {
+           //vtkErrorMacro("vvClipPolyData - NOT IMPLEMENTED");
+       }
+    }
+    //
+    output->ShallowCopy(input);
+    output->SetPoints(outputPoints);
+    output->GetPointData()->AddArray(outputStrings);
+    return 1;
+}
+
+//----------------------------------------------------------------------------
+
+void vvClipPolyData::PrintSelf(ostream& os, vtkIndent indent)
+{
+    this->Superclass::PrintSelf(os,indent);
+}
diff --git a/vv/vvClipPolyData.h b/vv/vvClipPolyData.h
new file mode 100644 (file)
index 0000000..5bd3f86
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef VVCLIPPOLYDATA_H
+#define VVCLIPPOLYDATA_H
+
+#include "vtkClipPolyData.h"
+
+class vvClipPolyData : public vtkClipPolyData
+{
+public:
+  vtkTypeMacro(vvClipPolyData,vtkClipPolyData);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  static vvClipPolyData *New();
+
+protected:
+  vvClipPolyData();
+  ~vvClipPolyData();
+
+  int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
+
+private:
+  vvClipPolyData(const vvClipPolyData&);  // Not implemented.
+  void operator=(const vvClipPolyData&);  // Not implemented.
+};
+
+#endif // VVCLIPPOLYDATA_H
index 682398f49deca17954a5dc95ed25a8364a17c699..0bab2f4305a8434023ffaa9751fdaf236f5f3fda 100644 (file)
@@ -41,6 +41,8 @@ vvLandmarks::vvLandmarks(int size)
   }
   mPolyData = vtkPolyData::New();
   mIds = vtkFloatArray::New();
+  mLabels = vtkStringArray::New();
+  mLabels->SetName("labels");
 }
 //--------------------------------------------------------------------
 
@@ -58,6 +60,8 @@ vvLandmarks::~vvLandmarks()
     mIds->Delete();
   if (mPolyData)
     mPolyData->Delete();
+  if (mLabels)
+    mLabels->Delete();
 }
 //--------------------------------------------------------------------
 
@@ -66,14 +70,21 @@ vvLandmarks::~vvLandmarks()
 void vvLandmarks::AddLandmark(float x,float y,float z,float t,double value)
 {
   vvLandmark point;
+  vtkIdType idPoint;
   point.coordinates[0] = x;
   point.coordinates[1] = y;
   point.coordinates[2] = z;
   point.coordinates[3] = t;
   point.pixel_value=value;
   mLandmarks.push_back(point);
-  mPoints[int(t)]->InsertNextPoint(x,y,z);
-  
+
+  idPoint = mPoints[int(t)]->InsertNextPoint(x,y,z);
+  std::string str_vtkIdType;       // string which will contain the result
+  std::ostringstream convert;      // stream used for the conversion
+  convert << idPoint;                  // insert the textual representation of 'idPoint' in the characters in the stream
+  str_vtkIdType = convert.str();    // set 'str_vtkIdType' to the contents of the stream
+  mLabels->InsertNextValue(str_vtkIdType.c_str());
+
   std::stringstream numberVal;
   numberVal << (mLandmarks.size()-1);
   /*
@@ -96,10 +107,12 @@ void vvLandmarks::RemoveLastLandmark()
 {
   mPoints[mLandmarks.back().coordinates[3]]->SetNumberOfPoints(
                                                                mPoints[mLandmarks.back().coordinates[3]]->GetNumberOfPoints()-1);
-  mPolyData->Modified();
   //  mText.pop_back();
   mLandmarks.pop_back();
   mIds->RemoveLastTuple();
+  mLabels->SetNumberOfValues(mLabels->GetNumberOfValues()-1);
+  mLabels->Modified();
+  mPolyData->Modified();
 }
 //--------------------------------------------------------------------
 
@@ -112,9 +125,17 @@ void vvLandmarks::RemoveLandmark(int index)
   // pologyons linking the points
   int npoints = mPoints[mLandmarks[index].coordinates[3]]->GetNumberOfPoints();
   int t = mLandmarks[index].coordinates[3];
-  for (int i = index; i < npoints - 1; i++)
+  for (int i = index; i < npoints - 1; i++) {
     mPoints[t]->InsertPoint(i, mPoints[t]->GetPoint(i+1));
+       std::string str_i;                   // string which will contain the result
+       std::ostringstream convert;      // stream used for the conversion
+       convert << i;                        // insert the textual representation of 'i' in the characters in the stream
+       str_i = convert.str();           // set 'str_i' to the contents of the stream
+       mLabels->SetValue(i,str_i.c_str());
+    }
   mPoints[t]->SetNumberOfPoints(npoints-1);
+  mLabels->SetNumberOfValues(npoints-1);
+  mLabels->Modified();
   mPolyData->Modified();
 
   mLandmarks.erase(mLandmarks.begin() + index);
@@ -165,6 +186,7 @@ void vvLandmarks::LoadFile(std::string filename)
   }
   mFilename = filename;
   mLandmarks.clear();
+  vtkIdType idPoint;
   char line[255];
   for (unsigned int i = 0; i < mPoints.size(); i++)
     mPoints[i]->SetNumberOfPoints(0);
@@ -246,8 +268,13 @@ void vvLandmarks::LoadFile(std::string filename)
       //      DD(point.comments);
       mLandmarks.push_back(point);
       mIds->InsertNextTuple1(0.55);
-      mPoints[int(point.coordinates[3])]->InsertNextPoint(
+     idPoint = mPoints[int(point.coordinates[3])]->InsertNextPoint(
                                                           point.coordinates[0],point.coordinates[1],point.coordinates[2]);
+     std::string str_vtkIdType;            // string which will contain the result
+     std::ostringstream convert;       // stream used for the conversion
+     convert << idPoint;                   // insert the textual representation of 'idPoint' in the characters in the stream
+     str_vtkIdType = convert.str(); // set 'str_vtkIdType' to the contents of the stream
+     mLabels->InsertNextValue(str_vtkIdType.c_str());
     }
   }
   SetTime(0);
@@ -301,6 +328,7 @@ void vvLandmarks::SetTime(int time)
   if (time >= 0 && time <= ((int)mPoints.size() -1)) {
     mPolyData->SetPoints(mPoints[time]);
     mPolyData->GetPointData()->SetScalars(mIds);
+    mPolyData->GetPointData()->AddArray(mLabels);
     mPolyData->Modified();
     mPolyData->Update();
   }
index 6bfe82e4469e22241599fcd13f821429c2a5dbd2..8f9471729d92462a0145f78e4ee95c92b0aca3c4 100644 (file)
@@ -24,6 +24,7 @@
 #include "vtkPolyData.h"
 #include "vtkPoints.h"
 #include "vvLandmarksGlyph.h"
+#include "vtkStringArray.h"
 
 //typedef
 struct vvLandmark {
@@ -67,6 +68,7 @@ private:
     std::vector<vtkPoints*> mPoints;
     vtkFloatArray* mIds;
     //std::vector<vvLandmarksGlyph*> mText;
+    vtkStringArray* mLabels;
     std::string mFilename;
     int mFormatVersion;
 };
index ef623d9fe21d6090db82e61faef60f50b1525f7d..2eea26d866b81d6c89793d62b8afe91a1cabca7a 100644 (file)
 #define COLUMN_RELOAD_IMAGE 6
 #define COLUMN_IMAGE_NAME 7
 
-#if CLITK_PRIVATE_FEATURES
-  #define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.usf)"
+#define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan *.nii.gz *.usf)"
 #else
-  #define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr)"
-#endif
+#define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan *.nii.gz)"
+
 
 /*Data Tree values
   0,Qt::UserRole full filename
@@ -3070,6 +3069,12 @@ void vvMainWindow::ShowLastImage()
 //------------------------------------------------------------------------------
 void vvMainWindow::UpdateRenderWindows()
 {
+  for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
+    mSlicerManagers[i]->GetSlicer(0)->UpdateLandmarks();
+    mSlicerManagers[i]->GetSlicer(1)->UpdateLandmarks();
+    mSlicerManagers[i]->GetSlicer(2)->UpdateLandmarks();
+    mSlicerManagers[i]->GetSlicer(3)->UpdateLandmarks();
+  }
   if (NOViewWidget->GetRenderWindow()) NOViewWidget->GetRenderWindow()->Render();
   if (NEViewWidget->GetRenderWindow()) NEViewWidget->GetRenderWindow()->Render();
   if (SOViewWidget->GetRenderWindow()) SOViewWidget->GetRenderWindow()->Render();
index e7f82f6b5fe084f2257ca3f8bba13205893b4b0f..74d588328865cdfa27ca192a0d44daf5cdcb7a3d 100644 (file)
@@ -35,7 +35,7 @@ vvROIActor::vvROIActor()
 {
   mIsVisible = true;
   mIsContourVisible = false;
-  mOpacity = 0.7;
+  mOpacity = 0.5;
   mIsSelected = false;
   mContourWidth = 1;
   mContourColor.resize(3);
@@ -166,10 +166,10 @@ void vvROIActor::Initialize(double depth, bool IsVisible) {
       mImageContour.push_back(vvImageContour::New());
       mImageContour[i]->SetSlicer(mSlicerManager->GetSlicer(i));
       mImageContour[i]->SetImage(mROI->GetImage());
-      // Color of the contour is "complement" of roi color
-      mContourColor[0] = 1-mROI->GetDisplayColor()[0];
-      mContourColor[1] = 1-mROI->GetDisplayColor()[1];
-      mContourColor[2] = 1-mROI->GetDisplayColor()[2];
+      // Color of the contour is same of roi color
+      mContourColor[0] = mROI->GetDisplayColor()[0];
+      mContourColor[1] = mROI->GetDisplayColor()[1];
+      mContourColor[2] = mROI->GetDisplayColor()[2];
       mImageContour[i]->SetColor(mContourColor[0], mContourColor[1], mContourColor[2]);
       mImageContour[i]->SetLineWidth(mContourWidth);
       mImageContour[i]->SetPreserveMemoryModeEnabled(true);
index a915a6b84b1b616e16430e23dad84853e2d7eee3..1e1245f425b787523aeb69d7e9cf87c7086c851d 100644 (file)
@@ -40,6 +40,7 @@
 #include <vtkDataArray.h>
 #include <vtkFloatArray.h>
 #include <vtkClipPolyData.h>
+#include <vtkActor2DCollection.h>
 #include <vtkGlyph3D.h>
 #include <vtkMath.h>
 #include <vtkCursor3D.h>
@@ -576,36 +577,40 @@ void vvSlicer::SetLandmarks(vvLandmarks* landmarks)
 
     if (!mCross)
       mCross = vtkSmartPointer<vtkCursor3D>::New();
+       if (!mClipBox)
+      mClipBox = vtkSmartPointer<vtkBox>::New();
+    if (!mLandClipper)
+      mLandClipper = vtkSmartPointer<vvClipPolyData>::New();
+    if (!mLandGlyph)
+      mLandGlyph = vtkSmartPointer<vtkGlyph3D>::New();
+    if (!mLandMapper)
+      mLandMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+    if (!mLandActor)
+      mLandActor = vtkSmartPointer<vtkActor>::New();
+
     mCross->SetFocalPoint(0.0,0.0,0.0);
     mCross->SetModelBounds(-10,10,-10,10,-10,10);
     mCross->AllOff();
     mCross->AxesOn();
 
-    if (!mLandGlyph)
-      mLandGlyph = vtkSmartPointer<vtkGlyph3D>::New();
+    mLandClipper->SetClipFunction(mClipBox);
+    mLandClipper->InsideOutOn();
+    mLandClipper->SetInput(mLandmarks->GetOutput());
+
     mLandGlyph->SetSource(mCross->GetOutput());
-    mLandGlyph->SetInput(landmarks->GetOutput());
+    mLandGlyph->SetInput(mLandClipper->GetOutput());
     //mLandGlyph->SetIndexModeToScalar();
-    mLandGlyph->SetRange(0,1);
-    mLandGlyph->ScalingOff();
-
-    mLandGlyph->SetColorModeToColorByScalar();
+    //mLandGlyph->SetRange(0,1);
+    //mLandGlyph->ScalingOff();
 
-    if (!mClipBox)
-      mClipBox = vtkSmartPointer<vtkBox>::New();
-    if (!mLandClipper)
-      mLandClipper = vtkSmartPointer<vtkClipPolyData>::New();
-    mLandClipper->InsideOutOn();
-    mLandClipper->SetInput(mLandGlyph->GetOutput());
-    mLandClipper->SetClipFunction(mClipBox);
+    //mLandGlyph->SetColorModeToColorByScalar();
+    
+    mLandGlyph->SetScaleModeToDataScalingOff();
+    mLandGlyph->SetIndexModeToOff();
 
-    if (!mLandMapper)
-      mLandMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
-    mLandMapper->SetInputConnection(mLandClipper->GetOutputPort());
+    mLandMapper->SetInputConnection(mLandGlyph->GetOutputPort());
     //mLandMapper->ScalarVisibilityOff();
 
-    if (!mLandActor)
-      mLandActor = vtkSmartPointer<vtkActor>::New();
     mLandActor->SetMapper(mLandMapper);
     mLandActor->GetProperty()->SetColor(255,10,212);
     mLandActor->SetPickable(0);
@@ -904,15 +909,15 @@ void vvSlicer::UpdateDisplayExtent()
     return;
   }
   input->UpdateInformation();
+  this->SetSlice( this->GetSlice() ); //SR: make sure the update let the slice in extents
 
   // Local copy of extent
   int w_ext[6];
   int* ext = GetExtent();
   copyExtent(ext, w_ext);
   // Set slice value
-  int s = this->Slice > ext[this->SliceOrientation*2+1] ? ext[this->SliceOrientation*2 + 1] : this->Slice;
-  w_ext[ this->SliceOrientation*2   ] = s;
-  w_ext[ this->SliceOrientation*2+1 ] = s;
+  w_ext[ this->SliceOrientation*2   ] = this->Slice;
+  w_ext[ this->SliceOrientation*2+1 ] = this->Slice;
   
   // Image actor
   this->ImageActor->SetDisplayExtent(w_ext);
@@ -1444,13 +1449,38 @@ void vvSlicer::UpdateLandmarks()
 {
   vtkPolyData *pd = static_cast<vtkPolyData*>(mLandClipper->GetInput());
   if (pd->GetPoints()) {
-    mLandGlyph->SetRange(0,1);
-    mLandGlyph->Modified();
-    mLandGlyph->Update();
+    //mLandGlyph->SetRange(0,1);
+    //mLandGlyph->Modified();
+    //mLandGlyph->Update();
 
     mClipBox->Modified();
     mLandClipper->Update();
     mLandMapper->Update();
+    //Let's add the captions
+    //First remove all captions:
+    for(unsigned int i=0;i<mLandLabelActors.size();i++) {
+       this->Renderer->RemoveActor2D(mLandLabelActors[i]);
+       //allActors2D->Remove (mLandLabelActors[i]);
+    }
+    mLandLabelActors.clear();
+    //Next add the captions to the displayed points
+    for (vtkIdType id=0; id<mLandClipper->GetOutput()->GetNumberOfPoints(); id++) {
+         double *position = mLandClipper->GetOutput()->GetPoint(id);
+      vtkStdString label = static_cast<vtkStringArray*>(mLandClipper->GetOutput()->GetPointData()->GetAbstractArray("labels"))->GetValue(id);
+      vtkSmartPointer<vtkCaptionActor2D> label_actor = vtkSmartPointer<vtkCaptionActor2D>::New();
+      label_actor->SetCaption(label);
+      label_actor->SetAttachmentPoint(position);
+      label_actor->GetCaptionTextProperty()->SetColor(1,0,0);
+      label_actor->GetCaptionTextProperty()->SetOrientation(33.333333);
+      label_actor->GetCaptionTextProperty()->SetFontFamilyToTimes();
+      label_actor->GetCaptionTextProperty()->SetBold(0);
+      label_actor->GetCaptionTextProperty()->SetFontSize(6);
+      label_actor->BorderOff();
+      label_actor->LeaderOff();
+      label_actor->ThreeDimensionalLeaderOff();
+      mLandLabelActors.push_back(label_actor);
+      this->Renderer->AddActor2D(mLandLabelActors[id]);
+     }
   }
 
 }
index 9a750e14d69a6db41596d143e4d3ff30c33b9fae..a738a788b192db47fb40859f233b5e31853a8569 100644 (file)
 #include "vvImage.h"
 #include "vvMesh.h"
 #include "vvMeshActor.h"
+#include "vvClipPolyData.h"
 
 #include <vtkSmartPointer.h>
 #include <vtkImageViewer2.h>
 #include <vtkImageReslice.h>
 #include <vtkImageMapToColors.h>
+#include <vtkCaptionActor2D.h>
 
 class vtkActor;
 class vtkActor2D;
@@ -244,9 +246,10 @@ protected:
   vtkSmartPointer<vtkActor> mVFActor;
   vtkSmartPointer<vtkGlyph3D> mLandGlyph;
   vtkSmartPointer<vtkCursor3D> mCross;
-  vtkSmartPointer<vtkClipPolyData> mLandClipper;
+  vtkSmartPointer<vvClipPolyData> mLandClipper;
   vtkSmartPointer<vtkPolyDataMapper> mLandMapper;
   vtkSmartPointer<vtkActor> mLandActor;
+  std::vector<vtkSmartPointer<vtkCaptionActor2D> > mLandLabelActors;
   vtkSmartPointer<vtkBox> mClipBox;
   vtkSmartPointer<vtkScalarBarActor> legend;
   std::vector<vvMeshActor*> mSurfaceCutActors;
index 015409b2debdf12cc501dd6b0226eddabf77e6a8..b175c46ccc642665487641e20c102b2e8c8e5d37 100644 (file)
@@ -417,6 +417,23 @@ void vvSlicerManager::LeftButtonReleaseEvent(int slicer)
 }
 //----------------------------------------------------------------------------
 
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::EmitMousePositionUpdated(int slicer)
+{
+  emit MousePositionUpdatedSignal(slicer);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::EmitKeyPressed(std::string KeyPress)
+{
+  emit KeyPressedSignal(KeyPress);
+}
+//----------------------------------------------------------------------------
+
+
 //----------------------------------------------------------------------------
 void vvSlicerManager::SetSliceOrientation(int slicer, int orientation)
 {
@@ -641,18 +658,18 @@ void vvSlicerManager::UpdateViews(int current,int slicer)
         }
         switch (mSlicers[i]->GetSliceOrientation()) {
         case vtkImageViewer2::SLICE_ORIENTATION_XY:
-          if (mSlicers[i]->GetSlice() != (int)floor(z))
-            mSlicers[i]->SetSlice((int)floor(z));
+          if (mSlicers[i]->GetSlice() != (int)lrint(z))
+            mSlicers[i]->SetSlice((int)lrint(z));
           break;
 
         case vtkImageViewer2::SLICE_ORIENTATION_XZ:
-          if (mSlicers[i]->GetSlice() != (int)floor(y))
-            mSlicers[i]->SetSlice((int)floor(y));
+          if (mSlicers[i]->GetSlice() != (int)lrint(y))
+            mSlicers[i]->SetSlice((int)lrint(y));
           break;
 
         case vtkImageViewer2::SLICE_ORIENTATION_YZ:
-          if (mSlicers[i]->GetSlice() != (int)floor(x))
-            mSlicers[i]->SetSlice((int)floor(x));
+          if (mSlicers[i]->GetSlice() != (int)lrint(x))
+            mSlicers[i]->SetSlice((int)lrint(x));
           break;
         }
         
index dcac673216f1af7eef36b8394dfa32bb6dbbf8f9..4fc274c5e4723ce460984cc7850de60ea60dbc58 100644 (file)
@@ -212,6 +212,8 @@ class vvSlicerManager : public QObject {
   void Activated();
   void Picked();
   void UpdateInfoOnCursorPosition(int slicer);
+  void EmitMousePositionUpdated(int slicer);
+  void EmitKeyPressed(std::string keyPress);
   void UpdateWindowLevel();
   void UpdateSlice(int slicer);
   void UpdateTSlice(int slicer);
@@ -234,6 +236,8 @@ signals :
   void UpdateVector(int display, double x, double y, double z, double value);
   void UpdateOverlay(int display, double valueOver, double valueRef);
   void UpdateFusion(int display, double valueFus);
+  void MousePositionUpdatedSignal(int slicer);
+  void KeyPressedSignal(std::string KeyPressed);
   void UpdateOrientation(int slicer, int orientation);
   void UpdateSlice(int slicer, int slice);
   void UpdateTSlice(int slicer, int slice);
index 73a0ab5efda3e79ba42b604908662a2149806b4b..ad80b925a6d0b5bfc34fe6516e5f1d889bf9c003 100644 (file)
@@ -266,6 +266,7 @@ void vvSlicerManagerCommand::Execute(vtkObject *caller,
           this->SM->UpdateSliceRange(VisibleInWindow);
         }
 
+        this->SM->EmitKeyPressed(KeyPress);
       }
 
       //All type of mouse events
@@ -276,7 +277,6 @@ void vvSlicerManagerCommand::Execute(vtkObject *caller,
         return;
       }
 
-      //DD(event);
       // Mouse release HERE
       if (event == vtkCommand::EndPickEvent) {
         //           DD(VisibleInWindow);
@@ -363,12 +363,24 @@ void vvSlicerManagerCommand::Execute(vtkObject *caller,
         break;
       }
 
+      // <<<<<<< HEAD
+      //       this->SM->GetSlicer(VisibleInWindow)->SetCurrentPosition(xWorld,yWorld,zWorld,
+      //                           this->SM->GetSlicer(VisibleInWindow)->GetTSlice());
+      //       // We propagate the mouse position
+      //       this->SM->EmitMousePositionUpdated(VisibleInWindow);      
+      // =======
       double p[3]; p[0] = xWorld; p[1] = yWorld; p[2] = zWorld;
       double pt[3];
       this->SM->GetSlicer(VisibleInWindow)->GetSlicingTransform()->TransformPoint(p, pt);
 
       this->SM->GetSlicer(VisibleInWindow)->SetCurrentPosition(pt[0],pt[1],pt[2],
           this->SM->GetSlicer(VisibleInWindow)->GetMaxCurrentTSlice());
+
+      // We propagate the mouse position
+      this->SM->EmitMousePositionUpdated(VisibleInWindow);
+
+      //>>>>>>> 921642d767beba2442dacc8fdb40dc36396e1b7d
+
       if (newLandmark) {
         this->SM->AddLandmark(xWorld,yWorld,zWorld,
                               this->SM->GetSlicer(VisibleInWindow)->GetTSlice());
index 8b0a48753671fc735e6cfed736dae8d62bfda1d1..e1d2e5c534e2f586d45657d3911a14417d6e6641 100644 (file)
@@ -491,9 +491,7 @@ void vvToolROIManager::UpdateAllContours()
   for(unsigned int i=0; i<mROIList.size(); i++) {
     mROIActorsList[i]->Update();
   }
-  for(int i=0; i<mCurrentSlicerManager->GetNumberOfSlicers(); i++) {
-    mCurrentSlicerManager->GetSlicer(i)->Render();
-  }
+  mCurrentSlicerManager->Render();
 }
 //------------------------------------------------------------------------------
 
@@ -679,6 +677,8 @@ void vvToolROIManager::ChangeColor() {
                 mCurrentROIActor->GetROI()->GetDisplayColor()[1],
                 mCurrentROIActor->GetROI()->GetDisplayColor()[2]);
   QColor c = QColorDialog::getColor(color, this, "Choose the ROI color");
+  if (!c.isValid()) return;// User cancel
+
   mCurrentROIActor->GetROI()->SetDisplayColor(c.redF(), c.greenF(), c.blueF());
   mCurrentROIActor->UpdateColor();
 
index dea3513013aff27801512bdf4143ed40830bd990..341084df8a4792c316ef0533d6b98a64c45190d1 100644 (file)
@@ -14,7 +14,7 @@
 
   - BSD        See included LICENSE.txt file
   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
-===========================================================================**/
+  ===========================================================================**/
 
 // vv
 #include "vvToolSegmentation.h"
 #include "vvToolInputSelectorWidget.h"
 #include "vvImageWriter.h"
 
+// clitk
+#include "clitkConnectedComponentLabeling_ggo.h"
+#include "clitkConnectedComponentLabelingGenericFilter.h"
+#include "clitkRegionGrowing_ggo.h"
+#include "clitkRegionGrowingGenericFilter.h"
+
 // Qt
 #include <QFileDialog>
 #include <QMessageBox>
@@ -30,7 +36,8 @@
 // vtk
 #include "vtkImageContinuousErode3D.h"
 #include "vtkImageContinuousDilate3D.h"
+#include "vtkRenderWindow.h"
+
 //------------------------------------------------------------------------------
 // Create the tool and automagically (I like this word) insert it in
 // the main window menu.
@@ -64,7 +71,16 @@ vvToolSegmentation::vvToolSegmentation(vvMainWindowBase * parent, Qt::WindowFlag
   AddInputSelector("Select one image");
   
   // Init
+  mCurrentLabelUnderMousePointer = 0.0;
+  mCurrentMousePositionInMM.resize(3);
+  //  mCurrentMousePositionInPixel.resize(3);
+  mRefMaskImage = NULL;
+  mCurrentState = State_Default;
   mKernelValue = 3; // FIXME must be odd. If even -> not symmetrical
+  mDefaultLUTColor = vtkSmartPointer<vtkLookupTable>::New();
+  mDefaultLUTColor->SetNumberOfTableValues(256);
+#include "vvDefaultLut.h"
+  
 }
 //------------------------------------------------------------------------------
 
@@ -72,6 +88,7 @@ vvToolSegmentation::vvToolSegmentation(vvMainWindowBase * parent, Qt::WindowFlag
 //------------------------------------------------------------------------------
 vvToolSegmentation::~vvToolSegmentation()
 {
+  DD("destructor");
 }
 //------------------------------------------------------------------------------
 
@@ -79,7 +96,14 @@ vvToolSegmentation::~vvToolSegmentation()
 //------------------------------------------------------------------------------
 bool vvToolSegmentation::close()
 {
-  mRefMaskActor->RemoveActors();
+  DD("remo ref");
+  if (mRefMaskActor) mRefMaskActor->RemoveActors();
+  DD("remo mask");
+  if (mCurrentMaskActor) mCurrentMaskActor->RemoveActors();
+  for(int i=0; i<mCurrentCCLActors.size(); i++) {
+    if (mCurrentCCLActors[i]) mCurrentCCLActors[i]->RemoveActors();
+  }
+  DD("wclose");
   QWidget::close();  
   mCurrentSlicerManager->Render();
   return true;
@@ -106,6 +130,21 @@ void vvToolSegmentation::InputIsSelected(vvSlicerManager * m)
 
   // Open mask
   OpenBinaryImage();
+  
+  // If cancel: stop
+  if (mRefMaskActor == NULL) {
+    close();
+    return;
+  }
+
+  // Update gui
+  mToolInputSelectionWidget->hide();
+
+  // Connect mouse position
+  connect(mCurrentSlicerManager, SIGNAL(MousePositionUpdatedSignal(int)),
+          this, SLOT(MousePositionChanged(int)));
+  connect(mCurrentSlicerManager, SIGNAL(KeyPressedSignal(std::string)),
+          this, SLOT(KeyPressed(std::string)));
 }
 //------------------------------------------------------------------------------
 
@@ -149,69 +188,222 @@ void vvToolSegmentation::OpenBinaryImage()
     return;
   }
 
-  mMaskImage = reader->GetOutput();
-  int dim = mMaskImage->GetNumberOfDimensions();
+  mRefMaskImage = reader->GetOutput();
+  int dim = mRefMaskImage->GetNumberOfDimensions();
   if (dim != 3 ) {
     QMessageBox::information(this,tr("Sorry only 3D yet"), tr("Sorry only 3D yet"));
     close();
     return;
   }
 
-  // Add a new roi actor
-  mRefMaskActor = QSharedPointer<vvROIActor>(new vvROIActor);
-  std::vector<double> color;
-  color.push_back(1);
-  color.push_back(0);
-  color.push_back(0);
-  clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New();
-  roi->SetFromBinaryImage(mMaskImage, 1, std::string("toto"), color, filename.toStdString());
-  mRefMaskActor->SetBGMode(true);
-  mRefMaskActor->SetROI(roi);
-  mRefMaskActor->SetSlicerManager(mCurrentSlicerManager);
-  mRefMaskActor->Initialize(10, true);
+  reader = vvImageReader::New();
+  reader->SetInputFilenames(filenames);
+  reader->Update(vvImageReader::IMAGE);
+  mCurrentMaskImage = reader->GetOutput();
+
+  // Add a new roi actor for the current mask
+  mCurrentMaskActor = CreateMaskActor(mCurrentMaskImage, 1, 0, false);
+  mCurrentMaskActor->Update(); // default color is red
+  UpdateMaskSize(mCurrentMaskImage, mCurrentMaskSizeInPixels, mCurrentMaskSizeInCC);  
+
+  // Add a mask actor for the reference
+  mRefMaskActor = CreateMaskActor(mRefMaskImage, 0, 1, true);
+  mRefMaskActor->SetContourVisible(true);
+  mRefMaskActor->SetVisible(false);
+  mRefMaskActor->SetContourColor(0,1,0); // green contour
+  mRefMaskActor->UpdateColor();
   mRefMaskActor->Update();
+  UpdateMaskSize(mRefMaskImage, mRefMaskSizeInPixels, mRefMaskSizeInCC);  
 
-  // Prepare widget to get keyboard event
-  grabKeyboard();
-  //connect(this, SIGNAL(keyPressEvent(QKeyEvent*)), this, SLOT(keyPressed(QKeyEvent*)));
+  // Update GUI
+  UpdateMaskSizeLabels();
 }
 //------------------------------------------------------------------------------
 
 
 //------------------------------------------------------------------------------
-void vvToolSegmentation::keyPressEvent(QKeyEvent * event)
+void vvToolSegmentation::UpdateMaskSizeLabels()
 {
-  vvToolWidgetBase::keyPressEvent(event);
-  //DD("key");
-  
-  if (event->text() == "e") {
+  QString s("%1 pix (%2 cm3)");
+  s = s.arg(mRefMaskSizeInPixels).arg(mRefMaskSizeInCC);
+  mRefMaskSizeLabel->setText(s);
+  QString s2("%1 pix (%2 cm3)");
+  s2 = s2.arg(mCurrentMaskSizeInPixels).arg(mCurrentMaskSizeInCC);
+  mCurrentMaskSizeLabel->setText(s2);
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolSegmentation::UpdateMaskSize(vvImage::Pointer image, long & pix, double & cc)
+{
+  pix = ComputeNumberOfPixels(image, GetForegroundValue());
+  double vol = image->GetSpacing()[0]*image->GetSpacing()[1]*image->GetSpacing()[2];
+  cc = pix * vol / (10*10*10);
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+long vvToolSegmentation::ComputeNumberOfPixels(vvImage::Pointer image, double value) 
+{
+  int n=0;
+  vtkImageData * im = image->GetFirstVTKImageData();
+  char * pPix = (char*)im->GetScalarPointer(); // FIXME char ?
+  for(uint i=0; i<im->GetNumberOfPoints(); i++) {
+    if (pPix[i] == value) n++;
+  }
+  DD(n);
+  return n;
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolSegmentation::KeyPressed(std::string KeyPress)
+{ 
+  if (KeyPress == "G") {
+    RegionGrowing();
+  }
+  if (KeyPress == "e") {
     Erode();
   }
-  if (event->text() == "d") {
+  if (KeyPress == "d") {
     Dilate(); // FIXME -> extend image BB !!
   }
-  if (event->text() == "s") {
+  if (KeyPress == "L") {
+    Labelize(); 
+  }
+  if (KeyPress == "m") {
+    Merge(); 
+    UpdateAndRenderNewMask();
+  }
+  if (KeyPress == "s") { // Supress "Remove" one label
+    if (mCurrentState == State_CCL) RemoveLabel();
+  }
+  if (KeyPress == "t") { // display remove ref contour
+    mRefMaskActor->SetContourVisible(!mRefMaskActor->IsContourVisible());
+    mRefMaskActor->UpdateColor();
+    mCurrentSlicerManager->Render();
+  }
+  if (KeyPress == "w") {
     vvImageWriter::Pointer writer = vvImageWriter::New();
     writer->SetOutputFileName("a.mha");
-    writer->SetInput(mMaskImage);
+    writer->SetInput(mCurrentMaskImage);
     writer->Update();
   }
 }
 //------------------------------------------------------------------------------
 
 
+//------------------------------------------------------------------------------
+void vvToolSegmentation::RegionGrowing()
+{
+  DD("RegionGrowing");
+  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+  // Merge labels if needed
+  Merge();
+  // Get mouse location
+  DD(mCurrentLabelUnderMousePointer); 
+  DDV(mCurrentMousePositionInMM, 3);
+  //  DDV(mCurrentMousePositionInPixel, 3);
+
+  // Build RG filter parameters
+  typedef args_info_clitkRegionGrowing ArgsInfoType;
+  ArgsInfoType a;
+  cmdline_parser_clitkRegionGrowing_init(&a);
+  // FIXME parameters
+  a.type_arg = 4;  // FIXME set by gui 
+  DD(a.lower_arg);
+  a.lower_arg = 200;
+  a.upper_arg = 3000;
+  a.seed_given = 3;
+  a.seed_arg = new int[3];
+
+  DDV(mCurrentMousePositionInMM, 3);
+  vtkImageData * image = mCurrentImage->GetFirstVTKImageData();
+  double x = (mCurrentMousePositionInMM[0] - image->GetOrigin()[0]) / image->GetSpacing()[0];
+  double y = (mCurrentMousePositionInMM[1] - image->GetOrigin()[1]) / image->GetSpacing()[1];
+  double z = (mCurrentMousePositionInMM[2] - image->GetOrigin()[2]) / image->GetSpacing()[2];
+  a.seed_arg[0] = x;
+  a.seed_arg[1] = y;
+  a.seed_arg[2] = z;
+  a.verbose_flag = 1;
+
+  // Build RG filter parameters
+  typedef clitk::RegionGrowingGenericFilter<args_info_clitkRegionGrowing> FilterType;
+  FilterType::Pointer filter = FilterType::New();
+  filter->SetArgsInfo(a);
+  filter->SetInputVVImage(mCurrentImage);
+  filter->SetIOVerbose(true);  
+  filter->Update();
+  mCurrentMaskImage = filter->GetOutputVVImage();
+  DD("filter done");
+
+  mCurrentMaskActor->RemoveActors();
+  mCurrentMaskActor = CreateMaskActor(mCurrentMaskImage, 1, 0, false);
+  mCurrentMaskActor->Update(); // default color is red
+  UpdateAndRenderNewMask();
+  UpdateMaskSizeLabels();
+  DD("end");
+  
+  // mouse pointer
+  QApplication::restoreOverrideCursor();
+}  
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolSegmentation::Merge()
+{
+  if (mCurrentState != State_CCL) return;
+  
+  DD("Merge");
+  // Remove actors
+  for(int i=0; i<mCurrentCCLActors.size(); i++) {
+    if (mCurrentCCLActors[i]) {
+      mCurrentCCLActors[i]->SetVisible(false);
+      mCurrentCCLActors[i]->RemoveActors();
+    }
+  }
+  mCurrentCCLActors.clear();
+
+  // Compute new mask
+  vtkImageData * ccl  = mCurrentCCLImage->GetFirstVTKImageData();
+  vtkImageData * mask = mCurrentMaskImage->GetFirstVTKImageData();
+  int * pCCL = (int*)ccl->GetScalarPointer();
+  char * pPix = (char*)mask->GetScalarPointer();
+  for(uint i=0; i<ccl->GetNumberOfPoints(); i++) {
+    if (pCCL[i] == 0) pPix[i] = GetBackgroundValue(); // copy BG. In CCL BG is always 0
+  }
+
+  // Display new mask and remove ccl
+  mCurrentCCLImage->Reset();
+  mCurrentMaskActor->RemoveActors(); // kill it
+  mCurrentMaskActor = CreateMaskActor(mCurrentMaskImage, 1, 0, false); // renew
+  mCurrentMaskActor->Update();
+  mCurrentMaskActor->SetVisible(true); 
+  // mCurrentSlicerManager->Render();
+  mCurrentState = State_Default;
+}
+//------------------------------------------------------------------------------
+
+
 //------------------------------------------------------------------------------
 void vvToolSegmentation::Erode()
 {
   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+  // Merge labels if needed
+  Merge();
+  // Get image and start erosion
   vtkImageContinuousErode3D* erode = vtkImageContinuousErode3D::New();
   erode->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
-  vtkImageData* image = mMaskImage->GetVTKImages()[0];
+  vtkImageData* image = mCurrentMaskImage->GetVTKImages()[0];
   erode->SetInput(image);
   erode->Update();
   image->DeepCopy(erode->GetOutput());
   image->Update();
-  UpdateAndRender();
+  UpdateAndRenderNewMask();
   erode->Delete();
   QApplication::restoreOverrideCursor();
 }
@@ -222,14 +414,17 @@ void vvToolSegmentation::Erode()
 void vvToolSegmentation::Dilate()
 {
   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+  // Merge labels if needed
+  Merge();
+  // Get image and start dilatation
   vtkImageContinuousDilate3D* dilate = vtkImageContinuousDilate3D::New();
   dilate->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
-  vtkImageData* image = mMaskImage->GetVTKImages()[0];
+  vtkImageData* image = mCurrentMaskImage->GetVTKImages()[0];
   dilate->SetInput(image);
   dilate->Update();
   image->DeepCopy(dilate->GetOutput());
   image->Update();
-  UpdateAndRender();
+  UpdateAndRenderNewMask();
   dilate->Delete();
   QApplication::restoreOverrideCursor();
 }
@@ -237,18 +432,177 @@ void vvToolSegmentation::Dilate()
 
 
 //------------------------------------------------------------------------------
-void vvToolSegmentation::UpdateAndRender()
+void vvToolSegmentation::UpdateAndRenderNewMask()
 {
-  bool visible = mRefMaskActor->IsVisible();
-  bool cvisible = mRefMaskActor->IsContourVisible();
-  mRefMaskActor->SetVisible(false);
-  mRefMaskActor->SetContourVisible(false);
+  bool visible = mCurrentMaskActor->IsVisible();
+  bool cvisible = mCurrentMaskActor->IsContourVisible();
+  mCurrentMaskActor->SetVisible(false);
+  mCurrentMaskActor->SetContourVisible(false);
+  mCurrentMaskActor->UpdateImage();
+  mCurrentMaskActor->SetVisible(visible);
+  mCurrentMaskActor->SetContourVisible(cvisible);
+
   mCurrentSlicerManager->Render();
+  UpdateMaskSize(mCurrentMaskImage, mCurrentMaskSizeInPixels, mCurrentMaskSizeInCC);
+  UpdateMaskSizeLabels();
+}
+//------------------------------------------------------------------------------
 
-  //mRefMaskActor->RemoveActors();
-  mRefMaskActor->UpdateImage();
-  mRefMaskActor->SetVisible(visible);
-  mRefMaskActor->SetContourVisible(cvisible);
+//------------------------------------------------------------------------------
+void vvToolSegmentation::Labelize()
+{
+  if (mCurrentState == State_CCL) return; // Do nothing in this case
+  DD("Labelize");
+  // Waiting cursos
+  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+  mCurrentMaskActor->SetVisible(false);
+  
+  // Build CCL filter
+  vtkImageData* image = mCurrentMaskImage->GetVTKImages()[0];
+  typedef args_info_clitkConnectedComponentLabeling ArgsInfoType;
+  ArgsInfoType a;
+  cmdline_parser_clitkConnectedComponentLabeling_init(&a);
+  a.inputBG_arg = GetBackgroundValue();
+  a.full_flag = false;  // FIXME set by gui
+  a.minSize_arg = 100;  // FIXME set by gui 
+  typedef clitk::ConnectedComponentLabelingGenericFilter<ArgsInfoType> FilterType;
+  FilterType::Pointer filter = FilterType::New();
+  filter->SetArgsInfo(a);
+  filter->SetInputVVImage(mCurrentMaskImage); // FIXME Check type is ok ? convert float ?
+  filter->SetIOVerbose(true);  
+  filter->Update();
+  DD(filter->GetOriginalNumberOfObjects());
+  DD(filter->GetSizeOfObjectsInPixels().size());
+  mCurrentCCLImage = filter->GetOutputVVImage();
+  DDV(filter->GetSizeOfObjectsInPixels(), filter->GetSizeOfObjectsInPixels().size());
+  DD("filter done");
+
+  /*
+  // DEBUG
+  vvImageWriter::Pointer writer = vvImageWriter::New();
+  writer->SetInput(mCurrentCCLImage);
+  writer->SetOutputFileName("bidon-ccl.mha");
+  writer->Update(); 
+  DD(mCurrentCCLImage->IsScalarTypeInteger());
+  */
+  
+  // Create actors 
+  int n = filter->GetSizeOfObjectsInPixels().size();
+  mCurrentCCLActors.clear();
+  for(int i=1; i<=std::min(n,10); i++) { // Start at 1 because 0 is BG. FIXME max by gui
+    QSharedPointer<vvROIActor> actor = CreateMaskActor(mCurrentCCLImage, i, i+1, false); 
+    mCurrentCCLActors.push_back( actor );
+    actor->Update();    
+  }
+  //  mCurrentMaskActor->Update();
   mCurrentSlicerManager->Render();
+  
+  // UpdateAndRender();
+  mCurrentState = State_CCL;
+  QApplication::restoreOverrideCursor();
+}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+QSharedPointer<vvROIActor> vvToolSegmentation::CreateMaskActor(vvImage::Pointer image, int i, int colorID, bool BGMode)
+{
+  static int depth = 1;
+  depth += 1;
+  QSharedPointer<vvROIActor> actor = QSharedPointer<vvROIActor>(new vvROIActor);
+  double * color = mDefaultLUTColor->GetTableValue(colorID % mDefaultLUTColor->GetNumberOfTableValues ());
+  std::vector<double> c;
+  c.push_back(color[0]);
+  c.push_back(color[1]);
+  c.push_back(color[2]);
+  clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New();
+  roi->SetFromBinaryImage(image, i, std::string("toto"), c, std::string("titi"));
+  if (BGMode) {
+    actor->SetBGMode(true);
+  }
+  else {
+    roi->SetForegroundValueLabelImage(i); // FG mode
+    actor->SetBGMode(false); // FG mode
+  }
+  actor->SetROI(roi);
+  actor->SetSlicerManager(mCurrentSlicerManager);
+  actor->Initialize(depth+i, true); // +1 to start at 1 not 0
+  actor->SetContourVisible(false);
+  actor->SetVisible(true);
+  return actor;
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolSegmentation::MousePositionChanged(int slicer)
+{
+  // DD("MousePositionChanged ");
+  // DD(slicer);
+  double x = mCurrentSlicerManager->GetSlicer(slicer)->GetCurrentPosition()[0];
+  double y = mCurrentSlicerManager->GetSlicer(slicer)->GetCurrentPosition()[1];
+  double z = mCurrentSlicerManager->GetSlicer(slicer)->GetCurrentPosition()[2];
+  mCurrentMousePositionInMM[0] = x;
+  mCurrentMousePositionInMM[1] = y;
+  mCurrentMousePositionInMM[2] = z;
+  // DDV(mCurrentMousePositionInMM, 3);
+
+  //  vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData();
+  vtkImageData * image = mCurrentMaskImage->GetFirstVTKImageData();
+  double Xover = (x - image->GetOrigin()[0]) / image->GetSpacing()[0];
+  double Yover = (y - image->GetOrigin()[1]) / image->GetSpacing()[1];
+  double Zover = (z - image->GetOrigin()[2]) / image->GetSpacing()[2];
+  int ix, iy, iz;
+  
+  // mCurrentMousePositionInPixel[0] = Xover;
+  // mCurrentMousePositionInPixel[1] = Yover;
+  // mCurrentMousePositionInPixel[2] = Zover;
+  // DDV(mCurrentMousePositionInPixel, 3);
+
+  if (Xover >= image->GetWholeExtent()[0] &&
+      Xover <= image->GetWholeExtent()[1] &&
+      Yover >= image->GetWholeExtent()[2] &&
+      Yover <= image->GetWholeExtent()[3] &&
+      Zover >= image->GetWholeExtent()[4] &&
+      Zover <= image->GetWholeExtent()[5]) {
+    if (mCurrentState == State_Default) { // inside the mask
+      mCurrentLabelUnderMousePointer = 1;
+      return; 
+    }
+    else { // inside the label image
+      vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData();
+      mCurrentLabelUnderMousePointer = 
+        mCurrentSlicerManager->GetSlicer(0)->GetScalarComponentAsDouble(image, Xover, Yover, Zover, ix, iy, iz, 0);
+      return;
+    }
+  }
+  else {
+    // DD("out of mask");
+    mCurrentLabelUnderMousePointer = 0; // BG is always 0 in CCL
+  }
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolSegmentation::RemoveLabel() {
+  DD("RemoveLabel");
+  if (mCurrentLabelUnderMousePointer == 0) return;
+  // First actor=0 and is label 1. Label 0 is not an actor, it is BG
+  int actorNumber = mCurrentLabelUnderMousePointer-1; 
+  // Set actor invisible
+  mCurrentCCLActors[actorNumber]->SetVisible(false);
+  mCurrentSlicerManager->Render();
+  // Set image label
+  vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData();
+  int * pPix = (int*)image->GetScalarPointer();
+  int n = 0;
+  for(uint i=0; i<image->GetNumberOfPoints(); i++) {
+    if (pPix[i] == mCurrentLabelUnderMousePointer) pPix[i] = 0;
+    if (pPix[i] != 0) n++; // count the number of pixels in the foreground
+  }
+  // Update mask size
+  mCurrentMaskSizeInPixels = n;
+  mCurrentMaskSizeInCC = mCurrentMaskImage->GetSpacing()[0] * mCurrentMaskImage->GetSpacing()[1] * mCurrentMaskImage->GetSpacing()[2] * n / (10*10*10);
+  UpdateMaskSizeLabels();
 }
 //------------------------------------------------------------------------------
index 7b8bb8c49ae297d73cb659d780f8079ffc4bfc45..5cd6e404b81d952b4237bd280b9378459a5b9521 100644 (file)
@@ -25,6 +25,8 @@
 #include "vvROIActor.h"
 #include "ui_vvToolSegmentation.h"
 
+#include "vtkLookupTable.h"
+
 //------------------------------------------------------------------------------
 class vvToolSegmentation:
   public vvToolWidgetBase,
@@ -40,23 +42,50 @@ class vvToolSegmentation:
   static void Initialize();
   virtual void InputIsSelected(vvSlicerManager * m);
   void OpenBinaryImage();
+  void RegionGrowing();
   void Erode();
   void Dilate();
-  void UpdateAndRender();
+  void Labelize();
+  void Merge();
+  void RemoveLabel();
+  void UpdateAndRenderNewMask();
 
   //-----------------------------------------------------
   public slots:
   virtual void apply();
-  virtual void keyPressEvent(QKeyEvent * event);
+  void KeyPressed(std::string KeyPress);
   virtual bool close();
-  // virtual void reject();
+  virtual void MousePositionChanged(int slicer);
 
  protected:
-  // virtual void closeEvent(QCloseEvent *event);
   Ui::vvToolSegmentation ui;
   QSharedPointer<vvROIActor> mRefMaskActor;
-  vvImage::Pointer mMaskImage;
+  QSharedPointer<vvROIActor> mCurrentMaskActor;
+  std::vector<QSharedPointer<vvROIActor> > mCurrentCCLActors;
+  vvImage::Pointer mRefMaskImage;
+  vvImage::Pointer mCurrentMaskImage;
+  vvImage::Pointer mCurrentCCLImage;
   int mKernelValue;
+  vtkSmartPointer<vtkLookupTable> mDefaultLUTColor;
+  enum { State_Default, State_CCL};
+  int mCurrentState;
+
+  QSharedPointer<vvROIActor> CreateMaskActor(vvImage::Pointer image, int i, int colorID, bool BGMode=false);
+  
+  double mCurrentLabelUnderMousePointer;
+  std::vector<double> mCurrentMousePositionInMM;
+  //std::vector<double> mCurrentMousePositionInPixel;
+  double GetBackgroundValue() { return 0; }
+  double GetForegroundValue() { return 1; }
+  long ComputeNumberOfPixels(vvImage::Pointer image, double value);
+
+  // Compute and store sizes of mask Foreground
+  void   UpdateMaskSize(vvImage::Pointer image, long & pix, double & cc);
+  void   UpdateMaskSizeLabels();
+  long   mRefMaskSizeInPixels;
+  double mRefMaskSizeInCC;
+  long   mCurrentMaskSizeInPixels;
+  double mCurrentMaskSizeInCC;
 
 }; // end class vvToolSegmentation
 //------------------------------------------------------------------------------