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