]> Creatis software - cpPlugins.git/blob - lib/cpPlugins/Plugins/BasicFilters/DoubleFloodImageFilter.cxx
61ff7d2e291b46a22e67b9fed0406d48735b64dc
[cpPlugins.git] / lib / cpPlugins / Plugins / BasicFilters / DoubleFloodImageFilter.cxx
1 #include "DoubleFloodImageFilter.h"
2 #include <cpPlugins/Interface/Image.h>
3 #include <cpPlugins/Interface/BaseApplication.h>
4 #include <cpPlugins/Interface/Plugins.h>
5 #include <cpExtensions/Interaction/ImageInteractorStyle.h>
6 #include <cpExtensions/Visualization/ImageSliceActors.h>
7
8 #include <vtkRenderWindowInteractor.h>
9
10 #include <itkFloodFilledImageFunctionConditionalConstIterator.h>
11 #include <itkImageFunction.h>
12
13 #ifdef cpPlugins_Interface_QT4
14 #include <QDialogButtonBox>
15
16 // -------------------------------------------------------------------------
17 cpPlugins::BasicFilters::DoubleFloodImageFilter_Dialog::
18 DoubleFloodImageFilter_Dialog(
19   QWidget* parent, DoubleFloodImageFilter* filter, Qt::WindowFlags f
20   )
21   : QDialog( parent, f | Qt::WindowStaysOnTopHint ),
22     m_Filter( filter )
23 {
24   this->m_Title = new QLabel( this );
25   this->m_Title->setText( "Execute simple vessel segmentation filter" );
26
27   this->m_MainLayout = new QGridLayout( this );
28   this->m_ToolsLayout = new QVBoxLayout( );
29   this->m_ToolsLayout->addWidget( this->m_Title );
30   this->m_MainLayout->addLayout( this->m_ToolsLayout, 0, 0, 1, 1 );
31
32   // Add buttons
33   QDialogButtonBox* bb = new QDialogButtonBox(
34     QDialogButtonBox::Cancel | QDialogButtonBox::Ok
35     );
36   QObject::connect( bb, SIGNAL( accepted( ) ), this, SLOT( accept( ) ) );
37   QObject::connect( bb, SIGNAL( rejected( ) ), this, SLOT( reject( ) ) );
38   this->m_ToolsLayout->addWidget( bb );
39 }
40
41 // -------------------------------------------------------------------------
42 cpPlugins::BasicFilters::DoubleFloodImageFilter_Dialog::
43 ~DoubleFloodImageFilter_Dialog( )
44 {
45   delete this->m_Title;
46   delete this->m_ToolsLayout;
47   delete this->m_MainLayout;
48 }
49
50 // -------------------------------------------------------------------------
51 void cpPlugins::BasicFilters::DoubleFloodImageFilter_Dialog::
52 accept( )
53 {
54   // Get interactive widget
55   if( this->m_Filter == NULL )
56     return;
57
58   typedef cpExtensions::Interaction::ImageInteractorStyle _TImageStyle;
59   typedef cpExtensions::Visualization::ImageSliceActors   _TImageActors;
60
61   // Get seeds
62   unsigned int nTotalSeeds = 0;
63   auto iIt = this->m_Filter->m_Interactors.begin( );
64   for( ; iIt != this->m_Filter->m_Interactors.end( ); ++iIt )
65   {
66     _TImageStyle* istyle =
67       dynamic_cast< _TImageStyle* >(
68         ( *iIt )->GetInteractorStyle( )
69         );
70     if( istyle == NULL )
71       continue;
72
73     // Get window level
74     _TImageActors* actors =
75       dynamic_cast< _TImageActors* >( istyle->GetAssociatedObject( ) );
76     if( actors != NULL )
77     {
78       this->m_Filter->GetParameters( )->SetReal( "Window", actors->GetWindow( ) );
79       this->m_Filter->GetParameters( )->SetReal( "Level", actors->GetLevel( ) );
80
81     } // fi
82
83     unsigned int nSeeds = istyle->GetNumberOfSeeds( );
84     for( unsigned int s = 0; s < nSeeds; ++s )
85     {
86       if( nTotalSeeds < 2 )
87       {
88         double seed[ 3 ];
89         istyle->GetSeedAsPoint( s, seed );
90         if( nTotalSeeds == 0 )
91           this->m_Filter->GetParameters( )->SetPoint( "Seed0", 3, seed );
92         else
93           this->m_Filter->GetParameters( )->SetPoint( "Seed1", 3, seed );
94
95       } // fi
96       nTotalSeeds++;
97
98     } // rof
99
100   } // rof
101
102   // Update filter
103   auto plugins = this->m_Filter->GetPlugins( );
104   if( plugins != NULL )
105   {
106     auto app = plugins->GetApplication( );
107     if( app != NULL )
108       app->UpdateActualFilter( );
109
110   } // fi
111 }
112
113 // -------------------------------------------------------------------------
114 void cpPlugins::BasicFilters::DoubleFloodImageFilter_Dialog::
115 reject( )
116 {
117   auto plugins = this->m_Filter->GetPlugins( );
118   if( plugins != NULL )
119     plugins->DeactivateFilter( );
120   this->Superclass::reject( );
121 }
122
123 #endif // cpPlugins_Interface_QT4
124
125 // -------------------------------------------------------------------------
126 cpPlugins::BasicFilters::DoubleFloodImageFilter::
127 DialogResult cpPlugins::BasicFilters::DoubleFloodImageFilter::
128 ExecConfigurationDialog( QWidget* parent )
129 {
130 #ifdef cpPlugins_Interface_QT4
131
132   typedef cpExtensions::Interaction::ImageInteractorStyle _TImageStyle;
133
134   // Activate seed widgets
135   bool at_least_one = false;
136   auto iIt = this->m_Interactors.begin( );
137   for( ; iIt != this->m_Interactors.end( ); ++iIt )
138   {
139     _TImageStyle* istyle =
140       dynamic_cast< _TImageStyle* >(
141         ( *iIt )->GetInteractorStyle( )
142         );
143     if( istyle != NULL )
144     {
145       istyle->SeedWidgetOn( );
146       at_least_one = true;
147
148     } // fi
149     
150   } // rof
151   if( !at_least_one )
152     return( false );
153   
154   // Create dialog
155   this->m_Dialog = new DoubleFloodImageFilter_Dialog( NULL, this );
156   this->m_Dialog->show( );
157
158   return( true );
159 #else // cpPlugins_Interface_QT4
160   return( false );
161 #endif // cpPlugins_Interface_QT4
162 }
163
164 // -------------------------------------------------------------------------
165 cpPlugins::BasicFilters::DoubleFloodImageFilter::
166 DoubleFloodImageFilter( )
167   : Superclass( )
168 {
169   this->_AddInput( "Input" );
170   this->_MakeOutput< cpPlugins::Interface::Image >( "Output" );
171
172   this->m_Parameters->ConfigureAsPoint( "Seed0" );
173   this->m_Parameters->ConfigureAsPoint( "Seed1" );
174   this->m_Parameters->ConfigureAsReal( "Window" );
175   this->m_Parameters->ConfigureAsReal( "Level" );
176   this->m_Parameters->ConfigureAsUint( "InsideValue" );
177   this->m_Parameters->ConfigureAsUint( "OutsideValue" );
178
179   this->m_Parameters->SetReal( "Window", 0 );
180   this->m_Parameters->SetReal( "Level", 0 );
181   this->m_Parameters->SetUint( "InsideValue", 255 );
182   this->m_Parameters->SetUint( "OutsideValue", 0 );
183 }
184
185 // -------------------------------------------------------------------------
186 cpPlugins::BasicFilters::DoubleFloodImageFilter::
187 ~DoubleFloodImageFilter( )
188 {
189 }
190
191 // -------------------------------------------------------------------------
192 std::string cpPlugins::BasicFilters::DoubleFloodImageFilter::
193 _GenerateData( )
194 {
195   cpPlugins::Interface::Image* image =
196     this->GetInput< cpPlugins::Interface::Image >( "Input" );
197   if( image == NULL )
198     return( "DoubleFloodImageFilter: No input image." );
199
200   itk::DataObject* itk_image = NULL;
201   std::string r = "";
202   cpPlugins_Image_Demangle_AllScalarTypes( 2, image, itk_image, r, _GD0 );
203   else cpPlugins_Image_Demangle_AllScalarTypes( 3, image, itk_image, r, _GD0 );
204   else r = "DoubleFloodImageFilter: Input image type not supported.";
205   return( r );
206 }
207
208 // -------------------------------------------------------------------------
209 template< class I >
210 std::string cpPlugins::BasicFilters::DoubleFloodImageFilter::
211 _GD0( itk::DataObject* image )
212 {
213   return(
214     this->_RealGD< I, itk::Image< unsigned char, I::ImageDimension > >(
215       image
216       )
217     );
218 }
219
220 // -------------------------------------------------------------------------
221 template< class I, class R = float >
222 class cpPlugins_BasicFilters_DoubleFloodImageFilter_Function
223   : public itk::ImageFunction< I, bool, R >
224 {
225 public:
226   typedef cpPlugins_BasicFilters_DoubleFloodImageFilter_Function Self;
227   typedef itk::ImageFunction< I, bool, R >                     Superclass;
228   typedef itk::SmartPointer< Self >                            Pointer;
229   typedef itk::SmartPointer< const Self >                      ConstPointer;
230
231   typedef typename Superclass::PointType           TPoint;
232   typedef typename Superclass::IndexType           TIndex;
233   typedef typename Superclass::ContinuousIndexType TCIndex;
234
235 public:
236   itkNewMacro( Self );
237   itkTypeMacro(
238     cpPlugins_BasicFilters_DoubleFloodImageFilter_Function,
239     itkImageFunction
240     );
241
242   itkSetMacro( Window, double );
243   itkSetMacro( Level, double );
244
245 public:
246   virtual bool Evaluate( const TPoint& point ) const
247     {
248       return( true );
249     }
250   virtual bool EvaluateAtIndex( const TIndex& index ) const
251     {
252       if( !( this->IsInsideBuffer( index ) ) )
253         return( false );
254
255       const I* image = this->GetInputImage( );
256       double w2 = this->m_Window / double( 2 );
257       double min = this->m_Level - w2;
258       double max = this->m_Level + w2;
259       unsigned char val = double( 0 );
260       double x = double( image->GetPixel( index ) );
261       double m = double( 100 ) / this->m_Window;
262       double b = ( this->m_Window - ( double( 2 ) * this->m_Level ) );
263       b *= double( 50 ) / this->m_Window;
264       if( x > min && x < max )
265         val = ( unsigned char )( ( m * x ) + b );
266
267       if( this->m_Start )
268       {
269         this->m_StartValue = val;
270         this->m_Start = false;
271         return( true );
272       }
273       else
274         return( std::abs( this->m_StartValue - val ) <= 2 );
275     }
276   virtual bool EvaluateAtContinuousIndex( const TCIndex& index ) const
277     {
278       return( true );
279     }
280
281 protected:
282   cpPlugins_BasicFilters_DoubleFloodImageFilter_Function( )
283     : Superclass( ),
284       m_Window( double( 0 ) ),
285       m_Level( double( 0 ) ),
286       m_Start( true )
287     {
288     }
289   virtual ~cpPlugins_BasicFilters_DoubleFloodImageFilter_Function( )
290     {
291     }
292
293 private:
294   // Purposely not implemented
295   cpPlugins_BasicFilters_DoubleFloodImageFilter_Function( const Self& other );
296   Self& operator=( const Self& other );
297
298 protected:
299   double m_Window;
300   double m_Level;
301   mutable unsigned char m_StartValue;
302   mutable bool m_Start;
303 };
304
305 // -------------------------------------------------------------------------
306 template< class I, class O >
307 inline std::string cpPlugins::BasicFilters::DoubleFloodImageFilter::
308 _RealGD( itk::DataObject* image )
309 {
310   typedef typename O::PixelType _OP;
311   typedef cpPlugins_BasicFilters_DoubleFloodImageFilter_Function< I > _F;
312   typedef itk::FloodFilledImageFunctionConditionalConstIterator< I, _F > _It;
313
314   typename I::PointType pseed0, pseed1;
315   pseed0 = this->m_Parameters->GetPoint< typename I::PointType >(
316     "Seed0", I::ImageDimension
317     );
318   pseed1 = this->m_Parameters->GetPoint< typename I::PointType >(
319     "Seed1", I::ImageDimension
320     );
321   double window = this->m_Parameters->GetReal( "Window" );
322   double level = this->m_Parameters->GetReal( "Level" );
323   _OP in_val = _OP( this->m_Parameters->GetUint( "InsideValue" ) );
324   _OP out_val = _OP( this->m_Parameters->GetUint( "OutsideValue" ) );
325
326   const I* in = dynamic_cast< const I* >( image );
327   typename I::IndexType seed0, seed1;
328   in->TransformPhysicalPointToIndex( pseed0, seed0 );
329   in->TransformPhysicalPointToIndex( pseed1, seed1 );
330
331   typename O::Pointer out = O::New( );
332   out->SetLargestPossibleRegion( in->GetLargestPossibleRegion( ) );
333   out->SetRequestedRegion( in->GetRequestedRegion( ) );
334   out->SetBufferedRegion( in->GetBufferedRegion( ) );
335   out->SetOrigin( in->GetOrigin( ) );
336   out->SetDirection( in->GetDirection( ) );
337   out->SetSpacing( in->GetSpacing( ) );
338   out->Allocate( );
339   out->FillBuffer( out_val );
340
341   typename _F::Pointer f = _F::New( );
342   f->SetInputImage( in );
343   f->SetWindow( window );
344   f->SetLevel( level );
345   _It i( in, f );
346   i.AddSeed( seed0 );
347   i.AddSeed( seed1 );
348
349   for( i.GoToBegin( ); !i.IsAtEnd( ); ++i )
350     out->SetPixel( i.GetIndex( ), in_val );
351
352   // Connect output
353   cpPlugins::Interface::Image* out_port =
354     this->GetOutput< cpPlugins::Interface::Image >( "Output" );
355   if( out_port != NULL )
356   {
357     out_port->SetITK< O >( out );
358     return( "" );
359   }
360   else
361     return( "DoubleFloodImageFilter: output not correctly created." );
362 }
363
364 // eof - $RCSfile$