( (bbBoxProcessModeIsManual()==true)&&(bbLetRecursiveExecuteManualMode==true) )
)
{
-
+
// printf("EED BlackBox::bbRecursiveExecute bbProcess start %s \n", bbGetFullName().c_str() );
//auto start = std::chrono::high_resolution_clock::now();
std::string v;
// Looks for the adaptor
if (bbGetOutputType(output).name() != typeid(std::string).name() )
- {
- // Look for factory
- Package::Pointer p = bbGetDescriptor()->GetPackage();
- if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
- {
- Factory::Pointer f = p->GetFactorySet().begin()->lock();
- BlackBox::Pointer a;
- try
- {
- a = f->NewAdaptor(
- bbGetOutputType(output),
- typeid(std::string),
- "");
- } catch (bbtk::Exception e)
- {
- }
- if (a){
- // bbUpdate();
- a->bbSetInput("In",bbGetOutput(output));
- a->bbExecute();
- v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
- } else {
- v="? (no adaptor found)";
- }
- }
- else
- {
- v="? (no factory found)";
- }
- }
- else
- {
- // bbUpdate();
- v = bbGetOutput(output).unsafe_get<std::string>() ;
- }
+ {
+ // Look for factory
+ Package::Pointer p = bbGetDescriptor()->GetPackage();
+ if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
+ {
+ Factory::Pointer f = p->GetFactorySet().begin()->lock();
+ BlackBox::Pointer a;
+ try {
+ a = f->NewAdaptor( bbGetOutputType(output), typeid(std::string), "");
+ } catch (bbtk::Exception e) {
+ }
+ if (a)
+ {
+ // bbUpdate();
+ a->bbSetInput("In",bbGetOutput(output));
+ a->bbExecute();
+ v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
+ } else {
+ v="? (no adaptor found)";
+ } // if a
+ } else {
+ v="? (no factory found)";
+ } // if p
+ } else {
+ // bbUpdate();
+ v = bbGetOutput(output).unsafe_get<std::string>() ;
+ } // name
return v;
}
//=========================================================================
mTo->bbSetInput( mInput,
mFrom->bbGetOutput(mOutput),
false);
- }
- else
- {
+ } else {
// 2) Look for an adaptor
bbtk::BlackBox::Pointer adaptor;
try
- {
+ {
adaptor = mFactory.lock()
->NewAdaptor(mFrom->bbGetOutput(mOutput).type(),
mTo->bbGetInputType(mInput),
pkgname,
path);
if (p!=0)
- {
- //===================================================================
- bbtkMessage("output",2,p->GetName()<<" "
+ {
+ //===================================================================
+ bbtkMessage("output",2,p->GetName()<<" "
<<p->GetVersion()
<<" "
<<p->GetAuthor() << " Category(s) :"
<<p->GetCategory()
<<std::endl);
- bbtkMessage("output",2,p->GetDescription()<<std::endl);
- //===================================================================
- p->AddFactory(GetThisPointer<Factory>());
- mPackageMap[pkgname] = p;
- return true;
- }
+ bbtkMessage("output",2,p->GetDescription()<<std::endl);
+ //===================================================================
+ p->AddFactory(GetThisPointer<Factory>());
+ mPackageMap[pkgname] = p;
+ return true;
+ } // if p
return false;
}
<<typein<<","
<<typeout<<",\""
<<name<<"\")"<<bbtkendl);
-
-
BlackBox::Pointer b;
PackageMapType::const_iterator i;
for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
- {
- b = i->second->NewAdaptor(typein,typeout,name);
- if (b) break;
- }
- if (!b)
- {
- bbtkError("no "<<typein<<" to "<<typeout
- <<" adaptor available");
- }
-
+ {
+ b = i->second->NewAdaptor(typein,typeout,name);
+ if (b) break;
+ } if (!b) {
+ bbtkError("no "<<typein<<" to "<<typeout<<" adaptor available in connection: "<< name);
+ }
bbtkDebugDecTab("kernel",7);
return b;
}
//===================================================================
-
//===================================================================
/// Creates an instance of a black box of type <type> with name <name>
BlackBox::Pointer Factory::NewWidgetAdaptor(const DataInfo& typein,
<<typeout<<",\""
<<name<<"\")"<<bbtkendl);
- AdaptorKey key(typein,typeout,
- BlackBoxDescriptor::DEFAULT_ADAPTOR);
+ AdaptorKey key(typein,typeout,BlackBoxDescriptor::DEFAULT_ADAPTOR);
AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
if (i == mAdaptorMap.end())
- {
- bbtkDebugDecTab("kernel",8);
- return BlackBox::Pointer();
- }
+ {
+ bbtkDebugDecTab("kernel",8);
+ return BlackBox::Pointer();
+ }
BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
bbtkDebugDecTab("kernel",8);
return bb;
DescriptorMapType::iterator i = mDescriptorMap.find(d->GetTypeName());
if (i!=mDescriptorMap.end())
- {
- bbtkWarning("Package<"<<GetName()<<"> : Trying to register box type <"
+ {
+ bbtkWarning("Package<"<<GetName()<<"> : Trying to register box type <"
<<d->GetTypeName()<<"> which is already in the package");
- return false;
- }
+ return false;
+ }
mDescriptorMap[d->GetTypeName()] = d;
// d->Reference();
// If it is a default adaptor, also register it in the adaptors map
if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_ADAPTOR )
- {
- bbtkDebugMessage("kernel",8,"Package<"<<GetName()<<">::Register(\""<<d->GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<<std::endl);
+ {
+ bbtkDebugMessage("kernel",8,"Package<"<<GetName()<<">::Register(\""<<d->GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<<std::endl);
- TypeInfo typein = d->GetInputDescriptor("In")->GetTypeInfo();
- TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
- DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature());
- DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
- AdaptorKey key(infoin,infoout,d->GetKind());
+ TypeInfo typein = d->GetInputDescriptor("In")->GetTypeInfo();
+ TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
+ DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature());
+ DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
+ AdaptorKey key(infoin,infoout,d->GetKind());
- AdaptorMapType::const_iterator i;
- i = mAdaptorMap.find(key);
- if (i == mAdaptorMap.end())
- {
- mAdaptorMap[key] = d;
- }
- // If already an adaptor registered : error
- else
- {
- if (i->second.lock()->GetTypeName() != d->GetTypeName())
- {
- bbtkError("Package <"<<GetName()<<
- "> : trying to register black box <"
- <<d->GetTypeName()
- <<"> as default adaptor but there is already a default adaptor registered (<"
- <<i->second.lock()->GetTypeName()<<">)");
- }
- }
- }
+ AdaptorMapType::const_iterator i;
+ i = mAdaptorMap.find(key);
+ if (i == mAdaptorMap.end())
+ {
+ mAdaptorMap[key] = d;
+ } else { // If already an adaptor registered : error
+ if (i->second.lock()->GetTypeName() != d->GetTypeName())
+ {
+ bbtkError("Package <"<<GetName()<<
+ "> : trying to register black box <"
+ <<d->GetTypeName()
+ <<"> as default adaptor but there is already a default adaptor registered (<"
+ <<i->second.lock()->GetTypeName()<<">)");
+ } // if name
+ }// if i
+ } // if kind
// If it is a default adaptor, also register it in the adaptors map
else if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_GUI)
{
--- /dev/null
+# ----------------------------------
+# - BBTKGEditor v 1.6 BBG BlackBox Diagram file
+# - /Users/davila/Creatis/C23/creatools_source/bbtk/packages/itk/bbs/appli/exampleThinningImageFilter3D.bbg
+# ----------------------------------
+
+APP_START
+CATEGORY:<VOID>
+DESCRIPTION:Description ??
+AUTHOR:Author ??
+EXPORTFORMAT:0
+COMPLEXBOX:FALSE
+COMPLEXINPUTS:0
+BOXES:5
+BOX
+vtk:LoadHola:Box00
+ISEXEC:FALSE
+-10.742698:32.159670:-900.000000
+10.807302:29.659670:-900.000000
+FIN_BOX
+BOX
+creaMaracasVisu:ImageChangeInformation:Box01
+ISEXEC:FALSE
+-11.837496:23.127593:-900.000000
+11.312504:20.627593:-900.000000
+FIN_BOX
+BOX
+itk:TubularStructures_Sato:Box02
+ISEXEC:FALSE
+-21.074848:6.431934:-900.000000
+1.720152:3.931934:-900.000000
+FIN_BOX
+BOX
+vtk:RescaleSlopeIntercept:Box03
+ISEXEC:FALSE
+-17.379907:13.958665:-900.000000
+5.445093:11.458665:-900.000000
+PORT
+OutputFormat:"VTK_DOUBLE"
+FIN_BOX
+BOX
+creaMaracasVisu:ViewerNV:Box04
+ISEXEC:TRUE
+-21.348547:-6.979333:-900.000000
+20.771453:-9.479333:-900.000000
+FIN_BOX
+CONNECTIONS:3
+CONNECTION
+Box00:Out:Box01:In
+NumberOfControlPoints:0
+CONNECTION
+Box01:Out:Box03:In
+NumberOfControlPoints:0
+CONNECTION
+Box03:Out:Box02:In
+NumberOfControlPoints:0
+APP_END
--- /dev/null
+# ----------------------------------
+# - BBTKGEditor v 1.6 BBS BlackBox Script
+# - /Users/davila/Creatis/C23/creatools_source/bbtk/packages/itk/bbs/appli/exampleThinningImageFilter3D.bbs
+# ----------------------------------
+
+# BBTK GEditor Script
+# ----------------------
+
+include std
+include itkvtk
+include vtk
+include creaMaracasVisu
+include itk
+
+author "Author ??"
+description "Description ??"
+category "<VOID>"
+
+new vtk:LoadHola Box00
+
+new creaMaracasVisu:ImageChangeInformation Box01
+
+new itk:TubularStructures_Sato Box02
+
+new vtk:RescaleSlopeIntercept Box03
+ set Box03.OutputFormat "VTK_DOUBLE"
+
+new creaMaracasVisu:ViewerNV Box04
+
+
+connect Box00.Out Box01.In
+
+connect Box01.Out Box03.In
+
+connect Box03.Out Box02.In
+
+
+
+# Complex input ports
+exec Box04
--- /dev/null
+//=====
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//=====
+#include "bbitkThinningImageFilter3D.h"
+#include "bbitkPackage.h"
+namespace bbitk
+{
+ BBTK_ADD_BLACK_BOX_TO_PACKAGE(itk,ThinningImageFilter3D)
+ BBTK_BLACK_BOX_IMPLEMENTATION(ThinningImageFilter3D,bbtk::AtomicBlackBox);
+}// EO namespace bbitk
+
+
--- /dev/null
+//=====
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//=====
+#ifndef __bbitkThinningImageFilter3D_h_INCLUDED__
+#define __bbitkThinningImageFilter3D_h_INCLUDED__
+
+#include "bbitk_EXPORT.h"
+#include "bbtkAtomicBlackBox.h"
+#include "iostream"
+
+#include "itkBinaryThinningImageFilter3D.hxx"
+
+#include "bbitkImage.h"
+
+namespace bbitk
+{
+
+class bbitk_EXPORT ThinningImageFilter3D
+:
+public bbtk::AtomicBlackBox
+{
+ BBTK_BLACK_BOX_INTERFACE(ThinningImageFilter3D,bbtk::AtomicBlackBox);
+ //=====
+ // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+ //=====
+ BBTK_DECLARE_INPUT(In,anyImagePointer);
+ BBTK_DECLARE_OUTPUT(Out,anyImagePointer);
+
+ BBTK_PROCESS(ProcessSwitch);
+ private :
+ inline void ProcessSwitch();
+ template <class T> void Process();
+ itk::Object *mOutput;
+
+ //=====
+ // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+ //=====
+};
+
+BBTK_BEGIN_DESCRIBE_BLACK_BOX(ThinningImageFilter3D,bbtk::AtomicBlackBox);
+ BBTK_NAME("ThinningImageFilter3D");
+ BBTK_AUTHOR("InfoDev");
+ BBTK_DESCRIPTION("No Description.");
+ BBTK_CATEGORY("empty");
+ BBTK_INPUT(ThinningImageFilter3D,In,"Image (SHORT format)",anyImagePointer,"");
+ BBTK_OUTPUT(ThinningImageFilter3D,Out,"Output image ",anyImagePointer,"");
+BBTK_END_DESCRIBE_BLACK_BOX(ThinningImageFilter3D);
+//=====
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//=====
+
+//===================================================
+void ThinningImageFilter3D::ProcessSwitch()
+{
+ bbtk::TypeInfo t = bbGetInputIn().type();
+// BBTK_TEMPLATE_ITK_IMAGE_SWITCH(t, this->Process);
+// BBTK_TEMPLATE_ITK_IMAGE_DIM_3_SWITCH(t, this->Process , "Error format. (you need 3D short,float,double)") ;
+
+ BBTK_BEGIN_TEMPLATE_SWITCH(t)
+// BBTK_SWITCH_ITK_IMAGE_short_3(t,this->Process,)
+ BBTK_SWITCH_ITK_IMAGE_int16_t_3(t,this->Process,)
+// BBTK_SWITCH_ITK_IMAGE_float_3(t,this->Process,)
+// BBTK_SWITCH_ITK_IMAGE_double_3(t,this->Process,)
+ BBTK_END_TEMPLATE_SWITCH(t)
+}
+
+//=====
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//=====
+template <class T>
+void ThinningImageFilter3D::Process()
+{
+ //
+ // https://github.com/thewtex/ITKBinaryThinningImageFilter3D
+ //
+ printf("EED ThinningImageFilter3D::Process Start\n");
+
+ // Verify the number of parameters in the command line
+// if (argc <= 2)
+// {
+// std::cerr << "Usage: " << std::endl;
+// std::cerr << argv[0] << " inputImageFile outputImageFile" << std::endl;
+// return EXIT_FAILURE;
+// }
+// char *infilename = argv[1];
+// char *outfilename = argv[2];
+//
+ const unsigned int Dimension = 3;
+ typedef signed short PixelType; // must be signed for CT since Hounsfield units can be < 0
+ typedef itk::Image<PixelType, Dimension> ImageType;
+
+// // Read image
+// typedef itk::ImageFileReader<ImageType> ReaderType;
+// ReaderType::Pointer reader = ReaderType::New();
+// reader->SetFileName(infilename);
+// try
+// {
+// reader->Update();
+// }
+// catch (itk::ExceptionObject &ex)
+// {
+// std::cout << ex << std::endl;
+// return EXIT_FAILURE;
+// }
+// cout << infilename << " sucessfully read." << endl;
+
+ // Define the thinning filter
+ typedef itk::BinaryThinningImageFilter3D<ImageType, ImageType> ThinningFilterType;
+ ThinningFilterType::Pointer thinningFilter = ThinningFilterType::New();
+
+ T* inputImage = this->bbGetInputIn().get<T*>();
+// thinningFilter->SetInput( reader->GetOutput() );
+ thinningFilter->SetInput( inputImage );
+
+ thinningFilter->Update();
+ thinningFilter->GetOutput()->Register();
+
+
+// // output to file
+// typedef itk::ImageFileWriter<ImageType> WriterType;
+// WriterType::Pointer writer = WriterType::New();
+// writer->SetInput(thinningFilter->GetOutput());
+// writer->SetFileName(outfilename);
+//
+// try
+// {
+// writer->Update();
+// }
+// catch (itk::ExceptionObject &ex)
+// {
+// std::cout << ex << std::endl;
+// return EXIT_FAILURE;
+// }
+// cout << outfilename << " sucessfully written." << endl;
+
+// cout << "Program terminated normally." << endl;
+// return EXIT_SUCCESS;
+
+ if (mOutput) mOutput->UnRegister();
+ this->bbSetOutputOut( thinningFilter->GetOutput() );
+ mOutput = thinningFilter->GetOutput();
+ printf("EED ThinningImageFilter3D::Process End\n");
+}
+
+//=====
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//=====
+void ThinningImageFilter3D::bbUserSetDefaultValues()
+{
+ mOutput = 0;
+}
+
+//=====
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//=====
+void ThinningImageFilter3D::bbUserInitializeProcessing()
+{
+}
+
+//=====
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//=====
+void ThinningImageFilter3D::bbUserFinalizeProcessing()
+{
+}
+
+}// EO namespace bbitk
+#endif // __bbitkThinningImageFilter3D_h_INCLUDED__
+
--- /dev/null
+/*=========================================================================
+ *
+ * Copyright Insight Software Consortium
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *=========================================================================*/
+#ifndef itkBinaryThinningImageFilter3D_h
+#define itkBinaryThinningImageFilter3D_h
+
+#include <itkNeighborhoodIterator.h>
+#include <itkImageToImageFilter.h>
+#include <itkImageRegionIteratorWithIndex.h>
+#include <itkConstantBoundaryCondition.h>
+
+namespace itk
+{
+/** \class BinaryThinningImageFilter3D
+*
+* \brief This filter computes one-pixel-wide skeleton of a 3D input image.
+*
+* This class is parametrized over the type of the input image
+* and the type of the output image.
+*
+* The input is assumed to be a binary image. All non-zero valued voxels
+* are set to 1 internally to simplify the computation. The filter will
+* produce a skeleton of the object. The output background values are 0,
+* and the foreground values are 1.
+*
+* A 26-neighbourhood configuration is used for the foreground and a
+* 6-neighbourhood configuration for the background. Thinning is performed
+* symmetrically in order to guarantee that the skeleton lies medial within
+* the object.
+*
+* This filter is a parallel thinning algorithm and is an implementation
+* of the algorithm described in:
+*
+* T.C. Lee, R.L. Kashyap, and C.N. Chu.
+* Building skeleton models via 3-D medial surface/axis thinning algorithms.
+* Computer Vision, Graphics, and Image Processing, 56(6):462--478, 1994.
+*
+* To do: Make use of multi-threading.
+*
+* \author Hanno Homann, Oxford University, Wolfson Medical Vision Lab, UK.
+*
+* \sa MorphologyImageFilter
+* \ingroup ImageEnhancement MathematicalMorphologyImageFilters BinaryThinningImageFilter3D
+*/
+
+template <class TInputImage, class TOutputImage>
+class BinaryThinningImageFilter3D : public ImageToImageFilter<TInputImage, TOutputImage>
+{
+public:
+ /** Standard class typedefs. */
+ typedef BinaryThinningImageFilter3D Self;
+ typedef ImageToImageFilter<TInputImage, TOutputImage> Superclass;
+ typedef SmartPointer<Self> Pointer;
+ typedef SmartPointer<const Self> ConstPointer;
+
+ /** Method for creation through the object factory */
+ itkNewMacro(Self);
+
+ /** Run-time type information (and related methods). */
+ itkTypeMacro(BinaryThinningImageFilter3D, ImageToImageFilter);
+
+ /** Type for input image. */
+ typedef TInputImage InputImageType;
+
+ /** Type for output image: Skelenton of the object. */
+ typedef TOutputImage OutputImageType;
+
+ /** Type for the region of the input image. */
+ typedef typename InputImageType::RegionType RegionType;
+
+ /** Type for the index of the input image. */
+ typedef typename RegionType::IndexType IndexType;
+
+ /** Type for the pixel type of the input image. */
+ typedef typename InputImageType::PixelType InputImagePixelType;
+
+ /** Type for the pixel type of the input image. */
+ typedef typename OutputImageType::PixelType OutputImagePixelType;
+
+ /** Type for the size of the input image. */
+ typedef typename RegionType::SizeType SizeType;
+
+ /** Pointer Type for input image. */
+ typedef typename InputImageType::ConstPointer InputImagePointer;
+
+ /** Pointer Type for the output image. */
+ typedef typename OutputImageType::Pointer OutputImagePointer;
+
+ /** Boundary condition type for the neighborhood iterator */
+ typedef ConstantBoundaryCondition<TInputImage> ConstBoundaryConditionType;
+
+ /** Neighborhood iterator type */
+ typedef NeighborhoodIterator<TInputImage, ConstBoundaryConditionType> NeighborhoodIteratorType;
+
+ /** Neighborhood type */
+ typedef typename NeighborhoodIteratorType::NeighborhoodType NeighborhoodType;
+
+ /** Get Skelenton by thinning image. */
+ OutputImageType *GetThinning(void);
+
+ /** ImageDimension enumeration */
+ itkStaticConstMacro(InputImageDimension, unsigned int,
+ TInputImage::ImageDimension);
+ itkStaticConstMacro(OutputImageDimension, unsigned int,
+ TOutputImage::ImageDimension);
+
+#ifdef ITK_USE_CONCEPT_CHECKING
+ /** Begin concept checking */
+ itkConceptMacro(SameDimensionCheck,
+ (Concept::SameDimension<InputImageDimension, 3>));
+ itkConceptMacro(SameTypeCheck,
+ (Concept::SameType<InputImagePixelType, OutputImagePixelType>));
+ itkConceptMacro(InputAdditiveOperatorsCheck,
+ (Concept::AdditiveOperators<InputImagePixelType>));
+ itkConceptMacro(InputConvertibleToIntCheck,
+ (Concept::Convertible<InputImagePixelType, int>));
+ itkConceptMacro(IntConvertibleToInputCheck,
+ (Concept::Convertible<int, InputImagePixelType>));
+ itkConceptMacro(InputIntComparableCheck,
+ (Concept::Comparable<InputImagePixelType, int>));
+ /** End concept checking */
+#endif
+
+protected:
+ BinaryThinningImageFilter3D();
+ virtual ~BinaryThinningImageFilter3D(){};
+ void PrintSelf(std::ostream &os, Indent indent) const;
+
+ /** Compute thinning Image. */
+ void GenerateData();
+
+ /** Prepare data. */
+ void PrepareData();
+
+ /** Compute thinning Image. */
+ void ComputeThinImage();
+
+ /** isEulerInvariant [Lee94] */
+ bool isEulerInvariant(NeighborhoodType neighbors, int *LUT);
+ void fillEulerLUT(int *LUT);
+ /** isSimplePoint [Lee94] */
+ bool isSimplePoint(NeighborhoodType neighbors);
+ /** Octree_labeling [Lee94] */
+ void Octree_labeling(int octant, int label, int *cube);
+
+private:
+ BinaryThinningImageFilter3D(const Self &); //purposely not implemented
+ void operator=(const Self &); //purposely not implemented
+
+}; // end of BinaryThinningImageFilter3D class
+
+} //end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkBinaryThinningImageFilter3D.hxx"
+#endif
+
+#endif // itkBinaryThinningImageFilter3D_h
--- /dev/null
+/*=========================================================================
+ *
+ * Copyright Insight Software Consortium
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *=========================================================================*/
+#ifndef itkBinaryThinningImageFilter3D_hxx
+#define itkBinaryThinningImageFilter3D_hxx
+
+#include <iostream>
+
+#include "itkBinaryThinningImageFilter3D.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkImageRegionIterator.h"
+#include "itkNeighborhoodIterator.h"
+#include <vector>
+
+namespace itk
+{
+/**
+ * Constructor
+ */
+template <class TInputImage, class TOutputImage>
+BinaryThinningImageFilter3D<TInputImage, TOutputImage>::BinaryThinningImageFilter3D()
+{
+
+ this->SetNumberOfRequiredOutputs(1);
+
+ OutputImagePointer thinImage = OutputImageType::New();
+ this->SetNthOutput(0, thinImage.GetPointer());
+}
+
+/**
+ * Return the thinning Image pointer
+ */
+template <class TInputImage, class TOutputImage>
+typename BinaryThinningImageFilter3D<
+ TInputImage, TOutputImage>::OutputImageType *
+BinaryThinningImageFilter3D<TInputImage, TOutputImage>::GetThinning(void)
+{
+ return dynamic_cast<OutputImageType *>(
+ this->ProcessObject::GetOutput(0));
+}
+
+/**
+ * Prepare data for computation
+ * Copy the input image to the output image, changing from the input
+ * type to the output type.
+ */
+template <class TInputImage, class TOutputImage>
+void BinaryThinningImageFilter3D<TInputImage, TOutputImage>::PrepareData(void)
+{
+
+ itkDebugMacro(<< "PrepareData Start");
+ OutputImagePointer thinImage = GetThinning();
+
+ InputImagePointer inputImage =
+ dynamic_cast<const TInputImage *>(ProcessObject::GetInput(0));
+
+ thinImage->SetBufferedRegion(thinImage->GetRequestedRegion());
+ thinImage->Allocate();
+
+ typename OutputImageType::RegionType region = thinImage->GetRequestedRegion();
+
+ ImageRegionConstIterator<TInputImage> it(inputImage, region);
+ ImageRegionIterator<TOutputImage> ot(thinImage, region);
+
+ it.GoToBegin();
+ ot.GoToBegin();
+
+ itkDebugMacro(<< "PrepareData: Copy input to output");
+
+ // Copy the input to the output, changing all foreground pixels to
+ // have value 1 in the process.
+ while (!ot.IsAtEnd())
+ {
+ if (it.Get())
+ {
+ ot.Set(NumericTraits<OutputImagePixelType>::One);
+ }
+ else
+ {
+ ot.Set(NumericTraits<OutputImagePixelType>::Zero);
+ }
+ ++it;
+ ++ot;
+ }
+ itkDebugMacro(<< "PrepareData End");
+}
+
+/**
+ * Post processing for computing thinning
+ */
+template <class TInputImage, class TOutputImage>
+void BinaryThinningImageFilter3D<TInputImage, TOutputImage>::ComputeThinImage()
+{
+ itkDebugMacro(<< "ComputeThinImage Start");
+ OutputImagePointer thinImage = GetThinning();
+
+ typename OutputImageType::RegionType region = thinImage->GetRequestedRegion();
+
+ ConstBoundaryConditionType boundaryCondition;
+ boundaryCondition.SetConstant(0);
+
+ typename NeighborhoodIteratorType::RadiusType radius;
+ radius.Fill(1);
+ NeighborhoodIteratorType ot(radius, thinImage, region);
+ ot.SetBoundaryCondition(boundaryCondition);
+
+ std::vector<IndexType> simpleBorderPoints;
+ typename std::vector<IndexType>::iterator simpleBorderPointsIt;
+
+ // Define offsets
+ typedef typename NeighborhoodIteratorType::OffsetType OffsetType;
+ OffsetType N = {{0, -1, 0}}; // north
+ OffsetType S = {{0, 1, 0}}; // south
+ OffsetType E = {{1, 0, 0}}; // east
+ OffsetType W = {{-1, 0, 0}}; // west
+ OffsetType U = {{0, 0, 1}}; // up
+ OffsetType B = {{0, 0, -1}}; // bottom
+
+ // prepare Euler LUT [Lee94]
+ int eulerLUT[256];
+ fillEulerLUT(eulerLUT);
+ // Loop through the image several times until there is no change.
+ int unchangedBorders = 0;
+ while (unchangedBorders < 6) // loop until no change for all the six border types
+ {
+ unchangedBorders = 0;
+ for (int currentBorder = 1; currentBorder <= 6; currentBorder++)
+ {
+ // Loop through the image.
+ for (ot.GoToBegin(); !ot.IsAtEnd(); ++ot)
+ {
+ // check if point is foreground
+ if (ot.GetCenterPixel() != 1)
+ {
+ continue; // current point is already background
+ }
+ // check 6-neighbors if point is a border point of type currentBorder
+ bool isBorderPoint = false;
+ if (currentBorder == 1 && ot.GetPixel(N) <= 0)
+ isBorderPoint = true;
+ if (currentBorder == 2 && ot.GetPixel(S) <= 0)
+ isBorderPoint = true;
+ if (currentBorder == 3 && ot.GetPixel(E) <= 0)
+ isBorderPoint = true;
+ if (currentBorder == 4 && ot.GetPixel(W) <= 0)
+ isBorderPoint = true;
+ if (currentBorder == 5 && ot.GetPixel(U) <= 0)
+ isBorderPoint = true;
+ if (currentBorder == 6 && ot.GetPixel(B) <= 0)
+ isBorderPoint = true;
+ if (!isBorderPoint)
+ {
+ continue; // current point is not deletable
+ }
+ // check if point is the end of an arc
+ int numberOfNeighbors = -1; // -1 and not 0 because the center pixel will be counted as well
+ for (int i = 0; i < 27; i++) // i = 0..26
+ if (ot.GetPixel(i) == 1)
+ numberOfNeighbors++;
+
+ if (numberOfNeighbors == 1)
+ {
+ continue; // current point is not deletable
+ }
+
+ // check if point is Euler invariant
+ if (!isEulerInvariant(ot.GetNeighborhood(), eulerLUT))
+ {
+ continue; // current point is not deletable
+ }
+
+ // check if point is simple (deletion does not change connectivity in the 3x3x3 neighborhood)
+ if (!isSimplePoint(ot.GetNeighborhood()))
+ {
+ continue; // current point is not deletable
+ }
+
+ // add all simple border points to a list for sequential re-checking
+ simpleBorderPoints.push_back(ot.GetIndex());
+ } // end image iteration loop
+
+ // sequential re-checking to preserve connectivity when
+ // deleting in a parallel way
+ bool noChange = true;
+ for (simpleBorderPointsIt = simpleBorderPoints.begin(); simpleBorderPointsIt != simpleBorderPoints.end(); simpleBorderPointsIt++)
+ {
+ // 1. Set simple border point to 0
+ thinImage->SetPixel(*simpleBorderPointsIt, NumericTraits<OutputImagePixelType>::Zero);
+ // 2. Check if neighborhood is still connected
+ ot.SetLocation(*simpleBorderPointsIt);
+ if (!isSimplePoint(ot.GetNeighborhood()))
+ {
+ // we cannot delete current point, so reset
+ thinImage->SetPixel(*simpleBorderPointsIt, NumericTraits<OutputImagePixelType>::One);
+ }
+ else
+ {
+ noChange = false;
+ }
+ }
+ if (noChange)
+ unchangedBorders++;
+
+ simpleBorderPoints.clear();
+ } // end currentBorder for loop
+ } // end unchangedBorders while loop
+
+ itkDebugMacro(<< "ComputeThinImage End");
+}
+
+/**
+ * Generate ThinImage
+ */
+template <class TInputImage, class TOutputImage>
+void BinaryThinningImageFilter3D<TInputImage, TOutputImage>::GenerateData()
+{
+
+ this->PrepareData();
+
+ itkDebugMacro(<< "GenerateData: Computing Thinning Image");
+ this->ComputeThinImage();
+} // end GenerateData()
+
+/**
+ * Fill the Euler look-up table (LUT) for later check of the Euler invariance. (see [Lee94])
+ */
+template <class TInputImage, class TOutputImage>
+void BinaryThinningImageFilter3D<TInputImage, TOutputImage>::fillEulerLUT(int *LUT)
+{
+ LUT[1] = 1;
+ LUT[3] = -1;
+ LUT[5] = -1;
+ LUT[7] = 1;
+ LUT[9] = -3;
+ LUT[11] = -1;
+ LUT[13] = -1;
+ LUT[15] = 1;
+ LUT[17] = -1;
+ LUT[19] = 1;
+ LUT[21] = 1;
+ LUT[23] = -1;
+ LUT[25] = 3;
+ LUT[27] = 1;
+ LUT[29] = 1;
+ LUT[31] = -1;
+ LUT[33] = -3;
+ LUT[35] = -1;
+ LUT[37] = 3;
+ LUT[39] = 1;
+ LUT[41] = 1;
+ LUT[43] = -1;
+ LUT[45] = 3;
+ LUT[47] = 1;
+ LUT[49] = -1;
+ LUT[51] = 1;
+
+ LUT[53] = 1;
+ LUT[55] = -1;
+ LUT[57] = 3;
+ LUT[59] = 1;
+ LUT[61] = 1;
+ LUT[63] = -1;
+ LUT[65] = -3;
+ LUT[67] = 3;
+ LUT[69] = -1;
+ LUT[71] = 1;
+ LUT[73] = 1;
+ LUT[75] = 3;
+ LUT[77] = -1;
+ LUT[79] = 1;
+ LUT[81] = -1;
+ LUT[83] = 1;
+ LUT[85] = 1;
+ LUT[87] = -1;
+ LUT[89] = 3;
+ LUT[91] = 1;
+ LUT[93] = 1;
+ LUT[95] = -1;
+ LUT[97] = 1;
+ LUT[99] = 3;
+ LUT[101] = 3;
+ LUT[103] = 1;
+
+ LUT[105] = 5;
+ LUT[107] = 3;
+ LUT[109] = 3;
+ LUT[111] = 1;
+ LUT[113] = -1;
+ LUT[115] = 1;
+ LUT[117] = 1;
+ LUT[119] = -1;
+ LUT[121] = 3;
+ LUT[123] = 1;
+ LUT[125] = 1;
+ LUT[127] = -1;
+ LUT[129] = -7;
+ LUT[131] = -1;
+ LUT[133] = -1;
+ LUT[135] = 1;
+ LUT[137] = -3;
+ LUT[139] = -1;
+ LUT[141] = -1;
+ LUT[143] = 1;
+ LUT[145] = -1;
+ LUT[147] = 1;
+ LUT[149] = 1;
+ LUT[151] = -1;
+ LUT[153] = 3;
+ LUT[155] = 1;
+
+ LUT[157] = 1;
+ LUT[159] = -1;
+ LUT[161] = -3;
+ LUT[163] = -1;
+ LUT[165] = 3;
+ LUT[167] = 1;
+ LUT[169] = 1;
+ LUT[171] = -1;
+ LUT[173] = 3;
+ LUT[175] = 1;
+ LUT[177] = -1;
+ LUT[179] = 1;
+ LUT[181] = 1;
+ LUT[183] = -1;
+ LUT[185] = 3;
+ LUT[187] = 1;
+ LUT[189] = 1;
+ LUT[191] = -1;
+ LUT[193] = -3;
+ LUT[195] = 3;
+ LUT[197] = -1;
+ LUT[199] = 1;
+ LUT[201] = 1;
+ LUT[203] = 3;
+ LUT[205] = -1;
+ LUT[207] = 1;
+
+ LUT[209] = -1;
+ LUT[211] = 1;
+ LUT[213] = 1;
+ LUT[215] = -1;
+ LUT[217] = 3;
+ LUT[219] = 1;
+ LUT[221] = 1;
+ LUT[223] = -1;
+ LUT[225] = 1;
+ LUT[227] = 3;
+ LUT[229] = 3;
+ LUT[231] = 1;
+ LUT[233] = 5;
+ LUT[235] = 3;
+ LUT[237] = 3;
+ LUT[239] = 1;
+ LUT[241] = -1;
+ LUT[243] = 1;
+ LUT[245] = 1;
+ LUT[247] = -1;
+ LUT[249] = 3;
+ LUT[251] = 1;
+ LUT[253] = 1;
+ LUT[255] = -1;
+}
+
+/**
+ * Check for Euler invariance. (see [Lee94])
+ */
+template <class TInputImage, class TOutputImage>
+bool BinaryThinningImageFilter3D<TInputImage, TOutputImage>::isEulerInvariant(NeighborhoodType neighbors, int *LUT)
+{
+ // calculate Euler characteristic for each octant and sum up
+ int EulerChar = 0;
+ unsigned char n;
+ // Octant SWU
+ n = 1;
+ if (neighbors[24] == 1)
+ n |= 128;
+ if (neighbors[25] == 1)
+ n |= 64;
+ if (neighbors[15] == 1)
+ n |= 32;
+ if (neighbors[16] == 1)
+ n |= 16;
+ if (neighbors[21] == 1)
+ n |= 8;
+ if (neighbors[22] == 1)
+ n |= 4;
+ if (neighbors[12] == 1)
+ n |= 2;
+ EulerChar += LUT[n];
+ // Octant SEU
+ n = 1;
+ if (neighbors[26] == 1)
+ n |= 128;
+ if (neighbors[23] == 1)
+ n |= 64;
+ if (neighbors[17] == 1)
+ n |= 32;
+ if (neighbors[14] == 1)
+ n |= 16;
+ if (neighbors[25] == 1)
+ n |= 8;
+ if (neighbors[22] == 1)
+ n |= 4;
+ if (neighbors[16] == 1)
+ n |= 2;
+ EulerChar += LUT[n];
+ // Octant NWU
+ n = 1;
+ if (neighbors[18] == 1)
+ n |= 128;
+ if (neighbors[21] == 1)
+ n |= 64;
+ if (neighbors[9] == 1)
+ n |= 32;
+ if (neighbors[12] == 1)
+ n |= 16;
+ if (neighbors[19] == 1)
+ n |= 8;
+ if (neighbors[22] == 1)
+ n |= 4;
+ if (neighbors[10] == 1)
+ n |= 2;
+ EulerChar += LUT[n];
+ // Octant NEU
+ n = 1;
+ if (neighbors[20] == 1)
+ n |= 128;
+ if (neighbors[23] == 1)
+ n |= 64;
+ if (neighbors[19] == 1)
+ n |= 32;
+ if (neighbors[22] == 1)
+ n |= 16;
+ if (neighbors[11] == 1)
+ n |= 8;
+ if (neighbors[14] == 1)
+ n |= 4;
+ if (neighbors[10] == 1)
+ n |= 2;
+ EulerChar += LUT[n];
+ // Octant SWB
+ n = 1;
+ if (neighbors[6] == 1)
+ n |= 128;
+ if (neighbors[15] == 1)
+ n |= 64;
+ if (neighbors[7] == 1)
+ n |= 32;
+ if (neighbors[16] == 1)
+ n |= 16;
+ if (neighbors[3] == 1)
+ n |= 8;
+ if (neighbors[12] == 1)
+ n |= 4;
+ if (neighbors[4] == 1)
+ n |= 2;
+ EulerChar += LUT[n];
+ // Octant SEB
+ n = 1;
+ if (neighbors[8] == 1)
+ n |= 128;
+ if (neighbors[7] == 1)
+ n |= 64;
+ if (neighbors[17] == 1)
+ n |= 32;
+ if (neighbors[16] == 1)
+ n |= 16;
+ if (neighbors[5] == 1)
+ n |= 8;
+ if (neighbors[4] == 1)
+ n |= 4;
+ if (neighbors[14] == 1)
+ n |= 2;
+ EulerChar += LUT[n];
+ // Octant NWB
+ n = 1;
+ if (neighbors[0] == 1)
+ n |= 128;
+ if (neighbors[9] == 1)
+ n |= 64;
+ if (neighbors[3] == 1)
+ n |= 32;
+ if (neighbors[12] == 1)
+ n |= 16;
+ if (neighbors[1] == 1)
+ n |= 8;
+ if (neighbors[10] == 1)
+ n |= 4;
+ if (neighbors[4] == 1)
+ n |= 2;
+ EulerChar += LUT[n];
+ // Octant NEB
+ n = 1;
+ if (neighbors[2] == 1)
+ n |= 128;
+ if (neighbors[1] == 1)
+ n |= 64;
+ if (neighbors[11] == 1)
+ n |= 32;
+ if (neighbors[10] == 1)
+ n |= 16;
+ if (neighbors[5] == 1)
+ n |= 8;
+ if (neighbors[4] == 1)
+ n |= 4;
+ if (neighbors[14] == 1)
+ n |= 2;
+ EulerChar += LUT[n];
+ if (EulerChar == 0)
+ return true;
+ else
+ return false;
+}
+
+/**
+ * Check if current point is a Simple Point.
+ * This method is named 'N(v)_labeling' in [Lee94].
+ * Outputs the number of connected objects in a neighborhood of a point
+ * after this point would have been removed.
+ */
+template <class TInputImage, class TOutputImage>
+bool BinaryThinningImageFilter3D<TInputImage, TOutputImage>::isSimplePoint(NeighborhoodType neighbors)
+{
+ // copy neighbors for labeling
+ int cube[26];
+ int i;
+ for (i = 0; i < 13; i++) // i = 0..12 -> cube[0..12]
+ cube[i] = neighbors[i];
+ // i != 13 : ignore center pixel when counting (see [Lee94])
+ for (i = 14; i < 27; i++) // i = 14..26 -> cube[13..25]
+ cube[i - 1] = neighbors[i];
+ // set initial label
+ int label = 2;
+ // for all points in the neighborhood
+ for (int i = 0; i < 26; i++)
+ {
+ if (cube[i] == 1) // voxel has not been labelled yet
+ {
+ // start recursion with any octant that contains the point i
+ switch (i)
+ {
+ case 0:
+ case 1:
+ case 3:
+ case 4:
+ case 9:
+ case 10:
+ case 12:
+ Octree_labeling(1, label, cube);
+ break;
+ case 2:
+ case 5:
+ case 11:
+ case 13:
+ Octree_labeling(2, label, cube);
+ break;
+ case 6:
+ case 7:
+ case 14:
+ case 15:
+ Octree_labeling(3, label, cube);
+ break;
+ case 8:
+ case 16:
+ Octree_labeling(4, label, cube);
+ break;
+ case 17:
+ case 18:
+ case 20:
+ case 21:
+ Octree_labeling(5, label, cube);
+ break;
+ case 19:
+ case 22:
+ Octree_labeling(6, label, cube);
+ break;
+ case 23:
+ case 24:
+ Octree_labeling(7, label, cube);
+ break;
+ case 25:
+ Octree_labeling(8, label, cube);
+ break;
+ }
+ label++;
+ if (label - 2 >= 2)
+ {
+ return false;
+ }
+ }
+ }
+ //return label-2; in [Lee94] if the number of connected compontents would be needed
+ return true;
+}
+
+/**
+ * Octree_labeling [Lee94]
+ * This is a recursive method that calulates the number of connected
+ * components in the 3D neighbourhood after the center pixel would
+ * have been removed.
+ */
+template <class TInputImage, class TOutputImage>
+void BinaryThinningImageFilter3D<TInputImage, TOutputImage>::Octree_labeling(int octant, int label, int *cube)
+{
+ // check if there are points in the octant with value 1
+ if (octant == 1)
+ {
+ // set points in this octant to current label
+ // and recurseive labeling of adjacent octants
+ if (cube[0] == 1)
+ cube[0] = label;
+ if (cube[1] == 1)
+ {
+ cube[1] = label;
+ Octree_labeling(2, label, cube);
+ }
+ if (cube[3] == 1)
+ {
+ cube[3] = label;
+ Octree_labeling(3, label, cube);
+ }
+ if (cube[4] == 1)
+ {
+ cube[4] = label;
+ Octree_labeling(2, label, cube);
+ Octree_labeling(3, label, cube);
+ Octree_labeling(4, label, cube);
+ }
+ if (cube[9] == 1)
+ {
+ cube[9] = label;
+ Octree_labeling(5, label, cube);
+ }
+ if (cube[10] == 1)
+ {
+ cube[10] = label;
+ Octree_labeling(2, label, cube);
+ Octree_labeling(5, label, cube);
+ Octree_labeling(6, label, cube);
+ }
+ if (cube[12] == 1)
+ {
+ cube[12] = label;
+ Octree_labeling(3, label, cube);
+ Octree_labeling(5, label, cube);
+ Octree_labeling(7, label, cube);
+ }
+ }
+ if (octant == 2)
+ {
+ if (cube[1] == 1)
+ {
+ cube[1] = label;
+ Octree_labeling(1, label, cube);
+ }
+ if (cube[4] == 1)
+ {
+ cube[4] = label;
+ Octree_labeling(1, label, cube);
+ Octree_labeling(3, label, cube);
+ Octree_labeling(4, label, cube);
+ }
+ if (cube[10] == 1)
+ {
+ cube[10] = label;
+ Octree_labeling(1, label, cube);
+ Octree_labeling(5, label, cube);
+ Octree_labeling(6, label, cube);
+ }
+ if (cube[2] == 1)
+ cube[2] = label;
+ if (cube[5] == 1)
+ {
+ cube[5] = label;
+ Octree_labeling(4, label, cube);
+ }
+ if (cube[11] == 1)
+ {
+ cube[11] = label;
+ Octree_labeling(6, label, cube);
+ }
+ if (cube[13] == 1)
+ {
+ cube[13] = label;
+ Octree_labeling(4, label, cube);
+ Octree_labeling(6, label, cube);
+ Octree_labeling(8, label, cube);
+ }
+ }
+ if (octant == 3)
+ {
+ if (cube[3] == 1)
+ {
+ cube[3] = label;
+ Octree_labeling(1, label, cube);
+ }
+ if (cube[4] == 1)
+ {
+ cube[4] = label;
+ Octree_labeling(1, label, cube);
+ Octree_labeling(2, label, cube);
+ Octree_labeling(4, label, cube);
+ }
+ if (cube[12] == 1)
+ {
+ cube[12] = label;
+ Octree_labeling(1, label, cube);
+ Octree_labeling(5, label, cube);
+ Octree_labeling(7, label, cube);
+ }
+ if (cube[6] == 1)
+ cube[6] = label;
+ if (cube[7] == 1)
+ {
+ cube[7] = label;
+ Octree_labeling(4, label, cube);
+ }
+ if (cube[14] == 1)
+ {
+ cube[14] = label;
+ Octree_labeling(7, label, cube);
+ }
+ if (cube[15] == 1)
+ {
+ cube[15] = label;
+ Octree_labeling(4, label, cube);
+ Octree_labeling(7, label, cube);
+ Octree_labeling(8, label, cube);
+ }
+ }
+ if (octant == 4)
+ {
+ if (cube[4] == 1)
+ {
+ cube[4] = label;
+ Octree_labeling(1, label, cube);
+ Octree_labeling(2, label, cube);
+ Octree_labeling(3, label, cube);
+ }
+ if (cube[5] == 1)
+ {
+ cube[5] = label;
+ Octree_labeling(2, label, cube);
+ }
+ if (cube[13] == 1)
+ {
+ cube[13] = label;
+ Octree_labeling(2, label, cube);
+ Octree_labeling(6, label, cube);
+ Octree_labeling(8, label, cube);
+ }
+ if (cube[7] == 1)
+ {
+ cube[7] = label;
+ Octree_labeling(3, label, cube);
+ }
+ if (cube[15] == 1)
+ {
+ cube[15] = label;
+ Octree_labeling(3, label, cube);
+ Octree_labeling(7, label, cube);
+ Octree_labeling(8, label, cube);
+ }
+ if (cube[8] == 1)
+ cube[8] = label;
+ if (cube[16] == 1)
+ {
+ cube[16] = label;
+ Octree_labeling(8, label, cube);
+ }
+ }
+ if (octant == 5)
+ {
+ if (cube[9] == 1)
+ {
+ cube[9] = label;
+ Octree_labeling(1, label, cube);
+ }
+ if (cube[10] == 1)
+ {
+ cube[10] = label;
+ Octree_labeling(1, label, cube);
+ Octree_labeling(2, label, cube);
+ Octree_labeling(6, label, cube);
+ }
+ if (cube[12] == 1)
+ {
+ cube[12] = label;
+ Octree_labeling(1, label, cube);
+ Octree_labeling(3, label, cube);
+ Octree_labeling(7, label, cube);
+ }
+ if (cube[17] == 1)
+ cube[17] = label;
+ if (cube[18] == 1)
+ {
+ cube[18] = label;
+ Octree_labeling(6, label, cube);
+ }
+ if (cube[20] == 1)
+ {
+ cube[20] = label;
+ Octree_labeling(7, label, cube);
+ }
+ if (cube[21] == 1)
+ {
+ cube[21] = label;
+ Octree_labeling(6, label, cube);
+ Octree_labeling(7, label, cube);
+ Octree_labeling(8, label, cube);
+ }
+ }
+ if (octant == 6)
+ {
+ if (cube[10] == 1)
+ {
+ cube[10] = label;
+ Octree_labeling(1, label, cube);
+ Octree_labeling(2, label, cube);
+ Octree_labeling(5, label, cube);
+ }
+ if (cube[11] == 1)
+ {
+ cube[11] = label;
+ Octree_labeling(2, label, cube);
+ }
+ if (cube[13] == 1)
+ {
+ cube[13] = label;
+ Octree_labeling(2, label, cube);
+ Octree_labeling(4, label, cube);
+ Octree_labeling(8, label, cube);
+ }
+ if (cube[18] == 1)
+ {
+ cube[18] = label;
+ Octree_labeling(5, label, cube);
+ }
+ if (cube[21] == 1)
+ {
+ cube[21] = label;
+ Octree_labeling(5, label, cube);
+ Octree_labeling(7, label, cube);
+ Octree_labeling(8, label, cube);
+ }
+ if (cube[19] == 1)
+ cube[19] = label;
+ if (cube[22] == 1)
+ {
+ cube[22] = label;
+ Octree_labeling(8, label, cube);
+ }
+ }
+ if (octant == 7)
+ {
+ if (cube[12] == 1)
+ {
+ cube[12] = label;
+ Octree_labeling(1, label, cube);
+ Octree_labeling(3, label, cube);
+ Octree_labeling(5, label, cube);
+ }
+ if (cube[14] == 1)
+ {
+ cube[14] = label;
+ Octree_labeling(3, label, cube);
+ }
+ if (cube[15] == 1)
+ {
+ cube[15] = label;
+ Octree_labeling(3, label, cube);
+ Octree_labeling(4, label, cube);
+ Octree_labeling(8, label, cube);
+ }
+ if (cube[20] == 1)
+ {
+ cube[20] = label;
+ Octree_labeling(5, label, cube);
+ }
+ if (cube[21] == 1)
+ {
+ cube[21] = label;
+ Octree_labeling(5, label, cube);
+ Octree_labeling(6, label, cube);
+ Octree_labeling(8, label, cube);
+ }
+ if (cube[23] == 1)
+ cube[23] = label;
+ if (cube[24] == 1)
+ {
+ cube[24] = label;
+ Octree_labeling(8, label, cube);
+ }
+ }
+ if (octant == 8)
+ {
+ if (cube[13] == 1)
+ {
+ cube[13] = label;
+ Octree_labeling(2, label, cube);
+ Octree_labeling(4, label, cube);
+ Octree_labeling(6, label, cube);
+ }
+ if (cube[15] == 1)
+ {
+ cube[15] = label;
+ Octree_labeling(3, label, cube);
+ Octree_labeling(4, label, cube);
+ Octree_labeling(7, label, cube);
+ }
+ if (cube[16] == 1)
+ {
+ cube[16] = label;
+ Octree_labeling(4, label, cube);
+ }
+ if (cube[21] == 1)
+ {
+ cube[21] = label;
+ Octree_labeling(5, label, cube);
+ Octree_labeling(6, label, cube);
+ Octree_labeling(7, label, cube);
+ }
+ if (cube[22] == 1)
+ {
+ cube[22] = label;
+ Octree_labeling(6, label, cube);
+ }
+ if (cube[24] == 1)
+ {
+ cube[24] = label;
+ Octree_labeling(7, label, cube);
+ }
+ if (cube[25] == 1)
+ cube[25] = label;
+ }
+}
+
+/**
+ * Print Self
+ */
+template <class TInputImage, class TOutputImage>
+void BinaryThinningImageFilter3D<TInputImage, TOutputImage>::PrintSelf(std::ostream &os, Indent indent) const
+{
+ Superclass::PrintSelf(os, indent);
+
+ os << indent << "Thinning image: " << std::endl;
+}
+
+} // end namespace itk
+
+#endif // itkBinaryThinningImageFilter3D_hxx
};
//=================================================================
-
-
-
//=================================================================
// BlackBox description
BBTK_BEGIN_DESCRIBE_TEMPLATE2_BLACK_BOX(CastVector,bbtk::AtomicBlackBox);
BBTK_END_DESCRIBE_TEMPLATE2_BLACK_BOX(CastVector);
//=================================================================
- template <class T, class U> void CastVector< T , U >::bbUserSetDefaultValues() {}
- template <class T, class U> void CastVector< T , U >::bbUserInitializeProcessing() {}
- template <class T, class U> void CastVector< T , U >::bbUserFinalizeProcessing() {}
-
+ template <class T, class U>
+ void CastVector< T , U >::bbUserSetDefaultValues()
+ {}
+
+ template <class T, class U>
+ void CastVector< T , U >::bbUserInitializeProcessing()
+ {}
+
+ template <class T, class U>
+ void CastVector< T , U >::bbUserFinalizeProcessing()
+ {}
} // namespace bbstd
BBTK_ADD_BLACK_BOX_TO_PACKAGE(std,DoubleToInt)
BBTK_BLACK_BOX_IMPLEMENTATION(DoubleToInt,bbtk::AtomicBlackBox);
+
//=====
// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
//=====
void DoubleToInt::Process()
{
-
// THE MAIN PROCESSING METHOD BODY
// Here we simply set the input 'In' value to the output 'Out'
// And print out the output value
// (the one provided in the attribute 'name' of the tag 'input')
// * TYPE is the C++ type of the input/output
// (the one provided in the attribute 'type' of the tag 'input')
- bbSetOutputOut( (int)bbGetInputIn() );
-
+ bbSetOutputOut( (int)bbGetInputIn() );
}
+
//=====
// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
//=====
void DoubleToInt::bbUserSetDefaultValues()
{
-
// SET HERE THE DEFAULT INPUT/OUTPUT VALUES OF YOUR BOX
// Here we initialize the input 'In' to 0
- bbSetInputIn(0);
-
+ bbSetInputIn(0);
}
+
//=====
// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
//=====
void DoubleToInt::bbUserInitializeProcessing()
{
-
// THE INITIALIZATION METHOD BODY :
// Here does nothing
// but this is where you should allocate the internal/output pointers
-// if any
-
-
+// if any
}
+
//=====
// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
//=====
void DoubleToInt::bbUserFinalizeProcessing()
{
-
// THE FINALIZATION METHOD BODY :
// Here does nothing
// but this is where you should desallocate the internal/output pointers
-// if any
-
+// if any
}
-}
-// EO namespace bbstd
+
+}// EO namespace bbstd
};
BBTK_BEGIN_DESCRIBE_BLACK_BOX(DoubleToInt,bbtk::AtomicBlackBox);
-BBTK_NAME("DoubleToInt");
-BBTK_AUTHOR("Claire Mouton");
-BBTK_DESCRIPTION("Converts a double to an int");
-BBTK_CATEGORY("");
-BBTK_INPUT(DoubleToInt,In,"Double input",double,"");
-BBTK_OUTPUT(DoubleToInt,Out,"Int output",int,"");
+ BBTK_NAME("DoubleToInt");
+ BBTK_AUTHOR("Claire Mouton");
+ BBTK_DESCRIPTION("Converts a double to an int");
+ BBTK_CATEGORY("");
+ BBTK_INPUT(DoubleToInt,In,"Double input",double,"");
+ BBTK_OUTPUT(DoubleToInt,Out,"Int output",int,"");
BBTK_END_DESCRIBE_BLACK_BOX(DoubleToInt);
//=====
// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
//=====
-}
-// EO namespace bbstd
+}// EO namespace bbstd
#endif // __bbstdDoubleToInt_h_INCLUDED__
--- /dev/null
+//=====
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//=====
+#include "bbstdNumericalVectorToStringVector.h"
+#include "bbstdPackage.h"
+namespace bbstd
+{
+
+BBTK_BLACK_BOX_TEMPLATE_IMPLEMENTATION(NumericalVectorToStringVector,bbtk::AtomicBlackBox);
+
+BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,int8_t);
+BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,uint8_t);
+BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,int16_t);
+BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,uint16_t);
+BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,int32_t);
+BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,uint32_t);
+BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,long);
+BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,float);
+BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,double);
+
+//typedef std::string string;
+// BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(std,NumericalVectorToStringVector,string);
+
+} // EO namespace bbstd
+
+
--- /dev/null
+//=====
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//=====
+#ifndef __bbstdNumericalVectorToStringVector_h_INCLUDED__
+#define __bbstdNumericalVectorToStringVector_h_INCLUDED__
+
+#include "bbstd_EXPORT.h"
+#include "bbtkAtomicBlackBox.h"
+#include <string>
+
+namespace bbstd
+{
+
+template <class T>
+class bbstd_EXPORT NumericalVectorToStringVector
+ :
+ public bbtk::AtomicBlackBox
+{
+ BBTK_TEMPLATE_BLACK_BOX_INTERFACE(NumericalVectorToStringVector,bbtk::AtomicBlackBox,T);
+//=====
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//=====
+ BBTK_DECLARE_INPUT(In,std::vector<T>);
+ BBTK_DECLARE_OUTPUT(Out,std::vector<std::string>);
+ BBTK_PROCESS(DoIt);
+ void DoIt();
+// T decode_item(const std::string&);
+//=====
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//=====
+};
+
+BBTK_BEGIN_DESCRIBE_TEMPLATE_BLACK_BOX(NumericalVectorToStringVector,bbtk::AtomicBlackBox);
+ BBTK_NAME(bbtk::HumanTypeName<std::vector<T> >() +"ToStringVector");
+ BBTK_AUTHOR("InfoDev");
+ BBTK_DEFAULT_ADAPTOR();
+ BBTK_DESCRIPTION("Converts the content of the input "
+ +bbtk::HumanTypeName<std::vector<T> >()
+ +" ("+bbtk::TypeName<std::vector<T> >()+") to string vector ");
+ typedef std::vector<T> Tvector;
+ BBTK_TEMPLATE_INPUT(NumericalVectorToStringVector,In,"Input",Tvector);
+ BBTK_TEMPLATE_OUTPUT(NumericalVectorToStringVector,Out,"Output",std::vector<std::string>);
+BBTK_END_DESCRIBE_TEMPLATE_BLACK_BOX(NumericalVectorToStringVector);
+
+template <class T>
+void NumericalVectorToStringVector<T>::bbUserSetDefaultValues()
+{}
+
+template <class T>
+void NumericalVectorToStringVector<T>::bbUserInitializeProcessing()
+{}
+
+template <class T>
+void NumericalVectorToStringVector<T>::bbUserFinalizeProcessing()
+{}
+
+template <class T>
+void NumericalVectorToStringVector<T>::DoIt()
+{
+ typedef T type;
+ bbmOutputOut.clear();
+ int lgt = bbGetInputIn().size();
+ for (int i=0; i<lgt; i++)
+ {
+ bbmOutputOut.push_back( std::to_string( bbGetInputIn()[i] ) );
+ } // for i
+}
+
+}// EO namespace bbstd
+#endif // __bbstdNumericalVectorToStringVector_h_INCLUDED__
+
BBTK_AUTHOR("InfoDev");
BBTK_DESCRIPTION("No Description.");
BBTK_CATEGORY("empty");
- BBTK_INPUT(VectorFilterDouble,Type,"default (0) 0=Erase duplicated lines, 1=Redimention Vectors, 2=Insert intermediat points,3=Adition k1, 4=Substraction k1, 5=Multilication k1, 6=Division k1, 7=Connect mesh X1,Y1,Z1,idxs1,X2,X2,X2,idx2, 8=Order All vectors with the logic of In0 (or the index k1 if exist) , 9=Invert Vectors, 10=Nearest Point in the vector. In3PointXYZ In0LstX In1LstY In2LstZ (Out0-index Out1-PointXYZ), 11=Mul Spacing (K1[spcX,spcY,spcZ]=Spacing), 12=Div Spacing (K1[spcX,spcY,spcZ]=Spacing), 13=Distance pointIn0 and pontIn1, 14=Select specific segments [k1] in In0=lstPx In1=lstPy In2=lstPz In3=lstIndex (if k1 empty all segments are selected) , 15 swhitch element in a point k1=0 yz, k1=1 nothing k1=2 xz , 16 switch In0 and In1 (k1=0 nothing, k1=1 swhich)",int,"");
+ BBTK_INPUT(VectorFilterDouble,Type,"default (0) 0=Erase consecutive duplicated lines, 1=Redimention Vectors, 2=Insert intermediat points,3=Adition k1, 4=Substraction k1, 5=Multilication k1, 6=Division k1, 7=Connect mesh X1,Y1,Z1,idxs1,X2,X2,X2,idx2, 8=Order All vectors with the logic of In0 (or the index k1 if exist) , 9=Invert Vectors, 10=Nearest Point in the vector. In3PointXYZ In0LstX In1LstY In2LstZ (Out0-index Out1-PointXYZ), 11=Mul Spacing (K1[spcX,spcY,spcZ]=Spacing), 12=Div Spacing (K1[spcX,spcY,spcZ]=Spacing), 13=Distance pointIn0 and pontIn1, 14=Select specific segments [k1] in In0=lstPx In1=lstPy In2=lstPz In3=lstIndex (if k1 empty all segments are selected) , 15 swhitch element in a point k1=0 yz, k1=1 nothing k1=2 xz , 16 switch In0 and In1 (k1=0 nothing, k1=1 swhich)",int,"");
BBTK_INPUT(VectorFilterDouble,k1,"(default [0]) nothing (Type0), k1[0]=new size vectors (Type 1) , nothing (Type2), k1[0] = Addition const. (Type 3), k1[0] = Substraction const. (Type 4), k1[0] = Multiplication const. (Type 5) , k1[0] = Division const. (Type 6), k1[0] In0..9 element base to be order (Type 8) , k1[spcX,spcY,spcZ] MulSpc In0_X,In1_Y,In2_Z (type 11), k1[spcX,spcY,spcZ] DivSpc In0_X,In1_Y,In2_Z (type 12) , k1[segment1, segment2,..] (type 14) , direction (type 15), direction (type 16) ",std::vector<double>,"");
BBTK_INPUT(VectorFilterDouble,In0,"Input vector",std::vector<double>,"");
BBTK_INPUT(VectorFilterDouble,In1,"Input vector",std::vector<double>,"");
//=================================================================
// BlackBox description
BBTK_BEGIN_DESCRIBE_TEMPLATE_BLACK_BOX(VectorToString,bbtk::AtomicBlackBox);
- BBTK_NAME(bbtk::HumanTypeName<std::vector<T> >()+"ToString");
- BBTK_AUTHOR("laurent.guigues@creatis.insa-lyon.fr");
- BBTK_DEFAULT_ADAPTOR();
- BBTK_DESCRIPTION("Converts the content of the input vector ("+bbtk::TypeName<std::vector<T> >()+") to a string in which each item is separated by the value of the input 'Separator'");
+ BBTK_NAME(bbtk::HumanTypeName<std::vector<T> >()+"ToString");
+ BBTK_AUTHOR("laurent.guigues@creatis.insa-lyon.fr");
+ BBTK_DEFAULT_ADAPTOR();
+ BBTK_DESCRIPTION("Converts the content of the input vector ("+bbtk::TypeName<std::vector<T> >()+") to a string in which each item is separated by the value of the input 'Separator'");
typedef std::vector<T> Tvector;
- BBTK_TEMPLATE_INPUT(VectorToString, In,"Input",Tvector);
- BBTK_TEMPLATE_INPUT(VectorToString, Separator,"Separator of item in the output string. Default is whitespace.",std::string);
- BBTK_TEMPLATE_OUTPUT(VectorToString, Out,"Output",std::string);
+ BBTK_TEMPLATE_INPUT(VectorToString, In,"Input",Tvector);
+ BBTK_TEMPLATE_INPUT(VectorToString, Separator,"Separator of item in the output string. Default is whitespace.",std::string);
+ BBTK_TEMPLATE_OUTPUT(VectorToString, Out,"Output",std::string);
BBTK_END_DESCRIBE_TEMPLATE_BLACK_BOX(VectorToString);
//=================================================================