${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)
#if CLITK_PRIVATE_FEATURES
#include "clitkUsfImageIOFactory.h"
#include "clitkUSVoxImageIOFactory.h"
+ #include "clitkSvlImageIOFactory.h"
#endif
//--------------------------------------------------------------------
#if CLITK_PRIVATE_FEATURES
clitk::UsfImageIOFactory::RegisterOneFactory();
clitk::USVoxImageIOFactory::RegisterOneFactory();
+ clitk::SvlImageIOFactory::RegisterOneFactory();
#endif
clitk::GateAsciiImageIOFactory::RegisterOneFactory();
clitk::DicomRTDoseIOFactory::RegisterOneFactory();
+++ /dev/null
-/*=========================================================================
- 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 */
-
+++ /dev/null
-/*=========================================================================
- 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 */
-
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);
{
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);
}
#include <itkImageToImageFilter.h>
#include <itkLabelStatisticsImageFilter.h>
+#include <iomanip>
+
namespace clitk {
//--------------------------------------------------------------------
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;
}
//--------------------------------------------------------------------
// 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);
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))
#=========================================================
# 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)
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)
#include "itkOrientImageFilter.h"
#include "itkSpatialOrientationAdapter.h"
#include "itkImageDuplicator.h"
+#include "itkRelabelComponentImageFilter.h"
+
#include <fcntl.h>
//--------------------------------------------------------------------
SetForegroundValue(1);
SetMinimalComponentSize(100);
VerboseRegionGrowingFlagOff();
+ RemoveSmallLabelBeforeSeparationFlagOn();
// Step 1 default values
SetUpperThreshold(-300);
//--------------------------------------------------------------------
//--------------------------------------------------------------------
StartNewStep("Separate Left/Right lungs");
- PrintMemory(GetVerboseMemoryFlag(), "Before Separate");
+ PrintMemory(GetVerboseMemoryFlag(), "Before Separate");
// Initial label
working_mask = Labelize<MaskImageType>(working_mask,
GetBackgroundValue(),
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) {
/*=========================================================================
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
+
+//--------------------------------------------------------------------
--- /dev/null
+#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"
+
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
#ifndef clitkCropImageGenericFilter_cxx
#define clitkCropImageGenericFilter_cxx
-/* =================================================
- * @file clitkCropImageGenericFilter.cxx
- * @author
- * @date
- *
- * @brief
- *
- ===================================================*/
-
#include "clitkCropImageGenericFilter.h"
-
//-----------------------------------------------------------
// Constructor
//-----------------------------------------------------------
- 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"
clitk::ImageStatisticsGenericFilter::Pointer genericFilter=clitk::ImageStatisticsGenericFilter::New();
genericFilter->SetArgsInfo(args_info);
- genericFilter->Update();
+ CLITK_TRY_CATCH_EXIT(genericFilter->Update());
return EXIT_SUCCESS;
}// end main
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
#ifndef clitkImageStatisticsGenericFilter_cxx
#define clitkImageStatisticsGenericFilter_cxx
-/* =================================================
- * @file clitkImageStatisticsGenericFilter.cxx
- * @author
- * @date
- *
- * @brief
- *
- ===================================================*/
-
#include "clitkImageStatisticsGenericFilter.h"
-
namespace clitk
{
m_Verbose=false;
m_InputFileName="";
}
-
+ //-----------------------------------------------------------
+
//-----------------------------------------------------------
// Update
#ifndef clitkImageStatisticsGenericFilter_h
#define clitkImageStatisticsGenericFilter_h
-/* =================================================
- * @file clitkImageStatisticsGenericFilter.h
- * @author
- * @date
- *
- * @brief
- *
- ===================================================*/
-
-
// clitk include
#include "clitkIO.h"
#include "clitkCommon.h"
namespace clitk
{
-
class ITK_EXPORT ImageStatisticsGenericFilter : public itk::LightObject
{
public:
#include "itkNthElementImageAdaptor.h"
#include "itkJoinSeriesImageFilter.h"
-/* =================================================
- * @file clitkImageStatisticsGenericFilter.txx
- * @author
- * @date
- *
- * @brief
- *
- ===================================================*/
#include "clitkImageStatisticsGenericFilter.h"
-
+#include "clitkCropLikeImageFilter.h"
+#include "clitkResampleImageWithOptionsFilter.h"
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,
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, ®, 0);
+ }
+ else {
+ std::cerr << "Mask image has a different size/spacing than input. Abort" << std::endl;
+ exit(-1);
+ }
+ }
+
}
}
vvToolMIP
vvToolConvert ## with dummy vvToolConvert.ui
vvToolROIManager
+ vvToolSegmentation
## these ones are for tests (not working)
# vvToolFoo
vvSlicer.cxx
vvLandmarks.cxx
vvLandmarksGlyph.cxx
+ vvClipPolyData.cxx
vvGlyphSource.cxx
vvGlyph2D.cxx
vvSlicerManager.cxx
<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/>
--- /dev/null
+#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);
+}
--- /dev/null
+#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
}
mPolyData = vtkPolyData::New();
mIds = vtkFloatArray::New();
+ mLabels = vtkStringArray::New();
+ mLabels->SetName("labels");
}
//--------------------------------------------------------------------
mIds->Delete();
if (mPolyData)
mPolyData->Delete();
+ if (mLabels)
+ mLabels->Delete();
}
//--------------------------------------------------------------------
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);
/*
{
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();
}
//--------------------------------------------------------------------
// 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);
}
mFilename = filename;
mLandmarks.clear();
+ vtkIdType idPoint;
char line[255];
for (unsigned int i = 0; i < mPoints.size(); i++)
mPoints[i]->SetNumberOfPoints(0);
// 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);
if (time >= 0 && time <= ((int)mPoints.size() -1)) {
mPolyData->SetPoints(mPoints[time]);
mPolyData->GetPointData()->SetScalars(mIds);
+ mPolyData->GetPointData()->AddArray(mLabels);
mPolyData->Modified();
mPolyData->Update();
}
#include "vtkPolyData.h"
#include "vtkPoints.h"
#include "vvLandmarksGlyph.h"
+#include "vtkStringArray.h"
//typedef
struct vvLandmark {
std::vector<vtkPoints*> mPoints;
vtkFloatArray* mIds;
//std::vector<vvLandmarksGlyph*> mText;
+ vtkStringArray* mLabels;
std::string mFilename;
int mFormatVersion;
};
#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
//------------------------------------------------------------------------------
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();
{
mIsVisible = true;
mIsContourVisible = false;
- mOpacity = 0.7;
+ mOpacity = 0.5;
mIsSelected = false;
mContourWidth = 1;
mContourColor.resize(3);
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);
#include <vtkDataArray.h>
#include <vtkFloatArray.h>
#include <vtkClipPolyData.h>
+#include <vtkActor2DCollection.h>
#include <vtkGlyph3D.h>
#include <vtkMath.h>
#include <vtkCursor3D.h>
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);
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);
{
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]);
+ }
}
}
#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;
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;
}
//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::EmitMousePositionUpdated(int slicer)
+{
+ emit MousePositionUpdatedSignal(slicer);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::EmitKeyPressed(std::string KeyPress)
+{
+ emit KeyPressedSignal(KeyPress);
+}
+//----------------------------------------------------------------------------
+
+
//----------------------------------------------------------------------------
void vvSlicerManager::SetSliceOrientation(int slicer, int orientation)
{
}
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;
}
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);
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);
this->SM->UpdateSliceRange(VisibleInWindow);
}
+ this->SM->EmitKeyPressed(KeyPress);
}
//All type of mouse events
return;
}
- //DD(event);
// Mouse release HERE
if (event == vtkCommand::EndPickEvent) {
// DD(VisibleInWindow);
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());
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();
}
//------------------------------------------------------------------------------
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();
- 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>
// 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.
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"
+
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
vvToolSegmentation::~vvToolSegmentation()
{
+ DD("destructor");
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
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;
// 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)));
}
//------------------------------------------------------------------------------
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();
}
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();
}
//------------------------------------------------------------------------------
-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();
}
//------------------------------------------------------------------------------
#include "vvROIActor.h"
#include "ui_vvToolSegmentation.h"
+#include "vtkLookupTable.h"
+
//------------------------------------------------------------------------------
class vvToolSegmentation:
public vvToolWidgetBase,
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
//------------------------------------------------------------------------------