diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkProjectionFilter.txx b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkProjectionFilter.txx index 8014c09c24..deb59b26b4 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkProjectionFilter.txx +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkProjectionFilter.txx @@ -1,200 +1,202 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _itkProjectionFilter_txx #define _itkProjectionFilter_txx #include "itkProjectionFilter.h" #include "mitkProgressBar.h" #include #define SEARCHSIGMA 10 /* length in linear voxel dimensions */ #define MAXSEARCHLENGTH (3*SEARCHSIGMA) namespace itk { ProjectionFilter::ProjectionFilter() { } ProjectionFilter::~ProjectionFilter() { } void ProjectionFilter::Project() { // Contains only code for the projection of FA data. The original FSL code contains some extra lines // For projection of other measurements than FA mitk::ProgressBar::GetInstance()->AddStepsToDo( 3 ); Float4DImageType::Pointer data_4d_projected = Float4DImageType::New(); data_4d_projected->SetRegions(m_AllFA->GetRequestedRegion()); data_4d_projected->SetDirection(m_AllFA->GetDirection()); data_4d_projected->SetSpacing(m_AllFA->GetSpacing()); data_4d_projected->SetOrigin(m_AllFA->GetOrigin()); data_4d_projected->Allocate(); data_4d_projected->FillBuffer(0.0); Float4DImageType::SizeType size = m_AllFA->GetRequestedRegion().GetSize(); for(int t=0; tGetPixel(ix) != 0) { VectorImageType::PixelType dir = m_Directions->GetPixel(ix); short maxvalX=0, maxvalY=0, maxvalZ=0; Float4DImageType::IndexType ix4d; ix4d[0]=x; ix4d[1]=y; ix4d[2]=z; ix4d[3]=t; - float maxval = m_AllFA->GetPixel(ix4d), maxval_weighted = maxval, - exponentfactor = -0.5 * (dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2]) / (float)(SEARCHSIGMA*SEARCHSIGMA); + float maxval = m_AllFA->GetPixel(ix4d); + float maxval_weighted = maxval; + float exponentfactor = -0.5 * (dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2]) / (float)(SEARCHSIGMA*SEARCHSIGMA); // No tubular structure here if(m_Tube->GetPixel(ix) == 0) { for(int iters=0;iters<2;iters++) { float distance=0; for(int d=1;d=size[0] && dy<=size[1] && dz<=size[2]) { d=MAXSEARCHLENGTH; } else if(m_DistanceMap->GetPixel(ix3d)>=distance) { float distanceweight = exp(d * d * exponentfactor); distance = m_DistanceMap->GetPixel(ix3d); ix4d[0]=x+dir[0]*D; ix4d[1]=y+dir[1]*D; ix4d[2]=z+dir[2]*D; ix4d[3]=t; if(distanceweight*m_AllFA->GetPixel(ix4d)>maxval_weighted) { maxval = m_AllFA->GetPixel(ix4d); maxval_weighted = maxval*distanceweight; maxvalX = dir[0]*D; maxvalY = dir[1]*D; maxvalZ = dir[2]*D; } } else{ d=MAXSEARCHLENGTH; } } } } // Tubular structure else { for(int dy=-MAXSEARCHLENGTH; dy<=MAXSEARCHLENGTH;dy++) { for(int dx=-MAXSEARCHLENGTH; dx<=MAXSEARCHLENGTH; dx++) { float distanceweight = exp(-0.5 * (dx*dx+dy*dy) / (float)(SEARCHSIGMA*SEARCHSIGMA) ); float r=sqrt((float)(dx*dx+dy*dy)); if (r>0) { int allok=1; for(float rr=1; rr<=r+0.1; rr++) /* search outwards from centre to current voxel - test that distancemap always increasing */ { int dx1=round(rr*dx/r); int dy1=round(rr*dy/r); int dx2=round((rr+1)*dx/r); int dy2=round((rr+1)*dy/r); RealImageType::IndexType ix1, ix2; ix1[0]=x+dx1; ix1[1]=y+dy1; ix1[2]=z; ix2[0]=x+dx2; ix2[1]=y+dy2; ix2[2]=z; if(m_DistanceMap->GetPixel(ix1) > m_DistanceMap->GetPixel(ix2) ) { allok=0; } } ix4d[0]=x+dx; ix4d[1]=y+dy, ix4d[2]=z; ix4d[3]=t; if( allok && (distanceweight * m_AllFA->GetPixel(ix4d) > maxval_weighted) ) { maxval = m_AllFA->GetPixel(ix4d); maxval_weighted = maxval * distanceweight; maxvalX=dx; maxvalY=dy; maxvalZ=0; } } } } } ix4d[0]=x; ix4d[1]=y; ix4d[2]=z; ix4d[3]=t; + data_4d_projected->SetPixel(ix4d, maxval); } } } } } m_Projections = data_4d_projected; } } #endif // _itkProjectionFilter_txx diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTbssSkeletonizationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTbssSkeletonizationView.cpp index a7a9279e25..c6df504317 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTbssSkeletonizationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTbssSkeletonizationView.cpp @@ -1,499 +1,493 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Qmitk #include "QmitkTbssSkeletonizationView.h" #include #include #include #include #include // mitk #include // Qt #include #include //vtk #include #include // Boost #include const std::string QmitkTbssSkeletonizationView::VIEW_ID = "org.mitk.views.tbssskeletonization"; using namespace berry; QmitkTbssSkeletonizationView::QmitkTbssSkeletonizationView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) { } QmitkTbssSkeletonizationView::~QmitkTbssSkeletonizationView() { } void QmitkTbssSkeletonizationView::OnSelectionChanged(std::vector nodes) { //datamanager selection changed if (!this->IsActivated()) return; bool found3dImage = false; bool found4dImage = false; this->m_Controls->m_TubularName->setText(QString("Tubular Structure Mask: ")); this->m_Controls->m_TubularName->setEnabled(false); this->m_Controls->m_MeanLabel->setText(QString("Mean: ")); this->m_Controls->m_MeanLabel->setEnabled(false); this->m_Controls->m_PatientDataLabel->setText(QString("Patient Data: ")); this->m_Controls->m_PatientDataLabel->setEnabled(false); // iterate selection for ( int i=0; iGetData(); std::string name = ""; nodes[i]->GetStringProperty("name", name); if(nodeData) { if(QString("Image").compare(nodeData->GetNameOfClass())==0) { mitk::Image* img = static_cast(nodeData); if(img->GetDimension() == 3) { bool isBinary(false); nodes[i]->GetBoolProperty("binary", isBinary); if(isBinary) { QString label("Tubular Structure Mask: "); label.append(QString(name.c_str())); this->m_Controls->m_TubularName->setText(label); this->m_Controls->m_TubularName->setEnabled(true); } else { found3dImage = true; QString label("Mean: "); label.append(QString(name.c_str())); this->m_Controls->m_MeanLabel->setText(label); this->m_Controls->m_MeanLabel->setEnabled(true); } } else if(img->GetDimension() == 4) { found4dImage = true; QString label("Patient Data: "); label.append(QString(name.c_str())); this->m_Controls->m_PatientDataLabel->setText(label); this->m_Controls->m_PatientDataLabel->setEnabled(true); } } } } this->m_Controls->m_Skeletonize->setEnabled(found3dImage); this->m_Controls->m_Project->setEnabled(found3dImage && found4dImage); this->m_Controls->m_OutputMask->setEnabled(found3dImage && found4dImage); this->m_Controls->m_OutputDistanceMap->setEnabled(found3dImage && found4dImage); } void QmitkTbssSkeletonizationView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkTbssSkeletonizationViewControls; m_Controls->setupUi( parent ); this->CreateConnections(); } } void QmitkTbssSkeletonizationView::Activated() { QmitkFunctionality::Activated(); } void QmitkTbssSkeletonizationView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkTbssSkeletonizationView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_Skeletonize), SIGNAL(clicked()), this, SLOT(Skeletonize() )); connect( (QObject*)(m_Controls->m_Project), SIGNAL(clicked()), this, SLOT(Project() )); } } void QmitkTbssSkeletonizationView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkTbssSkeletonizationView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkTbssSkeletonizationView::Skeletonize() { typedef itk::SkeletonizationFilter SkeletonisationFilterType; SkeletonisationFilterType::Pointer skeletonizer = SkeletonisationFilterType::New(); std::vector nodes = this->GetDataManagerSelection(); mitk::Image::Pointer meanImage = mitk::Image::New(); std::string name = ""; for ( int i=0; iGetData(); if(nodeData) { if(QString("Image").compare(nodeData->GetNameOfClass())==0) { bool isBinary(false); nodes[i]->GetBoolProperty("binary", isBinary); mitk::Image* img = static_cast(nodeData); if(img->GetDimension() == 3 && !isBinary) { meanImage = img; name = nodes[i]->GetName(); } } } } // Calculate skeleton FloatImageType::Pointer itkImg = FloatImageType::New(); mitk::CastToItkImage(meanImage, itkImg); skeletonizer->SetInput(itkImg); skeletonizer->Update(); FloatImageType::Pointer output = skeletonizer->GetOutput(); mitk::Image::Pointer mitkOutput = mitk::Image::New(); mitk::CastToMitkImage(output, mitkOutput); name += "_skeleton"; AddToDataStorage(mitkOutput, name); } void QmitkTbssSkeletonizationView::Project() { typedef itk::SkeletonizationFilter SkeletonisationFilterType; typedef itk::ProjectionFilter ProjectionFilterType; typedef itk::DistanceMapFilter DistanceMapFilterType; SkeletonisationFilterType::Pointer skeletonizer = SkeletonisationFilterType::New(); std::vector nodes = this->GetDataManagerSelection(); mitk::Image::Pointer meanImage = mitk::Image::New(); mitk::Image::Pointer subjects = mitk::Image::New(); mitk::Image::Pointer tubular = mitk::Image::New(); for ( int i=0; iGetData(); if(nodeData) { if(QString("Image").compare(nodeData->GetNameOfClass())==0) { mitk::Image* img = static_cast(nodeData); if(img->GetDimension() == 3) { bool isBinary(false); nodes[i]->GetBoolProperty("binary", isBinary); if(isBinary) { tubular = img; } else { meanImage = img; } } else if(img->GetDimension() == 4) { subjects = img; } } } } Float4DImageType::Pointer allFA = ConvertToItk(subjects); - - - - // Calculate skeleton + // Calculate skeleton FloatImageType::Pointer itkImg = FloatImageType::New(); mitk::CastToItkImage(meanImage, itkImg); skeletonizer->SetInput(itkImg); skeletonizer->Update(); FloatImageType::Pointer output = skeletonizer->GetOutput(); mitk::Image::Pointer mitkOutput = mitk::Image::New(); mitk::CastToMitkImage(output, mitkOutput); AddToDataStorage(mitkOutput, "mean_FA_skeletonised"); // Retrieve direction image needed later by the projection filter DirectionImageType::Pointer directionImg = skeletonizer->GetVectorImage(); // Calculate distance image DistanceMapFilterType::Pointer distanceMapFilter = DistanceMapFilterType::New(); distanceMapFilter->SetInput(output); distanceMapFilter->Update(); FloatImageType::Pointer distanceMap = distanceMapFilter->GetOutput(); if(m_Controls->m_OutputDistanceMap->isChecked()) { mitk::Image::Pointer mitkDistance = mitk::Image::New(); mitk::CastToMitkImage(distanceMap, mitkDistance); AddToDataStorage(mitkDistance, "distance map"); } // Do projection // Ask a threshold to create a skeleton mask double threshold = -1.0; while(threshold == -1.0) { threshold = QInputDialog::getDouble(m_Controls->m_Skeletonize, tr("Specify the FA threshold"), tr("Threshold:"), QLineEdit::Normal, 0.2); if(threshold < 0.0 || threshold > 1.0) { QMessageBox msgBox; msgBox.setText("Please choose a value between 0 and 1"); msgBox.exec(); threshold = -1.0; } } typedef itk::BinaryThresholdImageFilter ThresholdFilterType; ThresholdFilterType::Pointer thresholder = ThresholdFilterType::New(); thresholder->SetInput(output); thresholder->SetLowerThreshold(threshold); thresholder->SetUpperThreshold(std::numeric_limits::max()); thresholder->SetOutsideValue(0); thresholder->SetInsideValue(1); thresholder->Update(); CharImageType::Pointer thresholdedImg = thresholder->GetOutput(); if(m_Controls->m_OutputMask->isChecked()) { mitk::Image::Pointer mitkThresholded = mitk::Image::New(); mitk::CastToMitkImage(thresholdedImg, mitkThresholded); std::string maskName = "skeleton_mask_at_" + boost::lexical_cast(threshold); AddToDataStorage(mitkThresholded, maskName); } CharImageType::Pointer itkTubular = CharImageType::New(); mitk::CastToItkImage(tubular, itkTubular); ProjectionFilterType::Pointer projectionFilter = ProjectionFilterType::New(); projectionFilter->SetDistanceMap(distanceMap); projectionFilter->SetDirections(directionImg); projectionFilter->SetAllFA(allFA); projectionFilter->SetTube(itkTubular); projectionFilter->SetSkeleton(thresholdedImg); projectionFilter->Project(); Float4DImageType::Pointer projected = projectionFilter->GetProjections(); mitk::Image::Pointer mitkProjections = mitk::Image::New(); mitk::CastToMitkImage(projected, mitkProjections); AddToDataStorage(mitkProjections, "all_FA_projected"); } void QmitkTbssSkeletonizationView::AddToDataStorage(mitk::Image* img, std::string name) { mitk::DataNode::Pointer result = mitk::DataNode::New(); result->SetProperty( "name", mitk::StringProperty::New(name) ); result->SetData( img ); // add new image to data storage and set as active to ease further processing GetDefaultDataStorage()->Add( result ); } Float4DImageType::Pointer QmitkTbssSkeletonizationView::ConvertToItk(mitk::Image::Pointer image) { Float4DImageType::Pointer output = Float4DImageType::New(); mitk::Geometry3D* geo = image->GetGeometry(); mitk::Vector3D mitkSpacing = geo->GetSpacing(); mitk::Point3D mitkOrigin = geo->GetOrigin(); Float4DImageType::SpacingType spacing; spacing[0] = mitkSpacing[0]; spacing[1] = mitkSpacing[1]; spacing[2] = mitkSpacing[2]; spacing[3] = 1.0; // todo: check if spacing has length 4 Float4DImageType::PointType origin; origin[0] = mitkOrigin[0]; origin[1] = mitkOrigin[1]; origin[2] = mitkOrigin[2]; origin[3] = 0; Float4DImageType::SizeType size; size[0] = image->GetDimension(0); size[1] = image->GetDimension(1); size[2] = image->GetDimension(2); size[3] = image->GetDimension(3); Float4DImageType::DirectionType dir; vtkLinearTransform* lin = geo->GetVtkTransform(); vtkMatrix4x4 *m = lin->GetMatrix(); dir.Fill(0.0); for(int x=0; x<3; x++) { for(int y=0; y<3; y++) { dir[x][y] = m->GetElement(x,y); } } dir[3][3] = 1; output->SetSpacing(spacing); output->SetOrigin(origin); output->SetRegions(size); output->SetDirection(dir); output->Allocate(); if(image->GetDimension() == 4) { int timesteps = image->GetDimension(3); try{ // REPLACE THIS METHODE()ConvertToItk) WITH mitk::CastToItk - mitk::ImagePixelReadAccessor imageAccessor(image, image->GetSliceData()); // iterate through the subjects and copy data to output for(int t=0; tGetDimension(0); x++) { for(int y=0; yGetDimension(1); y++) { for(int z=0; zGetDimension(2); z++) { - itk::Index<4> ix4; - ix4[0] = x; - ix4[1] = y; - ix4[2] = z; - ix4[3] = t; + itk::Index<3> ix = {x, y, z}; + itk::Index<4> ix4 = {x, y, z, t}; - output->SetPixel(ix4, imageAccessor.GetPixelByIndex(ix4)); + output->SetPixel(ix4, image->GetPixelValueByIndex(ix, t)); } } } } - }catch(std::exception & e) + } + catch(std::exception & e) { MITK_INFO << e.what(); } } return output; }