00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "QmitkSegmentationPostProcessing.h"
00019 #include "QmitkNodeDescriptorManager.h"
00020 #include "QmitkToolGUI.h"
00021
00022 #include "mitkAutoCropImageFilter.h"
00023 #include "mitkBinaryThresholdTool.h"
00024 #include "mitkRenderingManager.h"
00025 #include "mitkShowSegmentationAsSurface.h"
00026 #include "mitkProgressBar.h"
00027 #include "mitkStatusBar.h"
00028 #include "mitkImageCast.h"
00029 #include "mitkDataNodeObject.h"
00030
00031 #include <QtGui>
00032
00033 #include <berryIWorkbenchPage.h>
00034
00035 #include <itkConstantPadImageFilter.h>
00036
00037 QmitkSegmentationPostProcessing::QmitkSegmentationPostProcessing(mitk::DataStorage* storage, QmitkFunctionality* functionality, QObject* parent)
00038 :QObject(parent)
00039 ,m_BlueBerryView(functionality)
00040 ,m_DataStorage(storage)
00041 {
00042
00043 QmitkNodeDescriptor* imageDataNodeDescriptor =
00044 QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("NoneBinaryImage");
00045
00046 if (imageDataNodeDescriptor)
00047 {
00048 m_ThresholdAction = new QAction("Threshold..", parent);
00049 imageDataNodeDescriptor->AddAction(m_ThresholdAction);
00050 connect( m_ThresholdAction, SIGNAL( triggered(bool) ) , this, SLOT( ThresholdImage(bool) ) );
00051 }
00052 else
00053 {
00054 MITK_WARN << "Could not get datamanager's node descriptor for 'Image'";
00055 }
00056
00057
00058 QmitkNodeDescriptor* binaryImageDataNodeDescriptor =
00059 QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("ImageMask");
00060
00061 if (binaryImageDataNodeDescriptor)
00062 {
00063 m_CreateSurfaceAction = new QAction("Create polygon model", parent);
00064 binaryImageDataNodeDescriptor->AddAction(m_CreateSurfaceAction);
00065 connect( m_CreateSurfaceAction, SIGNAL( triggered(bool) ) , this, SLOT( CreateSurface(bool) ) );
00066
00067 m_CreateSmoothSurfaceAction = new QAction("Create smoothed polygon model", parent);
00068 binaryImageDataNodeDescriptor->AddAction(m_CreateSmoothSurfaceAction);
00069 connect( m_CreateSmoothSurfaceAction, SIGNAL( triggered(bool) ) , this, SLOT( CreateSmoothedSurface(bool) ) );
00070
00071 m_StatisticsAction = new QAction("Statistics", parent);
00072 binaryImageDataNodeDescriptor->AddAction(m_StatisticsAction);
00073 berry::IBundle::Pointer imageStatisticsBundle = berry::Platform::GetBundle("org.mitk.gui.qt.imagestatistics");
00074 if(imageStatisticsBundle.IsNotNull())
00075 connect( m_StatisticsAction, SIGNAL( triggered(bool) ) , this, SLOT( ImageStatistics(bool) ) );
00076 else
00077 m_StatisticsAction->setEnabled( false );
00078
00079 m_AutocropAction = new QAction("Autocrop", parent);
00080 binaryImageDataNodeDescriptor->AddAction(m_AutocropAction);
00081 connect( m_AutocropAction, SIGNAL( triggered(bool) ) , this, SLOT( AutocropSelected(bool) ) );
00082 }
00083 else
00084 {
00085 MITK_WARN << "Could not get datamanager's node descriptor for 'ImageMask'";
00086 }
00087
00088
00089 m_SelectionListener = berry::ISelectionListener::Pointer(new berry::SelectionChangedAdapter<QmitkSegmentationPostProcessing>(this, &QmitkSegmentationPostProcessing::SelectionChanged));
00090 m_BlueBerryView->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener( m_SelectionListener);
00091 }
00092
00093 QmitkSegmentationPostProcessing::~QmitkSegmentationPostProcessing()
00094 {
00095 berry::ISelectionService* s = m_BlueBerryView->GetSite()->GetWorkbenchWindow()->GetSelectionService();
00096 if(s)
00097 {
00098 s->RemovePostSelectionListener(m_SelectionListener);
00099 }
00100
00101
00102 QmitkNodeDescriptor* imageDataNodeDescriptor =
00103 QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Image");
00104
00105 if (imageDataNodeDescriptor)
00106 {
00107 imageDataNodeDescriptor->RemoveAction( m_ThresholdAction );
00108 }
00109 else
00110 {
00111 MITK_WARN << "Could not get datamanager's node descriptor for 'Image'";
00112 }
00113
00114
00115 QmitkNodeDescriptor* binaryImageDataNodeDescriptor =
00116 QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("ImageMask");
00117
00118 if (binaryImageDataNodeDescriptor)
00119 {
00120 binaryImageDataNodeDescriptor->RemoveAction( m_CreateSurfaceAction );
00121 binaryImageDataNodeDescriptor->RemoveAction( m_CreateSmoothSurfaceAction );
00122 binaryImageDataNodeDescriptor->RemoveAction( m_StatisticsAction );
00123 binaryImageDataNodeDescriptor->RemoveAction( m_AutocropAction );
00124 }
00125 else
00126 {
00127 MITK_WARN << "Could not get datamanager's node descriptor for 'ImageMask'";
00128 }
00129 }
00130
00131 void QmitkSegmentationPostProcessing::SelectionChanged(berry::IWorkbenchPart::Pointer , berry::ISelection::ConstPointer selection)
00132 {
00133 if ( selection.IsNull() )
00134 {
00135 return;
00136 }
00137
00138
00139 m_CurrentSelection = selection.Cast<const mitk::DataNodeSelection>();
00140 }
00141
00142 QmitkSegmentationPostProcessing::NodeList QmitkSegmentationPostProcessing::GetSelectedNodes() const
00143 {
00144 NodeList result;
00145 if (m_CurrentSelection)
00146 {
00147
00148
00149 for (mitk::DataNodeSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i)
00150 {
00151
00152 if (mitk::DataNodeObject::Pointer nodeObj = i->Cast<mitk::DataNodeObject>())
00153 {
00154 mitk::DataNode::Pointer node = nodeObj->GetDataNode();
00155 result.push_back( node );
00156 }
00157 }
00158 }
00159
00160 return result;
00161 }
00162
00163 void QmitkSegmentationPostProcessing::ThresholdImage(bool)
00164 {
00165 NodeList selection = this->GetSelectedNodes();
00166
00167 m_ThresholdingToolManager = mitk::ToolManager::New( m_DataStorage );
00168 m_ThresholdingToolManager->RegisterClient();
00169 m_ThresholdingToolManager->ActiveToolChanged +=
00170 mitk::MessageDelegate<QmitkSegmentationPostProcessing>( this, &QmitkSegmentationPostProcessing::OnThresholdingToolManagerToolModified );
00171
00172 m_ThresholdingDialog = new QDialog(qobject_cast<QWidget *>(parent()));
00173 connect( m_ThresholdingDialog, SIGNAL(finished(int)), this, SLOT(ThresholdingDone(int)) );
00174
00175 QVBoxLayout* layout = new QVBoxLayout;
00176 layout->setContentsMargins(0, 0, 0, 0);
00177
00178 mitk::Tool* tool = m_ThresholdingToolManager->GetToolById( m_ThresholdingToolManager->GetToolIdByToolType<mitk::BinaryThresholdTool>() );
00179 if (tool)
00180 {
00181 itk::Object::Pointer possibleGUI = tool->GetGUI("Qmitk", "GUI");
00182 QmitkToolGUI* gui = dynamic_cast<QmitkToolGUI*>( possibleGUI.GetPointer() );
00183 if (gui)
00184 {
00185 gui->SetTool(tool);
00186 gui->setParent(m_ThresholdingDialog);
00187 layout->addWidget(gui);
00188 m_ThresholdingDialog->setLayout(layout);
00189 layout->activate();
00190 m_ThresholdingDialog->setFixedSize(300,75);
00191 m_ThresholdingDialog->open();
00192 }
00193 }
00194
00195 for ( NodeList::iterator iter = selection.begin(); iter != selection.end(); ++iter )
00196 {
00197 mitk::DataNode* node = *iter;
00198
00199 if (node)
00200 {
00201 m_ThresholdingToolManager->SetReferenceData( node );
00202 m_ThresholdingToolManager->ActivateTool( m_ThresholdingToolManager->GetToolIdByToolType<mitk::BinaryThresholdTool>() );
00203 }
00204 }
00205 }
00206
00207 void QmitkSegmentationPostProcessing::ThresholdingDone(int result)
00208 {
00209 if (result == QDialog::Rejected)
00210 m_ThresholdingToolManager->ActivateTool(-1);
00211 MITK_INFO << "Thresholding done, cleaning up";
00212 m_ThresholdingDialog->deleteLater();
00213 m_ThresholdingDialog = NULL;
00214 m_ThresholdingToolManager->SetReferenceData( NULL );
00215 m_ThresholdingToolManager->SetWorkingData( NULL );
00216
00217 mitk::RenderingManager::GetInstance()->RequestUpdateAll();
00218 }
00219
00220 void QmitkSegmentationPostProcessing::OnThresholdingToolManagerToolModified()
00221 {
00222 if ( m_ThresholdingToolManager.IsNull() ) return;
00223
00224
00225
00226 if ( m_ThresholdingToolManager->GetActiveToolID() < 0)
00227 {
00228 if (m_ThresholdingDialog)
00229 m_ThresholdingDialog->accept();
00230 }
00231 }
00232
00233 void QmitkSegmentationPostProcessing::CreateSmoothedSurface(bool)
00234 {
00235 InternalCreateSurface(true);
00236 }
00237
00238 void QmitkSegmentationPostProcessing::CreateSurface(bool)
00239 {
00240 InternalCreateSurface(false);
00241 }
00242
00243 void QmitkSegmentationPostProcessing::InternalCreateSurface(bool smoothed)
00244 {
00245 NodeList selection = this->GetSelectedNodes();
00246
00247 for ( NodeList::iterator iter = selection.begin(); iter != selection.end(); ++iter )
00248 {
00249 mitk::DataNode* node = *iter;
00250
00251 if (node)
00252 {
00253 mitk::Image::Pointer image = dynamic_cast<mitk::Image*>( node->GetData() );
00254 if (image.IsNull()) return;
00255
00256 try
00257 {
00258 mitk::ShowSegmentationAsSurface::Pointer surfaceFilter = mitk::ShowSegmentationAsSurface::New();
00259
00260
00261 itk::SimpleMemberCommand<QmitkSegmentationPostProcessing>::Pointer goodCommand = itk::SimpleMemberCommand<QmitkSegmentationPostProcessing>::New();
00262 goodCommand->SetCallbackFunction(this, &QmitkSegmentationPostProcessing::OnSurfaceCalculationDone);
00263 surfaceFilter->AddObserver(mitk::ResultAvailable(), goodCommand);
00264 itk::SimpleMemberCommand<QmitkSegmentationPostProcessing>::Pointer badCommand = itk::SimpleMemberCommand<QmitkSegmentationPostProcessing>::New();
00265 badCommand->SetCallbackFunction(this, &QmitkSegmentationPostProcessing::OnSurfaceCalculationDone);
00266 surfaceFilter->AddObserver(mitk::ProcessingError(), badCommand);
00267
00268 mitk::DataNode::Pointer nodepointer = node;
00269 surfaceFilter->SetPointerParameter("Input", image);
00270 surfaceFilter->SetPointerParameter("Group node", nodepointer);
00271 surfaceFilter->SetParameter("Show result", true );
00272 surfaceFilter->SetParameter("Sync visibility", false );
00273 surfaceFilter->SetDataStorage( *m_DataStorage );
00274
00275 if (smoothed)
00276 {
00277 surfaceFilter->SetParameter("Smooth", true );
00278
00279 surfaceFilter->SetParameter("Apply median", false );
00280 surfaceFilter->SetParameter("Median kernel size", 3u );
00281 surfaceFilter->SetParameter("Gaussian SD", 2.5f );
00282 surfaceFilter->SetParameter("Decimate mesh", true );
00283 surfaceFilter->SetParameter("Decimation rate", 0.80f );
00284 }
00285 else
00286 {
00287 surfaceFilter->SetParameter("Smooth", false );
00288 surfaceFilter->SetParameter("Apply median", false );
00289 surfaceFilter->SetParameter("Median kernel size", 3u );
00290 surfaceFilter->SetParameter("Gaussian SD", 1.5f );
00291 surfaceFilter->SetParameter("Decimate mesh", true );
00292 surfaceFilter->SetParameter("Decimation rate", 0.8f );
00293 }
00294
00295 mitk::ProgressBar::GetInstance()->AddStepsToDo(10);
00296 mitk::ProgressBar::GetInstance()->Progress(2);
00297 mitk::StatusBar::GetInstance()->DisplayText("Surface creation started in background...");
00298 surfaceFilter->StartAlgorithm();
00299 }
00300 catch(...)
00301 {
00302 MITK_ERROR << "surface creation filter had an error";
00303 }
00304 }
00305 else
00306 {
00307 MITK_INFO << " a NULL node selected";
00308 }
00309 }
00310 }
00311
00312 void QmitkSegmentationPostProcessing::OnSurfaceCalculationDone()
00313 {
00314 mitk::ProgressBar::GetInstance()->Progress(8);
00315 }
00316
00317
00318 void QmitkSegmentationPostProcessing::ImageStatistics(bool)
00319 {
00320 if (m_BlueBerryView)
00321 {
00322 m_BlueBerryView->GetSite()->GetWorkbenchWindow()->GetActivePage()->ShowView("org.mitk.views.imagestatistics");
00323 }
00324 }
00325
00326 void QmitkSegmentationPostProcessing::AutocropSelected(bool)
00327 {
00328 NodeList selection = this->GetSelectedNodes();
00329
00330 for ( NodeList::iterator iter = selection.begin(); iter != selection.end(); ++iter )
00331 {
00332 mitk::DataNode* node = *iter;
00333
00334 if (node)
00335 {
00336 mitk::Image::Pointer image = dynamic_cast<mitk::Image*>( node->GetData() );
00337 if (image.IsNull()) return;
00338
00339 mitk::ProgressBar::GetInstance()->AddStepsToDo(10);
00340 mitk::ProgressBar::GetInstance()->Progress(2);
00341
00342 qApp->processEvents();
00343
00344 mitk::AutoCropImageFilter::Pointer cropFilter = mitk::AutoCropImageFilter::New();
00345 cropFilter->SetInput( image );
00346 cropFilter->SetBackgroundValue( 0 );
00347 try
00348 {
00349 cropFilter->Update();
00350
00351 image = cropFilter->GetOutput();
00352
00353 if (image.IsNotNull())
00354 {
00355 node->SetData( this->IncreaseCroppedImageSize(image) );
00356 }
00357 }
00358 catch(...)
00359 {
00360 MITK_ERROR << "Cropping image failed...";
00361 }
00362 mitk::ProgressBar::GetInstance()->Progress(8);
00363 }
00364 else
00365 {
00366 MITK_INFO << " a NULL node selected";
00367 }
00368 }
00369 }
00370
00371 mitk::Image::Pointer QmitkSegmentationPostProcessing::IncreaseCroppedImageSize( mitk::Image::Pointer image )
00372 {
00373 typedef itk::Image< short, 3 > ImageType;
00374 typedef itk::Image< unsigned char, 3 > PADOutputImageType;
00375 ImageType::Pointer itkTransformImage = ImageType::New();
00376 mitk::CastToItkImage( image, itkTransformImage );
00377
00378 typedef itk::ConstantPadImageFilter< ImageType, PADOutputImageType > PadFilterType;
00379 PadFilterType::Pointer padFilter = PadFilterType::New();
00380
00381 unsigned long upperPad[3];
00382 unsigned long lowerPad[3];
00383 int borderLiner = 6;
00384
00385 mitk::Point3D mitkOriginPoint;
00386 double origin[3];
00387 origin[0]=0;
00388 origin[1]=0;
00389 origin[2]=0;
00390 itkTransformImage->SetOrigin(origin);
00391
00392 lowerPad[0]=borderLiner/2;
00393 lowerPad[1]=borderLiner/2;
00394 lowerPad[2]=borderLiner/2;
00395
00396 upperPad[0]=borderLiner/2;
00397 upperPad[1]=borderLiner/2;
00398 upperPad[2]=borderLiner/2;
00399
00400 padFilter->SetInput(itkTransformImage);
00401 padFilter->SetConstant(0);
00402 padFilter->SetPadUpperBound(upperPad);
00403 padFilter->SetPadLowerBound(lowerPad);
00404 padFilter->UpdateLargestPossibleRegion();
00405
00406
00407 mitk::Image::Pointer paddedImage = mitk::Image::New();
00408 mitk::CastToMitkImage(padFilter->GetOutput(), paddedImage);
00409
00410 paddedImage->SetGeometry(image->GetGeometry());
00411
00412
00413 mitk::Vector3D transVector = image->GetGeometry()->GetSpacing();
00414 transVector[0] = -(borderLiner/2);
00415 transVector[1] = -(borderLiner/2);
00416 transVector[2] = -(borderLiner/2);
00417
00418 mitk::Vector3D newTransVectorInmm = image->GetGeometry()->GetSpacing();
00419
00420 image->GetGeometry()->IndexToWorld(mitkOriginPoint, transVector, newTransVectorInmm);
00421 paddedImage->GetGeometry()->Translate(newTransVectorInmm);
00422
00423
00424 return paddedImage;
00425 }
00426