diff --git a/Documentation/Doxygen/Tutorial/Step09.dox b/Documentation/Doxygen/Tutorial/Step09.dox index 8033628aa3..f804f36bba 100644 --- a/Documentation/Doxygen/Tutorial/Step09.dox +++ b/Documentation/Doxygen/Tutorial/Step09.dox @@ -1,219 +1,219 @@ /** - + \page Step09Page MITK Tutorial - Step 9: A plug-in MITK uses a very modular concept to maximize reusability and portability. You start an application (for example mitkWorkbench, the sample application provided by MITK). An application has several bundles (or plug-ins). A bundle can be a functionality, which in turn can be a view, each of these terms specifying certain behaviour and attributes. The creation of a MITK plug-in is considerably facilitated by using the MITK BundleGenerator as described in \ref NewPluginPage . The mentioned tool was used to create a plug-in QmitkRegionGrowing. Let's first look at what files the BundleGenerator created: \verbatim documentation\doxygen\ modules.dox............................. Doxygen file for documenting your plug-in resources\ icon.xpm................................ The icon of your plug-in. GIMP or other programs (including your text editor) can be used to change this src\internal\ QmitkMITKRegionGrowingView.cpp.......... The most important file, implementing behaviour QmitkMITKRegionGrowingView.h............ Header file of the functionality QmitkMITKRegionGrowingViewControls.ui... XML file of the Qt Designer, describes buttons, combo boxes, etc. of your controls CMakeLists.txt \.......................... Build system related files for CMake files.cmake / manifest_headers.cmake.................... Information about your plug-in plugin.xml ............................... BlueBerry integration \endverbatim -If you are not familiar with Qt development, please look into +If you are not familiar with Qt development, please look into this Trolltech page describing .ui files (no, forget about the please, DO it!) The C++ files implement a subclass of QmitkAbstractView. In this special case of QmitkRegionGrowing, we added the ability to set some seed points and run a region grower. If you are interested in the concrete changes necessary to turn a freshly generated QmitkRegionGrowing into an integrated one: -Since an access to the StdMultiWidget is needed, manifest_headers.cmake has to be edited: +Since an access to the StdMultiWidget is needed, manifest_headers.cmake has to be edited: \verbatim set(Require-Plugin org.mitk.gui.qt.common org.mitk.gui.qt.stdmultiwidgeteditor) \endverbatim To add a PointSet for the seed points: QmitkRegionGrowingView.h Add includes: \verbatim #include "QmitkPointListWidget.h" #include "QmitkStdMultiWidget.h" #include "QmitkStdMultiWidgetEditor.h" \endverbatim Add the point set as protected object and add Pointers for a QmitkPointListWidget and a QmitkStdMultiWidget: \verbatim /// \brief This is the actual seed point data object mitk::PointSet::Pointer m_PointSet; QmitkPointListWidget* lstPoints; QmitkStdMultiWidget* m_MultiWidget; \endverbatim - + QmitkRegionGrowingView.cpp -CreateQtPartControl(): +CreateQtPartControl(): \verbatim // create a QmitkPointListWidget and add it to the widget created from .ui file lstPoints = new QmitkPointListWidget(); m_Controls.verticalLayout->addWidget(lstPoints); // get access to StdMultiWidget by using RenderWindowPart QmitkStdMultiWidgetEditor* qSMWE = dynamic_cast(GetRenderWindowPart()); m_MultiWidget = qSMWE->GetStdMultiWidget(); // let the point set widget know about the multi widget (crosshair updates) lstPoints->SetMultiWidget( m_MultiWidget ); - + // create a new DataTreeNode containing a PointSet with some interaction m_PointSet = mitk::PointSet::New(); mitk::DataNode::Pointer pointSetNode = mitk::DataNode::New(); pointSetNode->SetData( m_PointSet ); pointSetNode->SetName("seed points for region growing"); pointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true) ); pointSetNode->SetProperty("layer", mitk::IntProperty::New(1024) ); // add the pointset to the data tree (for rendering and access by other modules) GetDataStorage()->Add( pointSetNode ); // tell the GUI widget about out point set lstPoints->SetPointSetNode( pointSetNode ); \endverbatim To use the ITK region grower: QmitkRegionGrowingView.h Add protected method: \verbatim /*! \brief ITK image processing function This function is templated like an ITK image. The MITK-Macro AccessByItk determines the actual pixel type and dimensionality of a given MITK image and calls this function for further processing (in our case region growing) */ template < typename TPixel, unsigned int VImageDimension > void ItkImageProcessing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry ); \endverbatim QmitkRegionGrowingView.cpp Add includes: \verbatim // MITK #include "mitkImageAccessByItk.h" #include "mitkITKImageImport.h" #include "mitkProperties.h" #include "mitkColorProperty.h" // ITK #include \endverbatim DoImageProcessing(); \verbatim // So we have an image. Let's see if the user has set some seed points already if ( m_PointSet->GetSize() == 0 ) { // no points there. Not good for region growing - QMessageBox::information( NULL, "Region growing functionality", + QMessageBox::information( NULL, "Region growing functionality", "Please set some seed points inside the image first.\n" "(hold Shift key and click left mouse button inside the image.)" ); return; } // actually perform region growing. Here we have both an image and some seed points AccessByItk_1( image, ItkImageProcessing, image->GetGeometry() ); // some magic to call the correctly templated function \endverbatim And add the new method: \verbatim template < typename TPixel, unsigned int VImageDimension > void QmitkRegionGrowingView::ItkImageProcessing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry ) { typedef itk::Image< TPixel, VImageDimension > InputImageType; typedef typename InputImageType::IndexType IndexType; - + // instantiate an ITK region growing filter, set its parameters typedef itk::ConnectedThresholdImageFilter RegionGrowingFilterType; typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New(); regionGrower->SetInput( itkImage ); // don't forget this // determine a thresholding interval IndexType seedIndex; TPixel min( std::numeric_limits::max() ); TPixel max( std::numeric_limits::min() ); mitk::PointSet::PointsContainer* points = m_PointSet->GetPointSet()->GetPoints(); - for ( mitk::PointSet::PointsConstIterator pointsIterator = points->Begin(); + for ( mitk::PointSet::PointsConstIterator pointsIterator = points->Begin(); pointsIterator != points->End(); - ++pointsIterator ) + ++pointsIterator ) { // first test if this point is inside the image at all - if ( !imageGeometry->IsInside( pointsIterator.Value()) ) + if ( !imageGeometry->IsInside( pointsIterator.Value()) ) { continue; } // convert world coordinates to image indices imageGeometry->WorldToIndex( pointsIterator.Value(), seedIndex); // get the pixel value at this point TPixel currentPixelValue = itkImage->GetPixel( seedIndex ); // adjust minimum and maximum values if (currentPixelValue > max) max = currentPixelValue; if (currentPixelValue < min) min = currentPixelValue; regionGrower->AddSeed( seedIndex ); } - std::cout << "Values between " << min << " and " << max << std::endl; + MITK_INFO << "Values between " << min << " and " << max; min -= 30; max += 30; // set thresholds and execute filter regionGrower->SetLower( min ); regionGrower->SetUpper( max ); regionGrower->Update(); mitk::Image::Pointer resultImage = mitk::ImportItkImage( regionGrower->GetOutput() ); - mitk::DataTreeNode::Pointer newNode = mitk::DataTreeNode::New(); + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData( resultImage ); // set some properties newNode->SetProperty("binary", mitk::BoolProperty::New(true)); newNode->SetProperty("name", mitk::StringProperty::New("dumb segmentation")); newNode->SetProperty("color", mitk::ColorProperty::New(1.0,0.0,0.0)); newNode->SetProperty("volumerendering", mitk::BoolProperty::New(true)); newNode->SetProperty("layer", mitk::IntProperty::New(1)); newNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); // add result to data tree - this->GetDefaultDataStorage()->Add( newNode ); + this->GetDataStorage()->Add( newNode ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } \endverbatim Have fun using MITK! -If you meet any difficulties during your first steps, don't hesitate to ask on the MITK mailing list mitk-users@lists.sourceforge.net! +If you meet any difficulties during your first steps, don't hesitate to ask on the MITK mailing list mitk-users@lists.sourceforge.net! People there are kind and will try to help you. \ref Step08Page "[Previous step]" \ref Step10Page "[Next Step]" \ref TutorialPage "[Main tutorial page]" - + */