From 6e31ad8fc88606b4b31fa3bb73fb4b3137d167e5 Mon Sep 17 00:00:00 2001 From: Roman Grothausmann Date: Fri, 8 May 2015 13:48:18 +0200 Subject: [PATCH 1/5] basic implementation of JoinCopyFilter and its integration into CnJ --- GUI/Model/JoinModel.cxx | 68 +------------------------- Logic/Common/itkJoinCopyFilter.cxx | 76 +++++++++++++++++++++++++++++ Logic/Common/itkJoinCopyFilter.h | 73 +++++++++++++++++++++++++++ Logic/Framework/IRISApplication.cxx | 24 +++++++++ Logic/Framework/IRISApplication.h | 6 +++ Logic/Framework/JOINImageData.cxx | 22 +++++++++ Logic/Framework/JOINImageData.h | 9 ++++ todo | 7 +++ 8 files changed, 218 insertions(+), 67 deletions(-) create mode 100644 Logic/Common/itkJoinCopyFilter.cxx create mode 100644 Logic/Common/itkJoinCopyFilter.h diff --git a/GUI/Model/JoinModel.cxx b/GUI/Model/JoinModel.cxx index 61413500..0f834fc0 100644 --- a/GUI/Model/JoinModel.cxx +++ b/GUI/Model/JoinModel.cxx @@ -94,75 +94,9 @@ bool JoinModel::processCnJ(bool reverse_mode){ // Get the global objects IRISApplication *driver = m_Parent->GetDriver(); - GlobalState *gs = driver->GetGlobalState(); - - // Get Join source image - JsrcImageWrapper *jsrc = driver->GetJOINImageData()->GetJsrc(); - - // Get Join destination image - JdstImageWrapper *jdst = driver->GetJOINImageData()->GetJdst(); - - // Get the segmentation image - //LabelImageWrapper *imgLabel = driver->GetCurrentImageData()->GetSegmentation(); - - // Get the paint properties - LabelType drawing_color = gs->GetDrawingColorLabel(); - DrawOverFilter drawover = gs->GetDrawOverFilter(); - - // Define a region of interest - //LabelImageWrapper::ImageType::RegionType xTestRegion= jsrc->GetImage()->GetBufferedRegion(); - JsrcImageWrapper::ImageType::RegionType xTestRegion= jsrc->GetImage()->GetLargestPossibleRegion(); // Flag to see if anything was changed - bool flagUpdate = false; - - JsrcImageWrapper::ImageType::ValueType JsrcClickPV= jsrc->GetImage()->GetPixel(to_itkIndex(m_MousePosition)); - // JdstImageWrapper::ImageType::ValueType JdstClickPV= jdst->GetImage()->GetPixel(to_itkIndex(m_MousePosition)); - - - // Iterate over the region - JsrcImageWrapper::Iterator sit(jsrc->GetImage(), xTestRegion); - LabelImageWrapper::Iterator dit(jdst->GetImage(), xTestRegion); - for(; !sit.IsAtEnd(); ++sit, ++dit){ - - if(sit.Get() != JsrcClickPV) - continue; - - LabelType pxLabel = dit.Get(); - - // Standard paint mode - if(!reverse_mode) - { - if(drawover.CoverageMode == PAINT_OVER_ALL || - (drawover.CoverageMode == PAINT_OVER_ONE && pxLabel == drawover.DrawOverLabel) || - (drawover.CoverageMode == PAINT_OVER_VISIBLE && pxLabel != 0)) - { - dit.Set(drawing_color); - if(pxLabel != drawing_color) flagUpdate = true; - } - } - // Background paint mode (clear label over current label) - else - { - if(drawing_color != 0 && pxLabel == drawing_color) - { - dit.Set(0); - if(pxLabel != 0) flagUpdate = true; - } - else if(drawing_color == 0 && drawover.CoverageMode == PAINT_OVER_ONE) - { - dit.Set(drawover.DrawOverLabel); - if(pxLabel != drawover.DrawOverLabel) flagUpdate = true; - } - } - } - - // Image has been updated - if(flagUpdate) - { - jdst->GetImage()->Modified(); - //imgLabel->GetImage()->Modified(); - } + bool flagUpdate= driver->ExecuteCnJCopy(to_itkIndex(m_MousePosition)); return flagUpdate; } diff --git a/Logic/Common/itkJoinCopyFilter.cxx b/Logic/Common/itkJoinCopyFilter.cxx new file mode 100644 index 00000000..20b7daf2 --- /dev/null +++ b/Logic/Common/itkJoinCopyFilter.cxx @@ -0,0 +1,76 @@ +////image filter to set DrawingColor in output image if input pixel equals SeedValue + +#ifndef __itkJoinCopyFilter_cxx +#define __itkJoinCopyFilter_cxx + +#include "itkJoinCopyFilter.h" +#include +#include +#include + +namespace itk{ + + template + JoinCopyFilter + ::JoinCopyFilter(){ + m_SeedActive= false; + m_SeedIndex.Fill(0); + m_SeedValue= NumericTraits::Zero; + } + + template + void JoinCopyFilter + ::SetJsrc(const TInputImage1 *image1){ + this->SetNthInput( 0, const_cast< TInputImage1 * >( image1 ) ); + } + + template + void JoinCopyFilter + ::SetJdst(const TInputImage2 *image2){ + this->SetNthInput( 1, const_cast< TInputImage2 * >( image2 ) ); + } + + + template + void JoinCopyFilter + ::BeforeThreadedGenerateData(){ + + if(m_SeedActive){ + typename TInputImage1::ConstPointer input = dynamic_cast( ProcessObject::GetInput(0) ); + m_SeedValue= input->GetPixel(m_SeedIndex); + } + m_UpdateFlag= false; + } + + + template + void JoinCopyFilter + ::ThreadedGenerateData(const typename Superclass::OutputImageRegionType& outputRegionForThread, ThreadIdType threadId){ + + if(m_SeedActive){ + typename TInputImage1::ConstPointer input = dynamic_cast( ProcessObject::GetInput(0) ); + typename TOutputImage::Pointer output = this->GetOutput(); + + itk::ImageRegionConstIterator iti(input, outputRegionForThread); + itk::ImageRegionIterator ito(output, outputRegionForThread); + + // support progress methods/callbacks with 1000 updates + ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels(), 1000); + + while(!iti.IsAtEnd()){ + if(iti.Get() == m_SeedValue){ + ito.Set(m_DrawingColor); + } + ++iti; + ++ito; + progress.CompletedPixel(); + } + + m_UpdateFlag= true; + m_SeedActive= false; + //output->Modified(); + } + } + }// end namespace + +#endif //__itkJoinCopyFilter_cxx diff --git a/Logic/Common/itkJoinCopyFilter.h b/Logic/Common/itkJoinCopyFilter.h new file mode 100644 index 00000000..5b0a4150 --- /dev/null +++ b/Logic/Common/itkJoinCopyFilter.h @@ -0,0 +1,73 @@ +#ifndef __itkJoinCopyFilter_h +#define __itkJoinCopyFilter_h + +#include + +namespace itk{ + /** \class JoinCopyFilter + * \brief: sets DrawingColor in output image if input pixel equals SeedValue + * + * \ingroup ImageFilters + */ + template + class JoinCopyFilter: + public InPlaceImageFilter{ + public: + /** Standard class typedefs. */ + typedef JoinCopyFilter Self; + typedef InPlaceImageFilter Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(JoinCopyFilter, InPlaceImageFilter); + + void SetJsrc(const TInputImage1 *image1); + void SetJdst(const TInputImage2 *image2); + + /** Set/Get SeedIndex value */ + itkSetMacro(SeedIndex, typename TInputImage1::IndexType); + itkGetConstMacro(SeedIndex, typename TInputImage1::IndexType); + + /** Set/Get DrawingColor value */ + itkSetMacro(DrawingColor, typename TOutputImage::ValueType); + itkGetConstMacro(DrawingColor, typename TOutputImage::ValueType); + + /** Get UpdateFlag value */ + itkGetConstMacro(UpdateFlag, bool); + + /** Get/Set SeedActive value */ + itkSetMacro(SeedActive, bool); + itkGetConstMacro(SeedActive, bool); + + protected: + JoinCopyFilter(); + ~JoinCopyFilter(){} + + bool m_SeedActive; + typename TInputImage1::IndexType m_SeedIndex; + typename TInputImage1::ValueType m_SeedValue; + typename TOutputImage::ValueType m_DrawingColor; + bool m_UpdateFlag; + + + virtual void BeforeThreadedGenerateData(); + virtual void ThreadedGenerateData(const typename Superclass::OutputImageRegionType& outputRegionForThread, ThreadIdType threadId); + + private: + JoinCopyFilter(const Self &); //purposely not implemented + void operator=(const Self &); //purposely not implemented + + }; + } //namespace ITK + + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkJoinCopyFilter.cxx" +#endif + +#endif // __itkJoinCopyFilter_h + diff --git a/Logic/Framework/IRISApplication.cxx b/Logic/Framework/IRISApplication.cxx index 5cf09dc2..ce8f2ce4 100644 --- a/Logic/Framework/IRISApplication.cxx +++ b/Logic/Framework/IRISApplication.cxx @@ -289,10 +289,34 @@ ::InitializeJOINImageData(const SNAPSegmentationROISettings &roi, int CnJMode, c // Remember the ROI object m_GlobalState->SetSegmentationROISettings(roi); + // Initialize JoinCopyFilter + m_JOINImageData->InitializeJoinCF(); + // The set of layers has changed InvokeEvent(LayerChangeEvent()); } +bool +IRISApplication +::ExecuteCnJCopy(JsrcImageWrapper::ImageType::IndexType SeedIndex) +{ + assert(m_JOINImageData->IsJsrcLoaded()); + + GlobalState *gs = GetGlobalState(); + + // Get the paint properties + LabelType drawing_color = gs->GetDrawingColorLabel(); + DrawOverFilter drawover = gs->GetDrawOverFilter(); + + m_JOINImageData->GetJoinCF()->SetSeedIndex(SeedIndex); + m_JOINImageData->GetJoinCF()->SetDrawingColor(drawing_color); + m_JOINImageData->GetJoinCF()->SetSeedActive(true); + m_JOINImageData->GetJoinCF()->Update(); + + InvokeEvent(LayerChangeEvent()); + return m_JOINImageData->GetJoinCF()->GetUpdateFlag(); +} + void IRISApplication ::CopySegementationToJsrc(const SNAPSegmentationROISettings &roi, diff --git a/Logic/Framework/IRISApplication.h b/Logic/Framework/IRISApplication.h index 1accd45b..3f55fd29 100644 --- a/Logic/Framework/IRISApplication.h +++ b/Logic/Framework/IRISApplication.h @@ -46,6 +46,7 @@ #include "SystemInterface.h" #include "UndoDataManager.h" #include "SNAPEvents.h" +#include "JOINImageData.h" //for JsrcImageWrapper::ImageType::IndexType // #include "itkImage.h" @@ -320,6 +321,11 @@ class IRISApplication : public itk::Object void InitializeJOINImageData(const SNAPSegmentationROISettings &roi, int CnJMode, const char* FileName, CommandType *progressCommand = NULL); + /** + * Execute CnJ CopyFilter + */ + bool ExecuteCnJCopy(JsrcImageWrapper::ImageType::IndexType SeedIndex); + /** * Copy Segmentation to Jsrc for JOIN-mode 0 */ diff --git a/Logic/Framework/JOINImageData.cxx b/Logic/Framework/JOINImageData.cxx index 4da628ac..694958b9 100644 --- a/Logic/Framework/JOINImageData.cxx +++ b/Logic/Framework/JOINImageData.cxx @@ -301,4 +301,26 @@ void JOINImageData::UnloadAll(){ InvokeEvent(LayerChangeEvent()); } + +void +JOINImageData +::InitializeJoinCF(){ + ////make sure Jsrc and Jdst exist + assert(IsJsrcLoaded()); + assert(IsJdstLoaded()); + + ////Initialize JoinCopyFilter + m_JoinCF= JoinCopyFilterType::New(); + m_JoinCF->SetJsrc(m_JsrcWrapper->GetImage()); + m_JoinCF->SetJdst(m_JdstWrapper->GetImage()); + m_JdstWrapper->SetImage(m_JoinCF->GetOutput()); + m_JdstWrapper->GetImage()->Modified(); + m_JoinCF->InPlaceOn(); //adjust Jdst directly + } + +JOINImageData::JoinCopyFilterPointer +JOINImageData::GetJoinCF(){ + ////todo: introduce check if m_JoinCF was initialized + return m_JoinCF; + } diff --git a/Logic/Framework/JOINImageData.h b/Logic/Framework/JOINImageData.h index cf430a63..5dfbac21 100644 --- a/Logic/Framework/JOINImageData.h +++ b/Logic/Framework/JOINImageData.h @@ -39,6 +39,7 @@ #include "GenericImageData.h" #include "itkImageAdaptor.h" +#include "itkJoinCopyFilter.h" /** * \class JOINImageData @@ -57,6 +58,9 @@ class JOINImageData : public GenericImageData typedef JdstImageWrapper::ImageType JdstImageType; typedef WsrcImageWrapper::ImageType WsrcImageType; + typedef itk::JoinCopyFilter JoinCopyFilterType; + typedef JoinCopyFilterType::Pointer JoinCopyFilterPointer; + /** Initialize to a ROI from another image data object */ void InitializeToROI(GenericImageData *source, const SNAPSegmentationROISettings &roi, @@ -88,6 +92,8 @@ class JOINImageData : public GenericImageData bool IsWsrcLoaded(); void SetWsrcSticky(bool sticky); + void InitializeJoinCF(); + JoinCopyFilterType::Pointer GetJoinCF(); protected: @@ -102,6 +108,9 @@ class JOINImageData : public GenericImageData // GWS source image SmartPtr m_WsrcWrapper; + + JoinCopyFilterPointer m_JoinCF; + }; diff --git a/todo b/todo index 06b7f56c..8516173d 100644 --- a/todo +++ b/todo @@ -1,5 +1,12 @@ TODOs for GWS: +- implement JoinCopyFilter (templated over dimension) +-- multi-threaded ImageRegionIterator +-- multi-threaded ImageScanlineIterator +-- FloodFilledImageFunctionConditionalIterator (Modules/Segmentation/RegionGrowing/include/itkConnectedThresholdImageFilter.hxx) +--- add 2D/3D option to GUI + implementation +- optimize CopySegementationToJdst and CopySegementationToJsrc + - combine mode 2 with mode 0 and add extra button for "LoadImageToJsrc" -- restructure JoinDataPanel to have two main buttons: CnJ from Seg. or File OR CnJ from gWS - add 'n' for next smallest unused label see eg m_Wrapper->GetHistogram(nBins) in ./Logic/ImageWrapper/DisplayMappingPolicy.cxx From 9f0332ca8ff269daa4676b660eb0d22c3e9b5977 Mon Sep 17 00:00:00 2001 From: Roman Grothausmann Date: Wed, 31 Jan 2018 18:53:15 +0100 Subject: [PATCH 2/5] avoid SetImage (looses coord transf from InitializeToWrapper), no segfault any more, filter executes but has no effect --- Logic/Framework/JOINImageData.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Logic/Framework/JOINImageData.cxx b/Logic/Framework/JOINImageData.cxx index 694958b9..1b672b38 100644 --- a/Logic/Framework/JOINImageData.cxx +++ b/Logic/Framework/JOINImageData.cxx @@ -313,9 +313,8 @@ ::InitializeJoinCF(){ m_JoinCF= JoinCopyFilterType::New(); m_JoinCF->SetJsrc(m_JsrcWrapper->GetImage()); m_JoinCF->SetJdst(m_JdstWrapper->GetImage()); - m_JdstWrapper->SetImage(m_JoinCF->GetOutput()); - m_JdstWrapper->GetImage()->Modified(); - m_JoinCF->InPlaceOn(); //adjust Jdst directly + //m_JdstWrapper->SetImage(m_JoinCF->GetOutput()); //causes segfault due to missing transform of uninitialized output + m_JoinCF->InPlaceOn(); //makes 2nd input (SetJdst) be the output } JOINImageData::JoinCopyFilterPointer From 5bcf696791fa559519441c9060b2b2daf8fd9838 Mon Sep 17 00:00:00 2001 From: Roman Grothausmann Date: Wed, 31 Jan 2018 19:41:26 +0100 Subject: [PATCH 3/5] simplified itkJoinCopyFilter according to InplaceImageFilter example: http://itk.org/Wiki/ITK/Examples/Developer/InplaceImageFilter --- Logic/Common/itkJoinCopyFilter.cxx | 26 +++++++++++++------------- Logic/Common/itkJoinCopyFilter.h | 12 ++++++------ Logic/Framework/JOINImageData.h | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Logic/Common/itkJoinCopyFilter.cxx b/Logic/Common/itkJoinCopyFilter.cxx index 20b7daf2..cf817ba3 100644 --- a/Logic/Common/itkJoinCopyFilter.cxx +++ b/Logic/Common/itkJoinCopyFilter.cxx @@ -10,29 +10,29 @@ namespace itk{ - template - JoinCopyFilter + template + JoinCopyFilter ::JoinCopyFilter(){ m_SeedActive= false; m_SeedIndex.Fill(0); - m_SeedValue= NumericTraits::Zero; + m_SeedValue= NumericTraits::Zero; } - template - void JoinCopyFilter + template + void JoinCopyFilter ::SetJsrc(const TInputImage1 *image1){ this->SetNthInput( 0, const_cast< TInputImage1 * >( image1 ) ); } - template - void JoinCopyFilter + template + void JoinCopyFilter ::SetJdst(const TInputImage2 *image2){ this->SetNthInput( 1, const_cast< TInputImage2 * >( image2 ) ); } - template - void JoinCopyFilter + template + void JoinCopyFilter ::BeforeThreadedGenerateData(){ if(m_SeedActive){ @@ -43,16 +43,16 @@ namespace itk{ } - template - void JoinCopyFilter + template + void JoinCopyFilter ::ThreadedGenerateData(const typename Superclass::OutputImageRegionType& outputRegionForThread, ThreadIdType threadId){ if(m_SeedActive){ typename TInputImage1::ConstPointer input = dynamic_cast( ProcessObject::GetInput(0) ); - typename TOutputImage::Pointer output = this->GetOutput(); + typename TInputImage2::Pointer output = this->GetOutput(); itk::ImageRegionConstIterator iti(input, outputRegionForThread); - itk::ImageRegionIterator ito(output, outputRegionForThread); + itk::ImageRegionIterator ito(output, outputRegionForThread); // support progress methods/callbacks with 1000 updates ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels(), 1000); diff --git a/Logic/Common/itkJoinCopyFilter.h b/Logic/Common/itkJoinCopyFilter.h index 5b0a4150..982897c8 100644 --- a/Logic/Common/itkJoinCopyFilter.h +++ b/Logic/Common/itkJoinCopyFilter.h @@ -9,13 +9,13 @@ namespace itk{ * * \ingroup ImageFilters */ - template + template class JoinCopyFilter: - public InPlaceImageFilter{ + public InPlaceImageFilter{ public: /** Standard class typedefs. */ typedef JoinCopyFilter Self; - typedef InPlaceImageFilter Superclass; + typedef InPlaceImageFilter Superclass; typedef SmartPointer Pointer; typedef SmartPointer< const Self > ConstPointer; @@ -33,8 +33,8 @@ namespace itk{ itkGetConstMacro(SeedIndex, typename TInputImage1::IndexType); /** Set/Get DrawingColor value */ - itkSetMacro(DrawingColor, typename TOutputImage::ValueType); - itkGetConstMacro(DrawingColor, typename TOutputImage::ValueType); + itkSetMacro(DrawingColor, typename TInputImage2::ValueType); + itkGetConstMacro(DrawingColor, typename TInputImage2::ValueType); /** Get UpdateFlag value */ itkGetConstMacro(UpdateFlag, bool); @@ -50,7 +50,7 @@ namespace itk{ bool m_SeedActive; typename TInputImage1::IndexType m_SeedIndex; typename TInputImage1::ValueType m_SeedValue; - typename TOutputImage::ValueType m_DrawingColor; + typename TInputImage2::ValueType m_DrawingColor; bool m_UpdateFlag; diff --git a/Logic/Framework/JOINImageData.h b/Logic/Framework/JOINImageData.h index 5dfbac21..363863f7 100644 --- a/Logic/Framework/JOINImageData.h +++ b/Logic/Framework/JOINImageData.h @@ -58,7 +58,7 @@ class JOINImageData : public GenericImageData typedef JdstImageWrapper::ImageType JdstImageType; typedef WsrcImageWrapper::ImageType WsrcImageType; - typedef itk::JoinCopyFilter JoinCopyFilterType; + typedef itk::JoinCopyFilter JoinCopyFilterType; typedef JoinCopyFilterType::Pointer JoinCopyFilterPointer; /** Initialize to a ROI from another image data object */ From 1b63ff4412c307d7344c7bece5421d472a2e9c61 Mon Sep 17 00:00:00 2001 From: Roman Grothausmann Date: Wed, 31 Jan 2018 19:54:18 +0100 Subject: [PATCH 4/5] set JoinCF-output as Jdst (filter working now), see comment in example (main): http://itk.org/Wiki/ITK/Examples/Developer/InplaceImageFilter --- Logic/Framework/IRISApplication.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Logic/Framework/IRISApplication.cxx b/Logic/Framework/IRISApplication.cxx index ce8f2ce4..cc66f07e 100644 --- a/Logic/Framework/IRISApplication.cxx +++ b/Logic/Framework/IRISApplication.cxx @@ -312,6 +312,7 @@ ::ExecuteCnJCopy(JsrcImageWrapper::ImageType::IndexType SeedIndex) m_JOINImageData->GetJoinCF()->SetDrawingColor(drawing_color); m_JOINImageData->GetJoinCF()->SetSeedActive(true); m_JOINImageData->GetJoinCF()->Update(); + m_JOINImageData->GetJdst()->SetImage(m_JOINImageData->GetJoinCF()->GetOutput()); //needed because output has stolen the input's buffer and the input has no image buffer. InvokeEvent(LayerChangeEvent()); return m_JOINImageData->GetJoinCF()->GetUpdateFlag(); From a714e119284194c9dea0a6f49b6771c3dffcca7d Mon Sep 17 00:00:00 2001 From: Roman Grothausmann Date: Wed, 31 Jan 2018 20:27:15 +0100 Subject: [PATCH 5/5] progress report for itkJoinCopyFilter (from 82f72dc9) --- Logic/Framework/JOINImageData.cxx | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Logic/Framework/JOINImageData.cxx b/Logic/Framework/JOINImageData.cxx index 1b672b38..40809ff3 100644 --- a/Logic/Framework/JOINImageData.cxx +++ b/Logic/Framework/JOINImageData.cxx @@ -35,6 +35,20 @@ #include "IRISApplication.h" #include "JOINImageData.h" +//#include "itkJCFilterWatcher.h" +#include + + +void FilterEventHandlerITK2(itk::Object *caller, const itk::EventObject &event, void*){ + + const itk::ProcessObject* filter = static_cast(caller); + + if(itk::ProgressEvent().CheckEvent(&event)) + fprintf(stderr, "\r%s progress: %5.1f%%", filter->GetNameOfClass(), 100.0 * filter->GetProgress());//stderr is flushed directly + else if(itk::EndEvent().CheckEvent(&event)) + std::cerr << std::endl << std::flush; + } + JOINImageData ::JOINImageData(){ @@ -311,10 +325,19 @@ ::InitializeJoinCF(){ ////Initialize JoinCopyFilter m_JoinCF= JoinCopyFilterType::New(); + m_JoinCF->SetJsrc(m_JsrcWrapper->GetImage()); m_JoinCF->SetJdst(m_JdstWrapper->GetImage()); //m_JdstWrapper->SetImage(m_JoinCF->GetOutput()); //causes segfault due to missing transform of uninitialized output m_JoinCF->InPlaceOn(); //makes 2nd input (SetJdst) be the output + + itk::CStyleCommand::Pointer eventCallbackITK; + eventCallbackITK = itk::CStyleCommand::New(); + eventCallbackITK->SetCallback(FilterEventHandlerITK2); + + m_JoinCF->AddObserver(itk::ProgressEvent(), eventCallbackITK); + m_JoinCF->AddObserver(itk::EndEvent(), eventCallbackITK); + } JOINImageData::JoinCopyFilterPointer