]> Creatis software - cpMesh.git/blob - appli/InteractiveDeformableMeshSegmentation/MainWnd.cxx
Simple flood fill plugin added.
[cpMesh.git] / appli / InteractiveDeformableMeshSegmentation / MainWnd.cxx
1 #include "MainWnd.h"
2 #include "ui_MainWnd.h"
3
4 #include <algorithm>
5 #include <cctype>
6 #include <fstream>
7
8 #include <QFileDialog>
9 #include <QMessageBox>
10
11 #include <vtkAnnotatedCubeActor.h>
12 #include <vtkAxesActor.h>
13 #include <vtkPropAssembly.h>
14 #include <vtkProperty.h>
15 #include <vtkRenderWindow.h>
16
17 #include <cpPlugins/Interface/Image.h>
18
19 // -------------------------------------------------------------------------
20 #define IDMS_QT_ACTION( name )                                         \
21   QObject::connect(                                                    \
22     this->m_UI->action##name, SIGNAL( triggered( ) ),                  \
23     this, SLOT( _triggered_action##name( ) )                           \
24     )
25
26 // -------------------------------------------------------------------------
27 MainWnd::MainWnd( QWidget* parent )
28   : QMainWindow( parent ),
29     m_UI( new Ui::MainWnd ),
30     m_InputImage( NULL ),
31     m_SegmentedImage( NULL ),
32     m_ActivePlugin( NULL ),
33     m_ActiveParameters( NULL ),
34     m_ActivePluginType( Self::NonePluginType ),
35     m_ActivePluginCategory( Self::NonePluginCategory )
36 {
37   this->m_UI->setupUi( this );
38
39   // Configuration files
40   this->m_ApplicationPreferencesFile = "idms.config";
41   this->m_PluginsConfigurationFile = "idms.plugins";
42   this->_LoadApplicationPreferences( );
43
44   // Create MPR objects
45   this->m_MPR = new TMPR(
46     this->m_UI->m_XPlaneVTK->GetRenderWindow( ),
47     this->m_UI->m_YPlaneVTK->GetRenderWindow( ),
48     this->m_UI->m_ZPlaneVTK->GetRenderWindow( ),
49     this->m_UI->m_3DVTK->GetRenderWindow( )
50     );
51
52   // Associate observer
53   this->m_DoubleClickCommand =
54     vtkSmartPointer< DoubleClickCommand >::New( );
55   this->m_DoubleClickCommand->SetMainWnd( this );
56   this->m_MPR->AddDoubleClickObserver( this->m_DoubleClickCommand );
57
58   // Orientation marks
59   /* TODO
60      vtkSmartPointer< vtkAnnotatedCubeActor > oCube =
61      vtkSmartPointer< vtkAnnotatedCubeActor >::New( );
62      oCube->GetCubeProperty( )->SetColor( 0.9, 0.7, 0.2 );
63      oCube->GetTextEdgesProperty( )->SetLineWidth( 1 );
64      oCube->GetTextEdgesProperty( )->SetDiffuse( 0 );
65      oCube->GetTextEdgesProperty( )->SetAmbient( 1 );
66      oCube->GetTextEdgesProperty( )->SetColor( 0.18, 0.28, 0.23 );
67      oCube->GetXPlusFaceProperty( )->SetColor( 1, 0, 0 );
68      oCube->GetXPlusFaceProperty( )->SetInterpolationToFlat( );
69      oCube->GetXMinusFaceProperty( )->SetColor( 1, 0, 0 );
70      oCube->GetXMinusFaceProperty( )->SetInterpolationToFlat( );
71      oCube->GetYPlusFaceProperty( )->SetColor( 0, 1, 0 );
72      oCube->GetYPlusFaceProperty( )->SetInterpolationToFlat( );
73      oCube->GetYMinusFaceProperty( )->SetColor( 0, 1, 0 );
74      oCube->GetYMinusFaceProperty( )->SetInterpolationToFlat( );
75      oCube->GetZPlusFaceProperty( )->SetColor( 0, 0, 1 );
76      oCube->GetZPlusFaceProperty( )->SetInterpolationToFlat( );
77      oCube->GetZMinusFaceProperty( )->SetColor( 0, 0, 1 );
78      oCube->GetZMinusFaceProperty( )->SetInterpolationToFlat( );
79
80      vtkSmartPointer< vtkAxesActor > oAxes =
81      vtkSmartPointer< vtkAxesActor >::New( );
82      oAxes->AxisLabelsOff( );
83      oAxes->SetShaftTypeToCylinder( );
84      oAxes->SetTotalLength( 2.5, 2.5, 2.5 );
85
86      vtkSmartPointer< vtkPropAssembly > oActors =
87      vtkSmartPointer< vtkPropAssembly >::New( );
88      oActors->AddPart( oCube );
89      oActors->AddPart( oAxes );
90
91      this->m_3DOrientationWidget =
92      vtkSmartPointer< vtkOrientationMarkerWidget >::New( );
93      this->m_3DOrientationWidget->SetOutlineColor( 0.93, 0.57, 0.13 );
94      this->m_3DOrientationWidget->SetOrientationMarker( oActors );
95      this->m_3DOrientationWidget->SetViewport( 0.0, 0.0, 0.2, 0.2 );
96
97      // Add actors, widgets, stuff, ...
98      this->m_3DOrientationWidget->
99      SetInteractor( this->m_UI->m_3DVTK->GetInteractor( ) );
100      this->m_3DOrientationWidget->SetEnabled( 1 );
101      this->m_3DOrientationWidget->InteractiveOff( );
102   */
103
104   // Qt signals <-> slots
105   IDMS_QT_ACTION( ReloadPlugins );
106   IDMS_QT_ACTION( OpenInputImage );
107   IDMS_QT_ACTION( OpenSegmentedImage );
108   QObject::connect(
109     this->m_UI->actionNavigation, SIGNAL( triggered( ) ),
110     this, SLOT( _triggered_actionSwitchMode( ) )
111     );
112   QObject::connect(
113     this->m_UI->actionSegmentationInteractiveDeformation,
114     SIGNAL( triggered( ) ),
115     this, SLOT( _triggered_actionSwitchMode( ) )
116     );
117
118   // Historic configuration
119   this->m_LastOpenedFile = ".";
120
121   // Start: load all disponible plugins
122   this->_triggered_actionReloadPlugins( );
123 }
124
125 // -------------------------------------------------------------------------
126 MainWnd::
127 ~MainWnd( )
128 {
129   // Close all connections
130   this->m_Plugins.UnloadAll( );
131
132   // Delete objects
133   delete this->m_UI;
134   delete this->m_MPR;
135   if( this->m_ActiveParameters != NULL )
136   {
137     this->m_ActiveParameters->close( );
138     delete this->m_ActiveParameters;
139
140   } // fi
141   if( this->m_ActivePlugin != NULL ) delete this->m_ActivePlugin;
142   if( this->m_InputImage != NULL ) delete this->m_InputImage;
143   if( this->m_SegmentedImage != NULL ) delete this->m_SegmentedImage;
144 }
145
146 // -------------------------------------------------------------------------
147 void MainWnd::
148 _LoadApplicationPreferences( )
149 {
150   this->m_ApplicationPreferences.clear( );
151   std::ifstream in( this->m_ApplicationPreferencesFile.c_str( ) );
152   if( in )
153   {
154     std::string line;
155     std::getline( in, line );
156     while( !( in.eof( ) ) )
157     {
158       long pos = line.find_last_of( "=" );
159       std::string key = line.substr( 0, pos );
160       std::string value = line.substr( pos + 1 );
161       key.erase(
162         std::remove_if( key.begin( ), key.end( ), isspace ), key.end( )
163         );
164       value.erase(
165         std::remove_if( value.begin( ), value.end( ), isspace ), value.end( )
166         );
167       this->m_ApplicationPreferences[ key ] = value;
168       std::getline( in, line );
169
170     } // elihw
171   }
172   else
173   {
174     this->m_ApplicationPreferences[ "data_dimensions" ] = "3";
175     this->m_ApplicationPreferences[ "input_image_type" ]  = "short";
176     this->m_ApplicationPreferences[ "segmented_image_type" ]  = "uchar";
177     this->m_ApplicationPreferences[ "mesh_type" ]  = "double";
178
179   } // fi
180   in.close( );
181 }
182
183 // -------------------------------------------------------------------------
184 MainWnd::
185 TPluginImage* MainWnd::
186 _LoadImage( const std::string& image_type, const std::string& image_dim )
187 {
188   // Show dialog and check if it was accepted
189   QFileDialog dialog( this );
190   dialog.setFileMode( QFileDialog::ExistingFiles );
191   dialog.setDirectory( tr( this->m_LastOpenedFile.c_str( ) ) );
192   dialog.setNameFilter(
193     tr( "Medical image files (*.mhd *.bin *.dcm);;All files (*)" )
194     );
195   dialog.setDefaultSuffix( tr( "mhd" ) );
196   if( !( dialog.exec( ) ) )
197     return( NULL );
198
199   TPluginImage* ret = NULL;
200   unsigned int nFiles = dialog.selectedFiles( ).size( );
201   if( nFiles == 1 )
202   {
203     if( this->m_BaseClasses[ "ImageReader" ] == "" )
204     {
205       QMessageBox::critical(
206         this,
207         tr( "No plugin to read a single image file found!" ),
208         tr( "No plugin to read a single image file found!" )
209         );
210       return( ret );
211
212     } // fi
213
214     std::string fname = dialog.selectedFiles( ).at( 0 ).toStdString( );
215     this->m_LastOpenedFile = fname;
216
217     TPlugin* reader =
218       dynamic_cast< TPlugin* >(
219         this->m_Plugins.CreateObject( this->m_BaseClasses[ "ImageReader" ] )
220         );
221
222     TParameters reader_params = reader->GetDefaultParameters( );
223     reader_params[ "FileName" ].second = fname;
224     reader_params[ "PixelType" ].second = image_type;
225     reader_params[ "ImageDimension" ].second = image_dim;
226     reader_params[ "IsColorImage" ].second = "0";
227     reader->SetParameters( reader_params );
228     std::string err = reader->Update( );
229
230     if( err == "" )
231     {
232       ret = dynamic_cast< TPluginImage* >( reader->GetOutput( 0 ) );
233       reader->DisconnectOutputs( );
234     }
235     else
236       QMessageBox::critical(
237         this,
238         tr( "Error reading single image" ),
239         tr( err.c_str( ) )
240         );
241     delete reader;
242   }
243   else if( nFiles > 1 )
244   {
245     /* TODO
246        if( this->m_ImageSeriesReaderClassName == "" )
247        {
248        QMessageBox::critical(
249        this,
250        tr( "No plugin to read an image series found!" ),
251        tr( "No plugin to read an image series found!" )
252        );
253        return( ret );
254
255        } // fi
256        std::string fname = dialog.selectedFiles( ).at( 0 ).toStdString( );
257        this->m_LastOpenedFile = fname;
258     */
259
260   } // fi
261   return( ret );
262 }
263
264 // -------------------------------------------------------------------------
265 void MainWnd::
266 _UpdateEnabledFlags( )
267 {
268   bool img = ( this->m_InputImage != NULL );
269   this->m_UI->menuSegmentInputImage->setEnabled( img );
270   this->m_UI->actionOpenSegmentedImage->setEnabled( img );
271   this->m_UI->m_3DVTK->setEnabled( img );
272   this->m_UI->m_XPlaneVTK->setEnabled( img );
273   this->m_UI->m_YPlaneVTK->setEnabled( img );
274   this->m_UI->m_ZPlaneVTK->setEnabled( img );
275   this->m_UI->m_AuxVTK->setEnabled( img );
276
277   bool seg = ( this->m_SegmentedImage != NULL );
278   this->m_UI->menuFilterSegmentedImage->setEnabled( seg );
279   this->m_UI->menuExtractMesh->setEnabled( seg );
280   this->m_UI->menuProcessMesh->setEnabled( seg );
281   this->m_UI->actionOpenMesh->setEnabled( seg );
282
283   this->m_UI->actionNavigation->setEnabled( img && seg );
284   this->m_UI->actionSegmentationInteractiveDeformation->
285     setEnabled( img && seg );
286 }
287
288 // -------------------------------------------------------------------------
289 void MainWnd::
290 _triggered_actionReloadPlugins( )
291 {
292   if( !( this->_LoadPlugins( ) ) )
293   {
294     QMessageBox::critical(
295       this,
296       tr( "Could not load plugins from given file." ),
297       tr( "Could not load plugins from given file." )
298       );
299
300   } // fi
301   this->_UpdateEnabledFlags( );
302 }
303
304 // -------------------------------------------------------------------------
305 void MainWnd::
306 _triggered_actionOpenInputImage( )
307 {
308   if( this->m_InputImage != NULL )
309     delete this->m_InputImage;
310   this->m_InputImage =
311     this->_LoadImage(
312       this->m_ApplicationPreferences[ "input_image_type" ],
313       this->m_ApplicationPreferences[ "data_dimensions" ]
314       );
315   if( this->m_InputImage != NULL )
316   {
317     this->m_MPR->SetImage( this->m_InputImage->GetVTKImageData( ) );
318
319     // Update activations
320     this->_UpdateEnabledFlags( );
321     this->m_UI->actionNavigation->setChecked( true );
322     this->_triggered_actionSwitchMode( );
323
324   } // fi
325 }
326
327 // -------------------------------------------------------------------------
328 void MainWnd::
329 _triggered_actionOpenSegmentedImage( )
330 {
331   if( this->m_SegmentedImage != NULL )
332     delete this->m_SegmentedImage;
333   this->m_SegmentedImage =
334     this->_LoadImage(
335       this->m_ApplicationPreferences[ "segmented_image_type" ],
336       this->m_ApplicationPreferences[ "data_dimensions" ]
337       );
338   if( this->m_SegmentedImage != NULL )
339   {
340     this->m_MPR->SetSegmentation(
341       this->m_SegmentedImage->GetVTKImageData( )
342       );
343     /* TODO
344        cpPlugins::Interface::Image* img = 
345        dynamic_cast< cpPlugins::Interface::Image* >( this->m_SegmentedImage );
346        this->m_ImageActors->SetSegmentation( img->GetVTKImageData( ) );
347     */
348
349     // Ok, start!
350     this->m_MPR->Render( 0 );
351     this->m_MPR->Render( 1 );
352     this->m_MPR->Render( 2 );
353     this->_UpdateEnabledFlags( );
354
355   } // fi
356 }
357
358 // -------------------------------------------------------------------------
359 void MainWnd::
360 _triggered_actionSwitchMode( )
361 {
362   QAction* snd = dynamic_cast< QAction* >( this->sender( ) );
363   if( snd == this->m_UI->actionNavigation )
364   {
365     this->m_UI->actionSegmentationInteractiveDeformation->setChecked(
366       !( this->m_UI->actionNavigation->isChecked( ) )
367       );
368   }
369   else if( snd == this->m_UI->actionSegmentationInteractiveDeformation )
370   {
371     this->m_UI->actionNavigation->setChecked(
372       !( this->m_UI->actionSegmentationInteractiveDeformation->isChecked( ) )
373       );
374   }
375   else
376   {
377     this->m_UI->actionNavigation->setChecked( true );
378     this->m_UI->actionSegmentationInteractiveDeformation->setChecked( false );
379
380   } // fi
381
382   /* TODO
383      if( this->m_UI->aNavigation->isChecked( ) )
384      {
385      this->m_XStyle->SetModeToNavigation( );
386      this->m_YStyle->SetModeToNavigation( );
387      this->m_ZStyle->SetModeToNavigation( );
388      this->m_ImageActors->HideRegion( 0 );
389      this->m_ImageActors->HideRegion( 1 );
390      this->m_ImageActors->HideRegion( 2 );
391      this->m_3DRenderer->RemoveActor(
392      this->m_ImageActors->GetCursorActor( )
393      );
394      this->m_3DRenderer->RemoveActor(
395      this->m_ImageActors->GetRegionActor( )
396      );
397      this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
398      }
399      else if( this->m_UI->aSegmentationInteractiveDeformation->isChecked( ) )
400      {
401      this->m_XStyle->SetModeToDeformation( );
402      this->m_YStyle->SetModeToDeformation( );
403      this->m_ZStyle->SetModeToDeformation( );
404      this->m_ImageActors->ShowRegion( 0 );
405      this->m_ImageActors->ShowRegion( 1 );
406      this->m_ImageActors->ShowRegion( 2 );
407      this->m_3DRenderer->AddActor(
408      this->m_ImageActors->GetCursorActor( )
409      );
410      this->m_3DRenderer->AddActor(
411      this->m_ImageActors->GetRegionActor( )
412      );
413      this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
414
415      } // fi
416   */
417 }
418
419 // -------------------------------------------------------------------------
420 /* TODO
421
422 // -------------------------------------------------------------------------
423 bool MainWnd::
424 _ParametersDialog( TParameters& parameters )
425 {
426   QDialog dlg( this );
427   QGridLayout gridLayout( &dlg );
428   QVBoxLayout verticalLayout;
429
430   // Put values
431   typedef std::map< std::string, QWidget* > _TWidgets;
432   _TWidgets widgets;
433   TParameters::const_iterator pIt = parameters.begin( );
434   for( ; pIt != parameters.end( ); ++pIt )
435   {
436     unsigned long pos = pIt->first.find_last_of( ":" );
437     std::string v_name = pIt->first.substr( 0, pos );
438     std::string v_type = pIt->first.substr( pos + 1 );
439
440     QHBoxLayout* horizontalLayout = new QHBoxLayout( );
441     QLabel* label = new QLabel( &dlg );
442     label->setText( QString( v_name.c_str( ) ) );
443     horizontalLayout->addWidget( label );
444     if( v_type == "real" )
445     {
446       QDoubleSpinBox* v_double = new QDoubleSpinBox( &dlg );
447       v_double->setDecimals( 3 );
448       v_double->setMinimum( -( std::numeric_limits< double >::max( ) ) );
449       v_double->setMaximum( std::numeric_limits< double >::max( ) );
450       v_double->setValue( std::atof( pIt->second.c_str( ) ) );
451       horizontalLayout->addWidget( v_double );
452       widgets[ pIt->first ] = v_double;
453     }
454     else if( v_type == "atomic_real" )
455     {
456       if( v_name == "MeshType" )
457       {
458         QLabel* info = new QLabel( &dlg );
459         if( typeid( TScalar ) == typeid( float ) )
460           info->setText( QString( "float" ) );
461         else if( typeid( TScalar ) == typeid( double ) )
462           info->setText( QString( "double" ) );
463         horizontalLayout->addWidget( info );
464         widgets[ pIt->first ] = info;
465
466       } // fi
467
468     } // fi
469     verticalLayout.addLayout( horizontalLayout );
470
471   } // rof
472   gridLayout.addLayout( &verticalLayout, 0, 0, 1, 1 );
473
474   // Buttons box
475   QDialogButtonBox buttonBox( &dlg );
476   buttonBox.setOrientation( Qt::Horizontal );
477   buttonBox.setStandardButtons(
478     QDialogButtonBox::Cancel | QDialogButtonBox::Ok
479     );
480   gridLayout.addWidget( &buttonBox, 1, 0, 1, 1 );
481   QObject::connect(
482     &buttonBox, SIGNAL( accepted( ) ),
483     &dlg, SLOT( accept( ) )
484     );
485   QObject::connect(
486     &buttonBox, SIGNAL( rejected( ) ),
487     &dlg, SLOT( reject( ) )
488     );
489   QMetaObject::connectSlotsByName( &dlg );
490
491   // Execute dialog
492   if( dlg.exec( ) == QDialog::Accepted )
493   {
494     _TWidgets::const_iterator wIt = widgets.begin( );
495     for( ; wIt != widgets.end( ); ++wIt )
496     {
497       unsigned long pos = wIt->first.find_last_of( ":" );
498       std::string v_name = wIt->first.substr( 0, pos );
499       std::string v_type = wIt->first.substr( pos + 1 );
500       std::stringstream sstr;
501       if( v_type == "real" )
502       {
503         QDoubleSpinBox* v_double =
504           dynamic_cast< QDoubleSpinBox* >( wIt->second );
505         if( v_double != NULL )
506           sstr << v_double->value( );
507       }
508       else if( v_type == "atomic_real" )
509       {
510         if( v_name == "MeshType" )
511         {
512           QLabel* info = dynamic_cast< QLabel* >( wIt->second );
513           if( info != NULL )
514             sstr << info->text( ).toStdString( );
515
516         } // fi
517
518       } // fi
519       parameters[ wIt->first ] = sstr.str( );
520
521     } // rof
522     return( true );
523   }
524   return( false );
525   }
526
527 // -------------------------------------------------------------------------
528 void MainWnd::
529 triggered_aFilterSegmentedImage( )
530 {
531   // Get filter name
532   if( this->m_Segmentation.IsNull( ) )
533     return;
534   QAction* action = dynamic_cast< QAction* >( this->sender( ) );
535   if( action == NULL )
536     return;
537   std::string filter_name = action->text( ).toStdString( );
538
539   // Create filter
540   TFilterObject* filter = this->m_Plugins.CreateObject( filter_name );
541   if( filter == NULL )
542     return;
543
544   TParameters parameters = filter->GetDefaultParameters( );
545   if( !( this->_ParametersDialog( parameters ) ) )
546     return;
547   filter->SetInput( this->m_Segmentation );
548   filter->SetParameters( parameters );
549   std::string result = filter->Update( );
550
551   // Get modified segmentation
552      this->m_Mesh = filter->GetCastedOutput< TMesh >( );
553      if( this->m_Mesh.IsNotNull( ) )
554      {
555      this->m_Mesh->DisconnectPipeline( );
556
557      } // fi
558   // Ok, it seems to have runned fine
559   delete filter;
560 }
561
562 // -------------------------------------------------------------------------
563 void MainWnd::
564 triggered_aSegmentedImageToMesh( )
565 {
566   // Get filter name
567   if( this->m_Segmentation.IsNull( ) )
568     return;
569   QAction* action = dynamic_cast< QAction* >( this->sender( ) );
570   if( action == NULL )
571     return;
572   std::string filter_name = action->text( ).toStdString( );
573
574   // Create filter
575   TFilterObject* filter = this->m_Plugins.CreateObject( filter_name );
576   if( filter == NULL )
577     return;
578
579   TParameters parameters = filter->GetDefaultParameters( );
580   if( !( this->_ParametersDialog( parameters ) ) )
581     return;
582   filter->SetInput( this->m_Segmentation );
583   filter->SetParameters( parameters );
584   std::string result = filter->Update( );
585
586   // Get mesh
587   this->m_Mesh = filter->GetCastedOutput< TMesh >( );
588   if( this->m_Mesh.IsNotNull( ) )
589   {
590     this->m_Mesh->DisconnectPipeline( );
591
592   } // fi
593
594   // Ok, it seems to have runned fine
595   delete filter;
596 }
597 */
598
599 // -------------------------------------------------------------------------
600 /*
601   void MainWnd::
602   _SliceMesh( int axis )
603   {
604   TCutter* cutter = NULL;
605   if( axis == 2 ) cutter = this->m_ZCutter;
606
607   if( cutter == NULL )
608   return;
609
610   vtkPlane* vplane = this->m_ImageActors->GetSlicePlane( axis );
611   double vorigin[ 3 ], vnormal[ 3 ];
612   vplane->GetOrigin( vorigin );
613   vplane->GetNormal( vnormal );
614
615   TCutter::TVector corigin, cnormal;
616   corigin[ 0 ] = TScalar( vorigin[ 0 ] );
617   corigin[ 1 ] = TScalar( vorigin[ 1 ] );
618   corigin[ 2 ] = TScalar( vorigin[ 2 ] );
619   cnormal[ 0 ] = TScalar( vnormal[ 0 ] );
620   cnormal[ 1 ] = TScalar( vnormal[ 1 ] );
621   cnormal[ 2 ] = TScalar( vnormal[ 2 ] );
622
623   cutter->SetPlanePoint( corigin );
624   cutter->SetPlaneNormal( cnormal );
625   cutter->Update( );
626   }
627
628   // -------------------------------------------------------------------------
629   void MainWnd::
630   _SliceEventCallback(
631   vtkObject* caller,
632   long unsigned int eventId,
633   void* clientData, void* callData
634   )
635   {
636   if( clientData == NULL || callData == NULL )
637   return;
638   MainWnd* wnd = reinterpret_cast< MainWnd* >( clientData );
639   int axis = *( reinterpret_cast< int* >( callData ) );
640   if( wnd == NULL )
641   return;
642   if( eventId == idms::InteractorStyleImage::SliceEvent )
643   wnd->_SliceMesh( axis );
644   }
645
646   // -------------------------------------------------------------------------
647   void MainWnd::
648   triggered_aLoadImage( )
649   {
650   if( this->_LoadImage< TImage >( this->m_Image ) )
651   {
652   // Connect image to VTK
653   this->m_VTKImage->SetInput( this->m_Image );
654   this->m_VTKImage->Update( );
655   this->m_ImageActors->Configure(
656   this->m_VTKImage->GetOutput( ),
657   this->m_UI->m_XPlaneVTK->GetInteractor( ),
658   this->m_UI->m_YPlaneVTK->GetInteractor( ),
659   this->m_UI->m_ZPlaneVTK->GetInteractor( )
660   );
661   this->m_ImageActors->
662   AddAuxiliaryInteractor( this->m_UI->m_3DVTK->GetInteractor( ) );
663
664   // Associate actors
665   this->m_3DRenderer->AddActor(
666   this->m_ImageActors->GetImageOutlineActor( )
667   );
668   this->m_3DRenderer->AddActor(
669   this->m_ImageActors->GetXBoundsActor( )
670   );
671   this->m_3DRenderer->AddActor(
672   this->m_ImageActors->GetYBoundsActor( )
673   );
674   this->m_3DRenderer->AddActor(
675   this->m_ImageActors->GetZBoundsActor( )
676   );
677
678   // Reset all cameras
679   this->m_3DRenderer->ResetCamera( );
680   this->m_ImageActors->ResetCameras( );
681
682   // Ok, start!
683   this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
684   this->m_UI->m_XPlaneVTK->GetRenderWindow( )->Render( );
685   this->m_UI->m_YPlaneVTK->GetRenderWindow( )->Render( );
686   this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->Render( );
687
688   // Activate controls
689   this->m_UI->aLoadSegmentedImage->setEnabled( true );
690   this->m_UI->aSegmentImage->setEnabled( true );
691   this->m_UI->m_3DVTK->setEnabled( true );
692   this->m_UI->m_XPlaneVTK->setEnabled( true );
693   this->m_UI->m_YPlaneVTK->setEnabled( true );
694   this->m_UI->m_ZPlaneVTK->setEnabled( true );
695
696   } // fi
697   }
698
699   // -------------------------------------------------------------------------
700   void MainWnd::
701   triggered_aLoadSegmentedImage( )
702   {
703   if( this->m_Mesh.IsNotNull( ) )
704   {
705   QMessageBox::critical(
706   this,
707   tr( "Mesh already loaded!" ),
708   tr( "Mesh already loaded!" )
709   );
710   return;
711
712   } // fi
713
714   if( this->_LoadImage< TImage >( this->m_Segmentation ) )
715   {
716   // Compute segmentation values
717   itk::MinimumMaximumImageCalculator< TImage >::Pointer minmax =
718   itk::MinimumMaximumImageCalculator< TImage >::New( );
719   minmax->SetImage( this->m_Segmentation );
720   minmax->Compute( );
721   TPixel min_v = minmax->GetMinimum( );
722   TPixel max_v = minmax->GetMaximum( );
723   double thr = double( max_v + min_v ) / double( 2 );
724
725   typedef itk::Image< TScalar, Dimension > _TScalarImage;
726   typedef
727   itk::BinaryMinMaxCurvatureFlowImageFilter< TImage, _TScalarImage >
728   _TFilter;
729   typedef _TFilter::TimeStepType    _TTimeStep;
730   typedef _TFilter::RadiusValueType _TRadius;
731
732   _TFilter::Pointer filter = _TFilter::New( );
733   filter->SetInput( this->m_Segmentation );
734   filter->SetTimeStep( _TTimeStep( 0.0625 ) );
735   filter->SetNumberOfIterations( 10 );
736   filter->SetStencilRadius( _TRadius( 3 ) );
737   filter->SetThreshold( thr );
738   filter->Update( );
739
740   itk::ImageFileWriter< _TScalarImage >::Pointer w =
741   itk::ImageFileWriter< _TScalarImage >::New( );
742   w->SetInput( filter->GetOutput( ) );
743   w->SetFileName( "no_noise.mhd" );
744   w->Update( );
745   std::exit( 1 );
746
747   typedef
748   itk::LaplacianRecursiveGaussianImageFilter< TImage, _TScalarImage >
749   _TFilter;
750   _TFilter::Pointer filter = _TFilter::New( );
751   filter->SetInput( this->m_Segmentation );
752   filter->SetSigma( 3 ); // in spacing units
753   filter->SetNormalizeAcrossScale( false );
754
755   typedef itk::ThresholdImageFilter< _TScalarImage > _TThreshold;
756   _TThreshold::Pointer threshold = _TThreshold::New( );
757   threshold->SetInput( filter->GetOutput( ) );
758   threshold->ThresholdAbove( TScalar( 0 ) );
759   threshold->InPlaceOff( );
760   threshold->Update( );
761
762   itk::MinimumMaximumImageCalculator< _TScalarImage >::Pointer t_minmax =
763   itk::MinimumMaximumImageCalculator< _TScalarImage >::New( );
764   t_minmax->SetImage( threshold->GetOutput( ) );
765   t_minmax->Compute( );
766   TScalar min_t = t_minmax->GetMinimum( );
767
768   std::cout << min_t << " " << t_minmax->GetMaximum( ) << std::endl;
769
770   itk::SubtractImageFilter< _TScalarImage >::Pointer subtract =
771   itk::SubtractImageFilter< _TScalarImage >::New( );
772   subtract->SetInput1( threshold->GetOutput( ) );
773   subtract->SetConstant2( min_t );
774
775   itk::ImageFileWriter< _TScalarImage >::Pointer w =
776   itk::ImageFileWriter< _TScalarImage >::New( );
777   w->SetInput( subtract->GetOutput( ) );
778   w->SetFileName( "no_noise_laplace_2.mhd" );
779   w->Update( );
780   std::exit( 1 );
781
782   // Pass segmentation to VTK
783   this->m_VTKSegmentation = TVTKImage::New( );
784   this->m_VTKSegmentation->SetInput( this->m_Segmentation );
785   this->m_VTKSegmentation->Update( );
786
787   // Use VTK's marching cubes (it is smoother)
788   vtkSmartPointer< vtkImageMarchingCubes > segmentation_mc =
789   vtkSmartPointer< vtkImageMarchingCubes >::New( );
790   segmentation_mc->SetInputData( this->m_VTKSegmentation->GetOutput( ) );
791   segmentation_mc->SetValue( 0, thr );
792   segmentation_mc->Update( );
793
794   // Go back to ITK world
795   typedef cpm::VTK::PolyDataToMeshFilter< TTriangulation > _TVTKPDataToMesh;
796   _TVTKPDataToMesh::Pointer itk_mc = _TVTKPDataToMesh::New( );
797   itk_mc->SetInput( segmentation_mc->GetOutput( ) );
798   itk_mc->Update( );
799   this->m_Mesh = itk_mc->GetOutput( );
800   this->m_Mesh->DisconnectPipeline( );
801
802   this->m_MeshMapper = vtkSmartPointer< TTriangulationMapper >::New( );
803   this->m_MeshActor = vtkSmartPointer< vtkActor >::New( );
804
805   this->m_MeshMapper->SetInputData( this->m_Mesh );
806   this->m_MeshActor->SetMapper( this->m_MeshMapper );
807   this->m_MeshActor->GetProperty( )->SetColor( 1, 1, 0 );
808   this->m_MeshActor->GetProperty( )->SetRepresentationToWireframe( );
809   this->m_3DRenderer->AddActor( this->m_MeshActor );
810   this->m_3DRenderer->ResetCamera( );
811   this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
812
813   unsigned int reduction = 20;
814
815   typedef TImage::SpacingType::ValueType _TValue;
816
817
818   // Compute downsize parameters
819   TImage::SizeType o_size =
820   segmentation->GetLargestPossibleRegion( ).GetSize( );
821   TImage::SpacingType o_spac = segmentation->GetSpacing( );
822   _TValue min_spac = std::numeric_limits< _TValue >::max( );
823   for( unsigned int d = 0; d < Dimension; ++d )
824   min_spac = ( o_spac[ d ] < min_spac )? o_spac[ d ]: min_spac;
825   min_spac *= _TValue( reduction );
826   TImage::SpacingType n_spac( min_spac );
827   TImage::SizeType n_size;
828   for( unsigned int d = 0; d < Dimension; ++d )
829   n_size[ d ] = ( unsigned long )(
830   _TValue( o_size[ d ] ) * o_spac[ d ] / min_spac
831   );
832
833   // Downsize image
834   typedef itk::Image< TScalar, Dimension > _TScalarImage;
835   typedef itk::IdentityTransform< TScalar, Dimension > _TTransform;
836   typedef
837   itk::LinearInterpolateImageFunction< TImage, TScalar >
838   _TInterpolator;
839   typedef
840   itk::ResampleImageFilter< TImage, _TScalarImage, TScalar, TScalar >
841   _TResample;
842   _TResample::Pointer resample = _TResample::New( );
843   resample->SetInput( segmentation );
844   resample->SetSize( n_size );
845   resample->SetOutputDirection( segmentation->GetDirection( ) );
846   resample->SetOutputOrigin( segmentation->GetOrigin( ) );
847   resample->SetOutputSpacing( n_spac );
848   resample->SetTransform( _TTransform::New( ) );
849   resample->SetInterpolator( _TInterpolator::New( ) );
850   resample->UpdateLargestPossibleRegion( );
851
852   // Try to smooth
853   typedef
854   itk::SignedDanielssonDistanceMapImageFilter< _TScalarImage, _TScalarImage >
855   _TDanielsson;
856   _TDanielsson::Pointer danielsson = _TDanielsson::New( );
857   danielsson->SetInput( resample->GetOutput( ) );
858   danielsson->Update( );
859
860   // Go back to ITK world
861   typedef cpm::VTK::PolyDataToMeshFilter< TTriangulation > TVTKPDataToMesh;
862   TVTKPDataToMesh::Pointer itk_mc = TVTKPDataToMesh::New( );
863   itk_mc->SetInput( danielsson_mc->GetOutput( ) );
864   itk_mc->Update( );
865   this->m_Mesh = itk_mc->GetOutput( );
866   this->m_Mesh->DisconnectPipeline( );
867
868   this->m_ZCutter = TCutter::New( );
869   this->m_ZCutter->SetInput( this->m_Mesh );
870
871   this->m_MeshMapper = vtkSmartPointer< TTriangulationMapper >::New( );
872   this->m_MeshActor = vtkSmartPointer< vtkActor >::New( );
873
874   this->m_MeshMapper->SetInputData( this->m_Mesh );
875   this->m_MeshActor->SetMapper( this->m_MeshMapper );
876   this->m_MeshActor->GetProperty( )->SetColor( 1, 1, 0 );
877   this->m_MeshActor->GetProperty( )->SetRepresentationToWireframe( );
878   this->m_3DRenderer->AddActor( this->m_MeshActor );
879   this->m_3DRenderer->ResetCamera( );
880   this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
881
882   } // fi
883   }
884 */
885
886 // eof - $RCSfile$