2 #include "ui_MainWnd.h"
11 #include <QDialogButtonBox>
12 #include <QDoubleSpinBox>
13 #include <QFileDialog>
14 #include <QGridLayout>
15 #include <QHBoxLayout>
17 #include <QMessageBox>
18 #include <QVBoxLayout>
20 #include <itkGDCMImageIO.h>
21 #include <itkImageFileReader.h>
22 #include <itkImageSeriesReader.h>
24 #include <vtkRenderWindow.h>
27 #include "ui_SegmentationParametersDlg.h"
32 #include <itkImageFileWriter.h>
33 #include <itkMinimumMaximumImageCalculator.h>
34 #include <itkBinaryMask3DMeshSource.h>
36 #include <itkIdentityTransform.h>
37 #include <itkLinearInterpolateImageFunction.h>
38 #include <itkResampleImageFilter.h>
39 #include <itkSignedDanielssonDistanceMapImageFilter.h>
40 #include <vtkImageMarchingCubes.h>
41 #include <cpm/VTK/PolyDataToMeshFilter.h>
42 #include <itkBinaryMinMaxCurvatureFlowImageFilter.h>
43 #include <itkLaplacianRecursiveGaussianImageFilter.h>
44 #include <itkThresholdImageFilter.h>
45 #include <itkSubtractImageFilter.h>
47 #include <vtkAnnotatedCubeActor.h>
48 #include <vtkAxesActor.h>
49 #include <vtkPropAssembly.h>
50 #include <vtkProperty.h>
51 #include <vtkTextProperty.h>
52 #include <vtkCallbackCommand.h>
54 #include <vtkCamera.h>
57 // -------------------------------------------------------------------------
58 #define IDMS_QT_ACTION( action ) \
60 this->m_UI->a##action, SIGNAL( triggered( ) ), \
61 this, SLOT( triggered_a##action( ) ) \
64 // -------------------------------------------------------------------------
65 MainWnd::MainWnd( QWidget* parent )
66 : QMainWindow( parent ),
67 m_UI( new Ui::MainWnd )
69 this->m_UI->setupUi( this );
72 this->m_LastOpenedFile = ".";
73 this->m_PluginsConfigurationFile = "idms.plugins";
75 // Create and associate renderers
76 this->m_3DRenderer = vtkSmartPointer< vtkRenderer >::New( );
77 this->m_XPlaneRenderer = vtkSmartPointer< vtkRenderer >::New( );
78 this->m_YPlaneRenderer = vtkSmartPointer< vtkRenderer >::New( );
79 this->m_ZPlaneRenderer = vtkSmartPointer< vtkRenderer >::New( );
80 this->m_AuxRenderer = vtkSmartPointer< vtkRenderer >::New( );
81 this->m_3DRenderer->SetBackground( 0.2, 0.2, 0.2 );
82 this->m_XPlaneRenderer->SetBackground( 0.1, 0.3, 0.8 );
83 this->m_YPlaneRenderer->SetBackground( 0.1, 0.3, 0.8 );
84 this->m_ZPlaneRenderer->SetBackground( 0.1, 0.3, 0.8 );
85 this->m_AuxRenderer->SetBackground( 0.1, 0.3, 0.8 );
86 this->m_UI->m_3DVTK->GetRenderWindow( )->
87 AddRenderer( this->m_3DRenderer );
88 this->m_UI->m_XPlaneVTK->GetRenderWindow( )->
89 AddRenderer( this->m_XPlaneRenderer );
90 this->m_UI->m_YPlaneVTK->GetRenderWindow( )->
91 AddRenderer( this->m_YPlaneRenderer );
92 this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->
93 AddRenderer( this->m_ZPlaneRenderer );
94 this->m_UI->m_AuxVTK->GetRenderWindow( )->
95 AddRenderer( this->m_AuxRenderer );
97 // Configure MPR actors
98 this->m_ImageActors = vtkSmartPointer< idms::VolumeActors >::New( );
100 // Interaction styles
101 this->m_XStyle = vtkSmartPointer< idms::InteractorStyleImage >::New( );
102 this->m_YStyle = vtkSmartPointer< idms::InteractorStyleImage >::New( );
103 this->m_ZStyle = vtkSmartPointer< idms::InteractorStyleImage >::New( );
104 this->m_XStyle->Configure( this->m_ImageActors, 0 );
105 this->m_YStyle->Configure( this->m_ImageActors, 1 );
106 this->m_ZStyle->Configure( this->m_ImageActors, 2 );
107 this->m_UI->m_XPlaneVTK->GetInteractor( )->
108 SetInteractorStyle( this->m_XStyle );
109 this->m_UI->m_YPlaneVTK->GetInteractor( )->
110 SetInteractorStyle( this->m_YStyle );
111 this->m_UI->m_ZPlaneVTK->GetInteractor( )->
112 SetInteractorStyle( this->m_ZStyle );
115 vtkSmartPointer< vtkCallbackCommand > z_callback =
116 vtkSmartPointer< vtkCallbackCommand >::New( );
117 z_callback->SetCallback( MainWnd::_SliceEventCallback );
118 z_callback->SetClientData( this );
119 zstyle->AddObserver( idms::InteractorStyleImage::SliceEvent, z_callback );
122 vtkSmartPointer< vtkAnnotatedCubeActor > oCube =
123 vtkSmartPointer< vtkAnnotatedCubeActor >::New( );
124 oCube->GetCubeProperty( )->SetColor( 0.9, 0.7, 0.2 );
125 oCube->GetTextEdgesProperty( )->SetLineWidth( 1 );
126 oCube->GetTextEdgesProperty( )->SetDiffuse( 0 );
127 oCube->GetTextEdgesProperty( )->SetAmbient( 1 );
128 oCube->GetTextEdgesProperty( )->SetColor( 0.18, 0.28, 0.23 );
129 oCube->GetXPlusFaceProperty( )->SetColor( 1, 0, 0 );
130 oCube->GetXPlusFaceProperty( )->SetInterpolationToFlat( );
131 oCube->GetXMinusFaceProperty( )->SetColor( 1, 0, 0 );
132 oCube->GetXMinusFaceProperty( )->SetInterpolationToFlat( );
133 oCube->GetYPlusFaceProperty( )->SetColor( 0, 1, 0 );
134 oCube->GetYPlusFaceProperty( )->SetInterpolationToFlat( );
135 oCube->GetYMinusFaceProperty( )->SetColor( 0, 1, 0 );
136 oCube->GetYMinusFaceProperty( )->SetInterpolationToFlat( );
137 oCube->GetZPlusFaceProperty( )->SetColor( 0, 0, 1 );
138 oCube->GetZPlusFaceProperty( )->SetInterpolationToFlat( );
139 oCube->GetZMinusFaceProperty( )->SetColor( 0, 0, 1 );
140 oCube->GetZMinusFaceProperty( )->SetInterpolationToFlat( );
142 vtkSmartPointer< vtkAxesActor > oAxes =
143 vtkSmartPointer< vtkAxesActor >::New( );
144 oAxes->AxisLabelsOff( );
145 oAxes->SetShaftTypeToCylinder( );
146 oAxes->SetTotalLength( 2.5, 2.5, 2.5 );
148 vtkSmartPointer< vtkPropAssembly > oActors =
149 vtkSmartPointer< vtkPropAssembly >::New( );
150 oActors->AddPart( oCube );
151 oActors->AddPart( oAxes );
153 this->m_3DOrientationWidget =
154 vtkSmartPointer< vtkOrientationMarkerWidget >::New( );
155 this->m_3DOrientationWidget->SetOutlineColor( 0.93, 0.57, 0.13 );
156 this->m_3DOrientationWidget->SetOrientationMarker( oActors );
157 this->m_3DOrientationWidget->SetViewport( 0.0, 0.0, 0.2, 0.2 );
159 // Add actors, widgets, stuff, ...
160 this->m_3DOrientationWidget->
161 SetInteractor( this->m_UI->m_3DVTK->GetInteractor( ) );
162 this->m_3DOrientationWidget->SetEnabled( 1 );
163 this->m_3DOrientationWidget->InteractiveOff( );
165 IDMS_QT_ACTION( aLoadInputImage );
166 IDMS_QT_ACTION( aLoadSegmentedImage );
168 // Qt signals <-> slots
170 this->m_UI->aNavigation, SIGNAL( triggered( ) ),
171 this, SLOT( triggered_aSwitchMode( ) )
174 this->m_UI->aSegmentationInteractiveDeformation, SIGNAL( triggered( ) ),
175 this, SLOT( triggered_aSwitchMode( ) )
178 IDMS_QT_ACTION( OpenInputImage );
179 IDMS_QT_ACTION( OpenSegmentedImage );
180 IDMS_QT_ACTION( ReloadPlugins );
182 // Start: load all disponible plugins
183 this->triggered_aReloadPlugins( );
186 // -------------------------------------------------------------------------
193 // -------------------------------------------------------------------------
195 _UpdateEnabledFlags( )
197 bool img = this->m_Image.IsNotNull( );
198 this->m_UI->menuSegmentInputImage->setEnabled( img );
199 this->m_UI->aOpenSegmentedImage->setEnabled( img );
200 this->m_UI->m_3DVTK->setEnabled( img );
201 this->m_UI->m_XPlaneVTK->setEnabled( img );
202 this->m_UI->m_YPlaneVTK->setEnabled( img );
203 this->m_UI->m_ZPlaneVTK->setEnabled( img );
204 this->m_UI->m_AuxVTK->setEnabled( img );
206 bool seg = this->m_Segmentation.IsNotNull( );
207 this->m_UI->menuFilterSegmentedImage->setEnabled( seg );
208 this->m_UI->menuExtractMesh->setEnabled( seg );
209 this->m_UI->aOpenMesh->setEnabled( seg );
211 this->m_UI->aNavigation->setEnabled( img && seg );
212 this->m_UI->aSegmentationInteractiveDeformation->setEnabled( img && seg );
219 // -------------------------------------------------------------------------
221 _ParametersDialog( TParameters& parameters )
224 QGridLayout gridLayout( &dlg );
225 QVBoxLayout verticalLayout;
228 typedef std::map< std::string, QWidget* > _TWidgets;
230 TParameters::const_iterator pIt = parameters.begin( );
231 for( ; pIt != parameters.end( ); ++pIt )
233 unsigned long pos = pIt->first.find_last_of( ":" );
234 std::string v_name = pIt->first.substr( 0, pos );
235 std::string v_type = pIt->first.substr( pos + 1 );
237 QHBoxLayout* horizontalLayout = new QHBoxLayout( );
238 QLabel* label = new QLabel( &dlg );
239 label->setText( QString( v_name.c_str( ) ) );
240 horizontalLayout->addWidget( label );
241 if( v_type == "real" )
243 QDoubleSpinBox* v_double = new QDoubleSpinBox( &dlg );
244 v_double->setDecimals( 3 );
245 v_double->setMinimum( -( std::numeric_limits< double >::max( ) ) );
246 v_double->setMaximum( std::numeric_limits< double >::max( ) );
247 v_double->setValue( std::atof( pIt->second.c_str( ) ) );
248 horizontalLayout->addWidget( v_double );
249 widgets[ pIt->first ] = v_double;
251 else if( v_type == "atomic_real" )
253 if( v_name == "MeshType" )
255 QLabel* info = new QLabel( &dlg );
256 if( typeid( TScalar ) == typeid( float ) )
257 info->setText( QString( "float" ) );
258 else if( typeid( TScalar ) == typeid( double ) )
259 info->setText( QString( "double" ) );
260 horizontalLayout->addWidget( info );
261 widgets[ pIt->first ] = info;
266 verticalLayout.addLayout( horizontalLayout );
269 gridLayout.addLayout( &verticalLayout, 0, 0, 1, 1 );
272 QDialogButtonBox buttonBox( &dlg );
273 buttonBox.setOrientation( Qt::Horizontal );
274 buttonBox.setStandardButtons(
275 QDialogButtonBox::Cancel | QDialogButtonBox::Ok
277 gridLayout.addWidget( &buttonBox, 1, 0, 1, 1 );
279 &buttonBox, SIGNAL( accepted( ) ),
280 &dlg, SLOT( accept( ) )
283 &buttonBox, SIGNAL( rejected( ) ),
284 &dlg, SLOT( reject( ) )
286 QMetaObject::connectSlotsByName( &dlg );
289 if( dlg.exec( ) == QDialog::Accepted )
291 _TWidgets::const_iterator wIt = widgets.begin( );
292 for( ; wIt != widgets.end( ); ++wIt )
294 unsigned long pos = wIt->first.find_last_of( ":" );
295 std::string v_name = wIt->first.substr( 0, pos );
296 std::string v_type = wIt->first.substr( pos + 1 );
297 std::stringstream sstr;
298 if( v_type == "real" )
300 QDoubleSpinBox* v_double =
301 dynamic_cast< QDoubleSpinBox* >( wIt->second );
302 if( v_double != NULL )
303 sstr << v_double->value( );
305 else if( v_type == "atomic_real" )
307 if( v_name == "MeshType" )
309 QLabel* info = dynamic_cast< QLabel* >( wIt->second );
311 sstr << info->text( ).toStdString( );
316 parameters[ wIt->first ] = sstr.str( );
324 // -------------------------------------------------------------------------
327 _LoadImage( typename I::Pointer& image )
330 QFileDialog::getOpenFileNames(
332 tr( "Open an image" ),
333 tr( this->m_LastOpenedFile.c_str( ) ),
334 tr( "Medical image files (*.mhd *.bin *.dcm);;All files (*)" )
336 if( qList.size( ) == 0 )
340 QStringList::Iterator fIt = qList.begin( );
341 if( qList.size( ) == 1 )
343 // Read a single image
344 std::string fn = fIt->toStdString( );
345 this->m_LastOpenedFile = fn;
347 typename itk::ImageFileReader< I >::Pointer reader =
348 itk::ImageFileReader< I >::New( );
349 reader->SetFileName( fn );
354 catch( itk::ExceptionObject& err )
356 QMessageBox::critical(
358 tr( "Error opening single image!" ),
359 tr( err.GetDescription( ) )
364 image = reader->GetOutput( );
365 image->DisconnectPipeline( );
367 else if( qList.size( ) > 1 )
369 typedef std::set< std::string > _TOrderedStringList;
372 _TOrderedStringList filenames;
373 for( ; fIt != qList.end( ); ++fIt )
374 filenames.insert( fIt->toStdString( ) );
375 typename itk::ImageSeriesReader< I >::Pointer reader =
376 itk::ImageSeriesReader< I >::New( );
377 reader->SetImageIO( itk::GDCMImageIO::New( ) );
378 _TOrderedStringList::const_iterator oIt = filenames.begin( );
379 for( ; oIt != filenames.end( ); ++oIt )
381 reader->AddFileName( *oIt );
382 this->m_LastOpenedFile = *oIt;
389 catch( itk::ExceptionObject& err )
391 QMessageBox::critical(
393 tr( "Error opening image series!" ),
394 tr( err.GetDescription( ) )
399 image = reader->GetOutput( );
400 image->DisconnectPipeline( );
406 // -------------------------------------------------------------------------
408 triggered_aSwitchMode( )
410 QAction* snd = dynamic_cast< QAction* >( this->sender( ) );
411 if( snd == this->m_UI->aNavigation )
413 this->m_UI->aSegmentationInteractiveDeformation->setChecked(
414 !( this->m_UI->aNavigation->isChecked( ) )
417 else if( snd == this->m_UI->aSegmentationInteractiveDeformation )
419 this->m_UI->aNavigation->setChecked(
420 !( this->m_UI->aSegmentationInteractiveDeformation->isChecked( ) )
425 this->m_UI->aNavigation->setChecked( true );
426 this->m_UI->aSegmentationInteractiveDeformation->setChecked( false );
430 if( this->m_UI->aNavigation->isChecked( ) )
432 this->m_XStyle->SetModeToNavigation( );
433 this->m_YStyle->SetModeToNavigation( );
434 this->m_ZStyle->SetModeToNavigation( );
435 this->m_ImageActors->HideRegion( 0 );
436 this->m_ImageActors->HideRegion( 1 );
437 this->m_ImageActors->HideRegion( 2 );
438 this->m_3DRenderer->RemoveActor(
439 this->m_ImageActors->GetCursorActor( )
441 this->m_3DRenderer->RemoveActor(
442 this->m_ImageActors->GetRegionActor( )
444 this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
446 else if( this->m_UI->aSegmentationInteractiveDeformation->isChecked( ) )
448 this->m_XStyle->SetModeToDeformation( );
449 this->m_YStyle->SetModeToDeformation( );
450 this->m_ZStyle->SetModeToDeformation( );
451 this->m_ImageActors->ShowRegion( 0 );
452 this->m_ImageActors->ShowRegion( 1 );
453 this->m_ImageActors->ShowRegion( 2 );
454 this->m_3DRenderer->AddActor(
455 this->m_ImageActors->GetCursorActor( )
457 this->m_3DRenderer->AddActor(
458 this->m_ImageActors->GetRegionActor( )
460 this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
465 // -------------------------------------------------------------------------
467 triggered_aReloadPlugins( )
469 this->m_FilterPlugins.UnloadAll( );
471 std::ifstream in( this->m_PluginsConfigurationFile.c_str( ) );
475 std::getline( in, plugin );
476 while( !( in.eof( ) ) )
478 if( this->m_FilterPlugins.Load( plugin ) )
480 TFilterPlugins::TClassesIterator cIt =
481 this->m_FilterPlugins.BeginClasses( );
482 for( ; cIt != this->m_FilterPlugins.EndClasses( ); ++cIt )
484 TFilterObject* filter =
485 this->m_FilterPlugins.CreateObject( cIt->first );
488 std::string cat = filter->GetCategory( );
489 std::string catType = cat.substr( cat.find_last_of( ":" ) );
490 if( catType == ":BinaryImageToBinaryImageFilter" )
492 QAction* action = this->m_UI->menuFilterSegmentedImage->
493 addAction( QString( cIt->first.c_str( ) ) );
495 action, SIGNAL( triggered( ) ),
496 this, SLOT( triggered_aFilterSegmentedImage( ) )
499 else if( catType == ":ImageToMeshFilter" )
501 QAction* action = this->m_UI->menuExtractMesh->
502 addAction( QString( cIt->first.c_str( ) ) );
504 action, SIGNAL( triggered( ) ),
505 this, SLOT( triggered_aSegmentedImageToMesh( ) )
516 << "Ignoring \"" << plugin << "\""
518 std::getline( in, plugin );
524 QMessageBox::critical(
526 tr( "No plugins file loaded!" ),
527 tr( "No plugins file loaded!" )
532 this->_UpdateEnabledFlags( );
535 // -------------------------------------------------------------------------
537 triggered_aOpenInputImage( )
539 if( this->_LoadImage< TImage >( this->m_Image ) )
541 // Connect image to VTK
542 this->m_VTKImage = TVTKImage::New( );
543 this->m_VTKImage->SetInput( this->m_Image );
544 this->m_VTKImage->Update( );
546 this->m_ImageActors->Configure(
547 this->m_VTKImage->GetOutput( ),
548 this->m_UI->m_XPlaneVTK->GetInteractor( ),
549 this->m_UI->m_YPlaneVTK->GetInteractor( ),
550 this->m_UI->m_ZPlaneVTK->GetInteractor( )
552 this->m_ImageActors->
553 AddAuxiliaryInteractor( this->m_UI->m_3DVTK->GetInteractor( ) );
556 this->m_3DRenderer->AddActor(
557 this->m_ImageActors->GetImageOutlineActor( )
559 this->m_3DRenderer->AddActor(
560 this->m_ImageActors->GetXBoundsActor( )
562 this->m_3DRenderer->AddActor(
563 this->m_ImageActors->GetYBoundsActor( )
565 this->m_3DRenderer->AddActor(
566 this->m_ImageActors->GetZBoundsActor( )
570 this->m_3DRenderer->ResetCamera( );
571 this->m_ImageActors->ResetCameras( );
574 this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
575 this->m_UI->m_XPlaneVTK->GetRenderWindow( )->Render( );
576 this->m_UI->m_YPlaneVTK->GetRenderWindow( )->Render( );
577 this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->Render( );
578 this->_UpdateEnabledFlags( );
579 this->m_UI->aNavigation->setChecked( true );
580 this->triggered_aSwitchMode( );
585 // -------------------------------------------------------------------------
587 triggered_aOpenSegmentedImage( )
589 if( this->_LoadImage< TImage >( this->m_Segmentation ) )
591 // Connect image to VTK
592 this->m_VTKSegmentation = TVTKImage::New( );
593 this->m_VTKSegmentation->SetInput( this->m_Segmentation );
594 this->m_VTKSegmentation->Update( );
596 this->m_ImageActors->SetSegmentation(
597 this->m_VTKSegmentation->GetOutput( )
601 this->m_UI->m_XPlaneVTK->GetRenderWindow( )->Render( );
602 this->m_UI->m_YPlaneVTK->GetRenderWindow( )->Render( );
603 this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->Render( );
604 this->_UpdateEnabledFlags( );
609 // -------------------------------------------------------------------------
611 triggered_aFilterSegmentedImage( )
614 if( this->m_Segmentation.IsNull( ) )
616 QAction* action = dynamic_cast< QAction* >( this->sender( ) );
619 std::string filter_name = action->text( ).toStdString( );
622 TFilterObject* filter = this->m_FilterPlugins.CreateObject( filter_name );
626 TParameters parameters = filter->GetDefaultParameters( );
627 if( !( this->_ParametersDialog( parameters ) ) )
629 filter->SetInput( this->m_Segmentation );
630 filter->SetParameters( parameters );
631 std::string result = filter->Update( );
633 // Get modified segmentation
635 this->m_Mesh = filter->GetCastedOutput< TMesh >( );
636 if( this->m_Mesh.IsNotNull( ) )
638 this->m_Mesh->DisconnectPipeline( );
642 // Ok, it seems to have runned fine
646 // -------------------------------------------------------------------------
648 triggered_aSegmentedImageToMesh( )
651 if( this->m_Segmentation.IsNull( ) )
653 QAction* action = dynamic_cast< QAction* >( this->sender( ) );
656 std::string filter_name = action->text( ).toStdString( );
659 TFilterObject* filter = this->m_FilterPlugins.CreateObject( filter_name );
663 TParameters parameters = filter->GetDefaultParameters( );
664 if( !( this->_ParametersDialog( parameters ) ) )
666 filter->SetInput( this->m_Segmentation );
667 filter->SetParameters( parameters );
668 std::string result = filter->Update( );
671 this->m_Mesh = filter->GetCastedOutput< TMesh >( );
672 if( this->m_Mesh.IsNotNull( ) )
674 this->m_Mesh->DisconnectPipeline( );
678 // Ok, it seems to have runned fine
682 // -------------------------------------------------------------------------
685 _SliceMesh( int axis )
687 TCutter* cutter = NULL;
688 if( axis == 2 ) cutter = this->m_ZCutter;
693 vtkPlane* vplane = this->m_ImageActors->GetSlicePlane( axis );
694 double vorigin[ 3 ], vnormal[ 3 ];
695 vplane->GetOrigin( vorigin );
696 vplane->GetNormal( vnormal );
698 TCutter::TVector corigin, cnormal;
699 corigin[ 0 ] = TScalar( vorigin[ 0 ] );
700 corigin[ 1 ] = TScalar( vorigin[ 1 ] );
701 corigin[ 2 ] = TScalar( vorigin[ 2 ] );
702 cnormal[ 0 ] = TScalar( vnormal[ 0 ] );
703 cnormal[ 1 ] = TScalar( vnormal[ 1 ] );
704 cnormal[ 2 ] = TScalar( vnormal[ 2 ] );
706 cutter->SetPlanePoint( corigin );
707 cutter->SetPlaneNormal( cnormal );
711 // -------------------------------------------------------------------------
715 long unsigned int eventId,
716 void* clientData, void* callData
719 if( clientData == NULL || callData == NULL )
721 MainWnd* wnd = reinterpret_cast< MainWnd* >( clientData );
722 int axis = *( reinterpret_cast< int* >( callData ) );
725 if( eventId == idms::InteractorStyleImage::SliceEvent )
726 wnd->_SliceMesh( axis );
729 // -------------------------------------------------------------------------
731 triggered_aLoadImage( )
733 if( this->_LoadImage< TImage >( this->m_Image ) )
735 // Connect image to VTK
736 this->m_VTKImage->SetInput( this->m_Image );
737 this->m_VTKImage->Update( );
738 this->m_ImageActors->Configure(
739 this->m_VTKImage->GetOutput( ),
740 this->m_UI->m_XPlaneVTK->GetInteractor( ),
741 this->m_UI->m_YPlaneVTK->GetInteractor( ),
742 this->m_UI->m_ZPlaneVTK->GetInteractor( )
744 this->m_ImageActors->
745 AddAuxiliaryInteractor( this->m_UI->m_3DVTK->GetInteractor( ) );
748 this->m_3DRenderer->AddActor(
749 this->m_ImageActors->GetImageOutlineActor( )
751 this->m_3DRenderer->AddActor(
752 this->m_ImageActors->GetXBoundsActor( )
754 this->m_3DRenderer->AddActor(
755 this->m_ImageActors->GetYBoundsActor( )
757 this->m_3DRenderer->AddActor(
758 this->m_ImageActors->GetZBoundsActor( )
762 this->m_3DRenderer->ResetCamera( );
763 this->m_ImageActors->ResetCameras( );
766 this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
767 this->m_UI->m_XPlaneVTK->GetRenderWindow( )->Render( );
768 this->m_UI->m_YPlaneVTK->GetRenderWindow( )->Render( );
769 this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->Render( );
772 this->m_UI->aLoadSegmentedImage->setEnabled( true );
773 this->m_UI->aSegmentImage->setEnabled( true );
774 this->m_UI->m_3DVTK->setEnabled( true );
775 this->m_UI->m_XPlaneVTK->setEnabled( true );
776 this->m_UI->m_YPlaneVTK->setEnabled( true );
777 this->m_UI->m_ZPlaneVTK->setEnabled( true );
782 // -------------------------------------------------------------------------
784 triggered_aLoadSegmentedImage( )
786 if( this->m_Mesh.IsNotNull( ) )
788 QMessageBox::critical(
790 tr( "Mesh already loaded!" ),
791 tr( "Mesh already loaded!" )
797 if( this->_LoadImage< TImage >( this->m_Segmentation ) )
799 // Compute segmentation values
800 itk::MinimumMaximumImageCalculator< TImage >::Pointer minmax =
801 itk::MinimumMaximumImageCalculator< TImage >::New( );
802 minmax->SetImage( this->m_Segmentation );
804 TPixel min_v = minmax->GetMinimum( );
805 TPixel max_v = minmax->GetMaximum( );
806 double thr = double( max_v + min_v ) / double( 2 );
808 typedef itk::Image< TScalar, Dimension > _TScalarImage;
810 itk::BinaryMinMaxCurvatureFlowImageFilter< TImage, _TScalarImage >
812 typedef _TFilter::TimeStepType _TTimeStep;
813 typedef _TFilter::RadiusValueType _TRadius;
815 _TFilter::Pointer filter = _TFilter::New( );
816 filter->SetInput( this->m_Segmentation );
817 filter->SetTimeStep( _TTimeStep( 0.0625 ) );
818 filter->SetNumberOfIterations( 10 );
819 filter->SetStencilRadius( _TRadius( 3 ) );
820 filter->SetThreshold( thr );
823 itk::ImageFileWriter< _TScalarImage >::Pointer w =
824 itk::ImageFileWriter< _TScalarImage >::New( );
825 w->SetInput( filter->GetOutput( ) );
826 w->SetFileName( "no_noise.mhd" );
831 itk::LaplacianRecursiveGaussianImageFilter< TImage, _TScalarImage >
833 _TFilter::Pointer filter = _TFilter::New( );
834 filter->SetInput( this->m_Segmentation );
835 filter->SetSigma( 3 ); // in spacing units
836 filter->SetNormalizeAcrossScale( false );
838 typedef itk::ThresholdImageFilter< _TScalarImage > _TThreshold;
839 _TThreshold::Pointer threshold = _TThreshold::New( );
840 threshold->SetInput( filter->GetOutput( ) );
841 threshold->ThresholdAbove( TScalar( 0 ) );
842 threshold->InPlaceOff( );
843 threshold->Update( );
845 itk::MinimumMaximumImageCalculator< _TScalarImage >::Pointer t_minmax =
846 itk::MinimumMaximumImageCalculator< _TScalarImage >::New( );
847 t_minmax->SetImage( threshold->GetOutput( ) );
848 t_minmax->Compute( );
849 TScalar min_t = t_minmax->GetMinimum( );
851 std::cout << min_t << " " << t_minmax->GetMaximum( ) << std::endl;
853 itk::SubtractImageFilter< _TScalarImage >::Pointer subtract =
854 itk::SubtractImageFilter< _TScalarImage >::New( );
855 subtract->SetInput1( threshold->GetOutput( ) );
856 subtract->SetConstant2( min_t );
858 itk::ImageFileWriter< _TScalarImage >::Pointer w =
859 itk::ImageFileWriter< _TScalarImage >::New( );
860 w->SetInput( subtract->GetOutput( ) );
861 w->SetFileName( "no_noise_laplace_2.mhd" );
865 // Pass segmentation to VTK
866 this->m_VTKSegmentation = TVTKImage::New( );
867 this->m_VTKSegmentation->SetInput( this->m_Segmentation );
868 this->m_VTKSegmentation->Update( );
870 // Use VTK's marching cubes (it is smoother)
871 vtkSmartPointer< vtkImageMarchingCubes > segmentation_mc =
872 vtkSmartPointer< vtkImageMarchingCubes >::New( );
873 segmentation_mc->SetInputData( this->m_VTKSegmentation->GetOutput( ) );
874 segmentation_mc->SetValue( 0, thr );
875 segmentation_mc->Update( );
877 // Go back to ITK world
878 typedef cpm::VTK::PolyDataToMeshFilter< TTriangulation > _TVTKPDataToMesh;
879 _TVTKPDataToMesh::Pointer itk_mc = _TVTKPDataToMesh::New( );
880 itk_mc->SetInput( segmentation_mc->GetOutput( ) );
882 this->m_Mesh = itk_mc->GetOutput( );
883 this->m_Mesh->DisconnectPipeline( );
885 this->m_MeshMapper = vtkSmartPointer< TTriangulationMapper >::New( );
886 this->m_MeshActor = vtkSmartPointer< vtkActor >::New( );
888 this->m_MeshMapper->SetInputData( this->m_Mesh );
889 this->m_MeshActor->SetMapper( this->m_MeshMapper );
890 this->m_MeshActor->GetProperty( )->SetColor( 1, 1, 0 );
891 this->m_MeshActor->GetProperty( )->SetRepresentationToWireframe( );
892 this->m_3DRenderer->AddActor( this->m_MeshActor );
893 this->m_3DRenderer->ResetCamera( );
894 this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
896 unsigned int reduction = 20;
898 typedef TImage::SpacingType::ValueType _TValue;
901 // Compute downsize parameters
902 TImage::SizeType o_size =
903 segmentation->GetLargestPossibleRegion( ).GetSize( );
904 TImage::SpacingType o_spac = segmentation->GetSpacing( );
905 _TValue min_spac = std::numeric_limits< _TValue >::max( );
906 for( unsigned int d = 0; d < Dimension; ++d )
907 min_spac = ( o_spac[ d ] < min_spac )? o_spac[ d ]: min_spac;
908 min_spac *= _TValue( reduction );
909 TImage::SpacingType n_spac( min_spac );
910 TImage::SizeType n_size;
911 for( unsigned int d = 0; d < Dimension; ++d )
912 n_size[ d ] = ( unsigned long )(
913 _TValue( o_size[ d ] ) * o_spac[ d ] / min_spac
917 typedef itk::Image< TScalar, Dimension > _TScalarImage;
918 typedef itk::IdentityTransform< TScalar, Dimension > _TTransform;
920 itk::LinearInterpolateImageFunction< TImage, TScalar >
923 itk::ResampleImageFilter< TImage, _TScalarImage, TScalar, TScalar >
925 _TResample::Pointer resample = _TResample::New( );
926 resample->SetInput( segmentation );
927 resample->SetSize( n_size );
928 resample->SetOutputDirection( segmentation->GetDirection( ) );
929 resample->SetOutputOrigin( segmentation->GetOrigin( ) );
930 resample->SetOutputSpacing( n_spac );
931 resample->SetTransform( _TTransform::New( ) );
932 resample->SetInterpolator( _TInterpolator::New( ) );
933 resample->UpdateLargestPossibleRegion( );
937 itk::SignedDanielssonDistanceMapImageFilter< _TScalarImage, _TScalarImage >
939 _TDanielsson::Pointer danielsson = _TDanielsson::New( );
940 danielsson->SetInput( resample->GetOutput( ) );
941 danielsson->Update( );
943 // Go back to ITK world
944 typedef cpm::VTK::PolyDataToMeshFilter< TTriangulation > TVTKPDataToMesh;
945 TVTKPDataToMesh::Pointer itk_mc = TVTKPDataToMesh::New( );
946 itk_mc->SetInput( danielsson_mc->GetOutput( ) );
948 this->m_Mesh = itk_mc->GetOutput( );
949 this->m_Mesh->DisconnectPipeline( );
951 this->m_ZCutter = TCutter::New( );
952 this->m_ZCutter->SetInput( this->m_Mesh );
954 this->m_MeshMapper = vtkSmartPointer< TTriangulationMapper >::New( );
955 this->m_MeshActor = vtkSmartPointer< vtkActor >::New( );
957 this->m_MeshMapper->SetInputData( this->m_Mesh );
958 this->m_MeshActor->SetMapper( this->m_MeshMapper );
959 this->m_MeshActor->GetProperty( )->SetColor( 1, 1, 0 );
960 this->m_MeshActor->GetProperty( )->SetRepresentationToWireframe( );
961 this->m_3DRenderer->AddActor( this->m_MeshActor );
962 this->m_3DRenderer->ResetCamera( );
963 this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );