diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.cpp b/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.cpp new file mode 100644 index 0000000000..0ea7a6fd49 --- /dev/null +++ b/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.cpp @@ -0,0 +1,179 @@ +/*=================================================================== + +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. + +===================================================================*/ + +//#include + +//Itk Iterators +#include +#include + +//Set Functions +template +void mitk::CostFunctionBase::SetRegion(std::pair regionPair) +{ + m_RegionPair = regionPair; +} + +template +void mitk::CostFunctionBase::SetImage(itk::Image * image) +{ + m_Image = image; +} + +//Other Functions +template < typename TPixel, unsigned int VImageDimension > +int mitk::CostFunctionBase::RegionIsFullEnough () +{ + //Calculate the volume of the region cuboid + itk::Size<3> size = m_RegionPair.first.GetSize(); + double volume = size[0] * size[1] * size[2]; + + typedef itk::Image< int, VImageDimension > IntegerImageType; + itk::ImageRegionIterator it_region(m_Image, m_RegionPair.first); + + double voxelsWithRegionValue(1); //Because the possible new voxel hasn't been set to the region value yet + double voxelsWithValueZero(0); + + for(it_region.GoToBegin(); !it_region.IsAtEnd(); ++it_region) + { + if (it_region.Value() == m_RegionPair.second) + { + voxelsWithRegionValue++; + } + if (it_region.Value() == 0) + { + voxelsWithValueZero++; + } + } + + double measurement = voxelsWithRegionValue / (volume - voxelsWithValueZero); + + if (measurement > 0.3) + { + return 1; + } + return 0; +} + +template < typename TPixel, unsigned int VImageDimension > +int mitk::CostFunctionBase::SidesAreNotTooLong () +{ + itk::Size<3> size = m_RegionPair.first.GetSize(); + + if (size[0] < size[1] + size[2] + 1 && size[1] < size[0] + size[2] + 1 && size[2] < size[0] + size[1] + 1) + { + return 1; + } + return 0; +} + +template < typename TPixel, unsigned int VImageDimension > +int mitk::CostFunctionBase::COMLiesWithinParcel() +{ + std::pair chosenRegion = m_RegionPair; + + typedef itk::Image< int, VImageDimension > IntegerImageType; + itk::ImageRegionIterator it_region(m_Image, chosenRegion.first); + std::vector centerOfMass; + centerOfMass = this->GetCenterOfMass(); + typename IntegerImageType::IndexType indexCenterOfMass; + indexCenterOfMass.SetElement(0, centerOfMass[0] + 0.5); + indexCenterOfMass.SetElement(1, centerOfMass[1] + 0.5); + indexCenterOfMass.SetElement(2, centerOfMass[2] + 0.5); + it_region.SetIndex(indexCenterOfMass); + int value = it_region.Value(); + + if (it_region.Value() == chosenRegion.second || it_region.Value() == 0) + { + return 1; + } + return 0; +} + +template < typename TPixel, unsigned int VImageDimension > +int mitk::CostFunctionBase::CalculateCost() +{ + int costFunctionValue(0); + std::vector costVector; + costVector.push_back(this->RegionIsFullEnough()); + costVector.push_back(this->SidesAreNotTooLong()); + costVector.push_back(this->COMLiesWithinParcel()); + + m_weight.clear(); + m_weight.push_back(1); //weight for RegionIsFullEnough + m_weight.push_back(1); //weight for SidesAreNotTooLong + m_weight.push_back(0); //weight for COMLiesWithinParcel + + //Vector multiplication + for (int i = 0; i < costVector.size(); i++) + { + costFunctionValue += costVector[i]*m_weight[i]; + } + + return costFunctionValue; +} + +template +std::vector mitk::CostFunctionBase::GetCenterOfMass() +{ + //Count all tagged voxels in this region + itk::ImageRegionIterator it_region(m_Image, m_RegionPair.first); + + typedef itk::Image< TPixel, VImageDimension > ImageType; + int currentSizeOfRegion (0); + std::vector indexVoxel; + std::vector centerOfMass; + double xValue(0); + double yValue(0); + double zValue(0); + + for (it_region.GoToBegin(); !it_region.IsAtEnd(); ++it_region) + { + if(it_region.Value() == m_RegionPair.second) + { + indexVoxel.push_back(it_region.GetIndex()); + currentSizeOfRegion++; + } + } + + xValue = 0; + yValue = 0; + zValue = 0; + + for (int i = 0; i < currentSizeOfRegion; i++) + { + xValue += indexVoxel[i][0]; + yValue += indexVoxel[i][1]; + zValue += indexVoxel[i][2]; + } + + centerOfMass.push_back(xValue/currentSizeOfRegion); + centerOfMass.push_back(yValue/currentSizeOfRegion); + centerOfMass.push_back(zValue/currentSizeOfRegion); + + return centerOfMass; +} + +template +int mitk::CostFunctionBase::MaximalValue() +{ + int maximalValue(0); + for (int i = 0; i < m_weight.size(); i++) + { + maximalValue += m_weight[i]; + } + return maximalValue; +} diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.h b/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.h new file mode 100644 index 0000000000..2be9b702fd --- /dev/null +++ b/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.h @@ -0,0 +1,73 @@ +/*=================================================================== + +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 mitkCostFunctionBase_h +#define mitkCostFunctionBase_h + +//Which one do we really need? +//#include +#include + +#include +#include "mitkCommon.h" +#include "MitkConnectomicsExports.h" + +//To use pair +#include + +namespace mitk +{ + template + class CostFunctionBase + { + public: + typedef itk::ImageRegion<3> RegionType; + typedef itk::Image< TPixel, VImageDimension > ImageType; + //Set Functions + void SetImage(itk::Image *); + void SetRegion(std::pair); + //Main Function + /** \brief Checks if the functions RegionIsFullEnough, SidesAreNotTooLong and COMLiesWithinParcel all return value 1*/ + int CalculateCost(); + /** \brief Calculates the maximal possible value of the cost function*/ + int MaximalValue(); + + private: + ImageType * m_Image; + std::pair m_RegionPair; + //Functions to calculate cost + /** \brief Checks if the parcel fills out the region it lies within quit well + * This is to get a convex structure. + */ + int RegionIsFullEnough (); + /** \brief Checks if the length of one direction is much longer than the length of the other two directions + * So we don't get parcels which just grow in one direction and look like a line. + */ + int SidesAreNotTooLong (); + /** \brief Checks if the center of mass of a parcel lies within the parcel + * This is to avoid U-shaped parcels. + */ + int COMLiesWithinParcel(); + /** \brief Gives back the center of mass of a parcel as a vector*/ + std::vector GetCenterOfMass(); + + std::vector m_weight; + }; +} + +#include "mitkCostFunctionBase.cpp" + +#endif /* mitkCostFunctionBase_h */ \ No newline at end of file diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.cpp b/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.cpp new file mode 100644 index 0000000000..d60fa8bec0 --- /dev/null +++ b/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.cpp @@ -0,0 +1,1189 @@ +/*=================================================================== + +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. + +===================================================================*/ + +//#include + +//To sort +#include + +//To use sqrt +#include + +//Itk Iterators +#include +#include + +//for the use of abs() +#include + +//Better Random Function xrand (extended range) +#define XRAND_MAX (RAND_MAX*(RAND_MAX + 2)) +unsigned int xrand (void) +{ + return rand () * (RAND_MAX + 1) + rand (); +} + +//Definition of the Set-Functions +template +void mitk::RandomParcellationGenerator::SetImage(itk::Image * image) +{ + m_Image = image; +} + +template +void mitk::RandomParcellationGenerator::SetNumberNodes(int numberNodes) +{ + m_NumberNodes = numberNodes; +} + +template +void mitk::RandomParcellationGenerator::SetVariablesForMerging (int givenSizeOfSmallestRegion, int desiredNumberOfParcels, int givenSizeOfSmallestRegionBeginning) +{ + m_GivenSizeOfSmallestRegion = givenSizeOfSmallestRegion; + m_DesiredNumberOfParcels = desiredNumberOfParcels; + m_GivenSizeOfSmallestRegionBeginning = givenSizeOfSmallestRegionBeginning; +} + +template +void mitk::RandomParcellationGenerator::SetBoolsForMerging(bool mergingWithNumberParcels, bool mergingWithSmallestParcel, bool justMergeSmallParcels) +{ + m_MergingWithNumberParcels = mergingWithNumberParcels; + m_MergingWithSmallestParcel = mergingWithSmallestParcel; + m_JustMergeSmallParcels = justMergeSmallParcels; +} + +//Definition of other functions + +//Calculates the Center of mass (COM) and m_SizeOfRegions +template +std::vector mitk::RandomParcellationGenerator::GetCenterOfMass( itk::ImageRegionIterator it_region, int valueOfRegion, bool getSizeOfRegions) +{ + //Counts all tagged voxels in this region + + typedef itk::Image< TPixel, VImageDimension > ImageType; + int currentSizeOfRegion (0); + std::vector indexVoxel; + std::vector centerOfMass; + double xValue(0); + double yValue(0); + double zValue(0); + + for (it_region.GoToBegin(); !it_region.IsAtEnd(); ++it_region) + { + if(it_region.Value() == valueOfRegion) + { + indexVoxel.push_back(it_region.GetIndex()); + currentSizeOfRegion++; + } + } + + if (getSizeOfRegions == true) + { + m_SizeOfRegions.push_back(currentSizeOfRegion); + } + + xValue = 0; + yValue = 0; + zValue = 0; + + for (int i = 0; i < currentSizeOfRegion; i++) + { + xValue += indexVoxel[i][0]; + yValue += indexVoxel[i][1]; + zValue += indexVoxel[i][2]; + } + + centerOfMass.push_back(xValue/currentSizeOfRegion); + centerOfMass.push_back(yValue/currentSizeOfRegion); + centerOfMass.push_back(zValue/currentSizeOfRegion); + + return centerOfMass; +} + +template +double mitk::RandomParcellationGenerator::GetDistance( std::vector centerOfMass, typename itk::Image< TPixel, VImageDimension >::IndexType indexNewVoxel) +{ + double distancetemp(0); + + for (int i = 0; i < 3; i++) + { + distancetemp += (centerOfMass[i] - indexNewVoxel[i])*(centerOfMass[i] - indexNewVoxel[i]); + } + return sqrt(distancetemp); +} + +template +double mitk::RandomParcellationGenerator::GetDistanceVector( std::vector centerOfMass, std::vector indexNewVoxel) +{ + double distancetemp(0); + + for (int i = 0; i < 3; i++) + { + distancetemp += (centerOfMass[i] - indexNewVoxel[i])*(centerOfMass[i] - indexNewVoxel[i]); + } + return sqrt(distancetemp); +} + + +template < typename TPixel, unsigned int VImageDimension > +int mitk::RandomParcellationGenerator::SmallestValue (std::vector distance) +{ + int distancemin; + distancemin = distance[0]; + + for (int i = 1; i < distance.size(); i++) + { + if (distance[i] < distancemin) + { + distancemin = distance[i]; + } + } + return distancemin; +} + +template < typename TPixel, unsigned int VImageDimension > +double mitk::RandomParcellationGenerator::SmallestValue (std::vector distance) +{ + double distancemin; + distancemin = distance[0]; + + for (int i = 1; i < distance.size(); i++) + { + if (distance[i] < distancemin) + { + distancemin = distance[i]; + } + } + return distancemin; +} + +template < typename TPixel, unsigned int VImageDimension > +void mitk::RandomParcellationGenerator::SetAppropriateValues() +{ + typedef itk::Image< TPixel, VImageDimension > TemplateImageType; + + itk::ImageRegionIterator it_image(m_Image, m_Image->GetLargestPossibleRegion()); + + TPixel minimumValue, maximumValue; + + it_image.GoToBegin(); + maximumValue = minimumValue = it_image.Value(); + + for(it_image.GoToBegin(); !it_image.IsAtEnd(); ++it_image) + { + if ( it_image.Value() < minimumValue ) + { + minimumValue = it_image.Value(); + } + else + { + if ( it_image.Value() > maximumValue ) + { + maximumValue = it_image.Value(); + } + } + } + + int range = int ( maximumValue - minimumValue ); //needs to be castable to int + int offset = int ( minimumValue ); + + if ( range < 0 ) //error + { + return; + } + + std::vector< unsigned int > histogram; + histogram.resize( range + 1, 0 ); + + for(it_image.GoToBegin(); !it_image.IsAtEnd(); ++it_image) + { + histogram[ int ( it_image.Value() ) - offset ] += 1; + } + + int gapCounter = 0; //this variable will be used to count the empty labels + + //stores how much has to be subtracted from the image to remove gaps + std::vector< TPixel > subtractionStorage; + subtractionStorage.resize( range + 1, 0 ); + + for( int index = 0; index <= range; index++ ) + { + if( histogram[ index ] == 0 ) + { + gapCounter++; //if the label is empty, increase gapCounter + } + else + { + subtractionStorage[ index ] = TPixel ( gapCounter ); + } + } + + //remove gaps from label image + for(it_image.GoToBegin(); !it_image.IsAtEnd(); ++it_image) + { + it_image.Value() = it_image.Value() - subtractionStorage[ int ( it_image.Value() ) ]; + } +} + + + +template < typename TPixel, unsigned int VImageDimension > +typename itk::Image< TPixel, VImageDimension >::RegionType mitk::RandomParcellationGenerator::ExtendedRegion(typename itk::Image< TPixel, VImageDimension >::RegionType chosenRegion, typename ImageType::IndexType indexChosenVoxel) +{ + itk::Size<3> size = chosenRegion.GetSize(); + itk::Index<3> start = chosenRegion.GetIndex(); + std::vector greatestValues; + std::vector smallestValues; + + for(int i = 0; i < 3; i++) + { + greatestValues.push_back(start[i] + size[i]); + smallestValues.push_back(start[i]); + } + + for(int i = 0; i < 3; i++) + { + if (indexChosenVoxel[i] == greatestValues[i]) + { + size[i] += 1; + } + if (indexChosenVoxel[i] == smallestValues[i] - 1) + { + start[i] -= 1; + size[i] += 1; + } + } + + chosenRegion.SetSize(size); + chosenRegion.SetIndex(start); + + return chosenRegion; +} + +template < typename TPixel, unsigned int VImageDimension > +typename itk::Image< TPixel, VImageDimension >::RegionType mitk::RandomParcellationGenerator::ExtendedRegionNotNeighbor(typename itk::Image< TPixel, VImageDimension >::RegionType chosenRegion, typename itk::Image< TPixel, VImageDimension >::RegionType smallestRegion) +{ + itk::Size<3> sizeChosenRegion = chosenRegion.GetSize(); + itk::Index<3> startChosenRegion = chosenRegion.GetIndex(); + itk::Size<3> sizeSmallestRegion = smallestRegion.GetSize(); + itk::Index<3> startSmallestRegion = smallestRegion.GetIndex(); + + //size and start of the new merged region + itk::Size<3> size; + itk::Index<3> start; + + //Calculate the size of the merged region + for (int i = 0; i < 3; i++) + { + //Overlapping (start of ChosenRegion before start of SmallestRegion) + if ((startChosenRegion[i] + sizeChosenRegion[i] > startSmallestRegion[i]) && + (startChosenRegion[i] <= startSmallestRegion[i])) + { + //Not integrated + if (startSmallestRegion[i] + sizeSmallestRegion[i] > startChosenRegion[i] + sizeChosenRegion[i]) + { + size[i] = abs(startSmallestRegion[i] - startChosenRegion[i]) + sizeSmallestRegion[i]; + } + //Integrated + else + { + size[i] = std::max(sizeChosenRegion[i], sizeSmallestRegion[i]); + } + } + + //Overlapping (start of SmallestRegion before start of ChosenRegion) + if ((startSmallestRegion[i] + sizeSmallestRegion[i] > startChosenRegion[i]) && + (startChosenRegion[i] >= startSmallestRegion[i])) + { + //Not integrated + if (startChosenRegion[i] + sizeChosenRegion[i] > startSmallestRegion[i] + sizeSmallestRegion[i]) + { + size[i] = abs(startSmallestRegion[i] - startChosenRegion[i]) + sizeChosenRegion[i]; + } + //Integrated + else + { + size[i] = std::max(sizeChosenRegion[i], sizeSmallestRegion[i]); + } + } + + //No overlapping (right next to each other) + if ((startChosenRegion[i] + sizeChosenRegion[i] == startSmallestRegion[i]) || + (startSmallestRegion[i] + sizeSmallestRegion[i] == startChosenRegion[i])) + { + size[i] = sizeChosenRegion[i] + sizeSmallestRegion[i]; + } + + //Isolated + if ((startChosenRegion[i] + sizeChosenRegion[i] < startSmallestRegion[i]) || + (startSmallestRegion[i] + sizeSmallestRegion[i] < startChosenRegion[i])) + { + if(startChosenRegion[i] + sizeChosenRegion[i] < startSmallestRegion[i]) + { + size[i] = abs(startChosenRegion[i] - startSmallestRegion[i]) +1; + } + if(startSmallestRegion[i] + sizeSmallestRegion[i] < startChosenRegion[i]) + { + size[i] = abs(startChosenRegion[i] - startSmallestRegion[i]) + sizeChosenRegion[i]; + } + } + } + + //Calculate the start point of the new region, choose the smallest value respectively + for (int i = 0; i < 3; i++) + { + start[i] = std::min(startChosenRegion[i], startSmallestRegion[i]); + } + + chosenRegion.SetSize(size); + chosenRegion.SetIndex(start); + + return chosenRegion; +} + +//checks if a number is already an element of the vector +template < typename TPixel, unsigned int VImageDimension > +bool mitk::RandomParcellationGenerator::IsUnique (int number, std::vector vec) +{ + for (int i = 0; i < vec.size(); i++) + { + if (vec[i] == number) + { + return false; + } + } + return true; +} + +template < typename TPixel, unsigned int VImageDimension > +void mitk::RandomParcellationGenerator::GetRandomSeedVoxels() +{ + typedef itk::Image< TPixel, VImageDimension > ImageType; + + RegionVoxelCounter counter; + counter.SetImage(m_Image); + counter.SetRegion(m_Image->GetLargestPossibleRegion()); + + int numberVoxels = counter.VoxelWithValue(1); + + //Create vector with unique numbers + + std::vector randomvector; + int randomnumber; + + //for-loop to get (m_NumberNodes) randomly chosen seed-points + for (int j = 0; j < m_NumberNodes; j++) + { + //xrand() is the same as rand() but with an extended range + randomnumber = xrand() % numberVoxels +1; + + //Bool-function (IsUnique) + if (this->IsUnique(randomnumber, randomvector)) + { + randomvector.push_back(randomnumber); + } + else + { + j--; + } + } + + //sorts the numbers in randomvector according to their size + sort (randomvector.begin(), randomvector.end()); + + //assign new values to the chosen voxels and build the regions + + itk::Size<3> originalSize; + originalSize.Fill(1); + itk::Index<3> originalStart; + typename ImageType::IndexType currentIndex; + + int valueCounter(0); + int regionNumber(0); + typename ImageType::RegionType tempRegion; + itk::ImageRegionIterator it_image(m_Image, m_Image->GetLargestPossibleRegion()); + + + for (it_image.GoToBegin(); !it_image.IsAtEnd(), regionNumber < m_NumberNodes; ++it_image) + { + if (it_image.Value() >= 1) + { + valueCounter++; + if (valueCounter == randomvector[regionNumber]) + { + it_image.Value() = regionNumber+3; + + //Build the Regions + currentIndex = it_image.GetIndex(); + originalStart[0] = currentIndex[0]; + originalStart[1] = currentIndex[1]; + originalStart[2] = currentIndex[2]; + + tempRegion.SetSize(originalSize); + tempRegion.SetIndex(originalStart); + std::pair tempPair (tempRegion, regionNumber+3); + m_OddRegions.push_back(tempPair); + regionNumber++; + } + } + } +} + +template < typename TPixel, unsigned int VImageDimension > +void mitk::RandomParcellationGenerator::ParcelGrowthOverFaces() +{ + typedef itk::Image< int, VImageDimension > IntegerImageType; + typedef itk::NeighborhoodIterator< IntegerImageType > NeighborhoodIteratorType; + typename NeighborhoodIteratorType::RadiusType radius; + radius.Fill(1); + + std::pair chosenRegion; + int thisRegion; + typename IntegerImageType::IndexType indexChosenVoxel; + std::vector distance; + std::vector possibleNeighbor; + int thisNeighbor; + std::vector centerOfMass; + typename IntegerImageType::IndexType indexNewVoxel; + std::vector indexNewVoxelVector; + int numberAvailableVoxels(0); + bool validVoxelNotYetFound; + bool checkRegionsOfOddSize(true); + std::vector > * possibleRegions; + int costValue; + + + //As long as there are still non invalid regions (of even or odd size) add a voxel to them in each iteration step + while(m_OddRegions.size() != 0 || m_EvenRegions.size() != 0) + { + //When we change from odd to even or vice versa + if (m_OddRegions.size() == 0) + { + checkRegionsOfOddSize = false; + possibleRegions = &m_EvenRegions; + } + + if (m_EvenRegions.size() == 0) + { + checkRegionsOfOddSize = true; + possibleRegions = &m_OddRegions; + } + + //All our smallest regions are contained in possibleRegions, choose one randomly and check whether we can expand it + + thisRegion = xrand() % possibleRegions->size(); + chosenRegion = (*possibleRegions)[thisRegion]; + + //Calculate Center of mass (COM) + centerOfMass.clear(); + itk::ImageRegionIterator it_region(m_Image, chosenRegion.first); + centerOfMass = this->GetCenterOfMass(it_region, chosenRegion.second, false); + + numberAvailableVoxels = 0; + NeighborhoodIteratorType it_neighborhood(radius, m_Image, chosenRegion.first); + + //Check if there are any valid voxels which we can add to our chosen region + + for (it_neighborhood.GoToBegin(); !it_neighborhood.IsAtEnd(); ++it_neighborhood) + { + if (it_neighborhood.GetCenterPixel() == chosenRegion.second) + { + //Now the Neighborhood of a Parcel-Voxel is available + //Check if there is a valid voxel + + for (int k = 0; k <27; k++) + { + if (it_neighborhood.GetPixel(k) == 1 && (k == 4 || k == 10 || k == 12 || k == 14 || k == 16 || k == 22) ) + { + // Calculate the distance btw. the centerOfMass and the NewVoxel + indexNewVoxel = it_neighborhood.GetIndex(k); + indexNewVoxelVector.push_back(indexNewVoxel); + + distance.push_back(this->GetDistance(centerOfMass, indexNewVoxel)); + + numberAvailableVoxels++; + } + } + } + } + + if (numberAvailableVoxels > 0) + { + validVoxelNotYetFound = true; + while (validVoxelNotYetFound && distance.size() > 0) + { + possibleNeighbor.clear(); + //Find the possible neighbors with the smallest distance to the COM of the region + + for (int i = 0; i < distance.size(); i++) + { + if (distance[i] == this->SmallestValue(distance)) + { + possibleNeighbor.push_back(i); + } + } + + //Choose a random voxel and check if it is valid + //Get the index of this voxel + thisNeighbor = xrand() % possibleNeighbor.size(); + indexChosenVoxel = indexNewVoxelVector[possibleNeighbor[thisNeighbor]]; + + //Check if we now have to expand the region due to the possible new voxel + std::pair chosenRegionChanged; + chosenRegionChanged.first = this->ExtendedRegion(chosenRegion.first, indexChosenVoxel); + chosenRegionChanged.second = chosenRegion.second; + + //Constraints + + CostFunctionBase costCalculator; + costCalculator.SetImage(m_Image); + costCalculator.SetRegion(chosenRegionChanged); + costValue = costCalculator.CalculateCost(); + + + if(costValue >= costCalculator.MaximalValue())//Constraints are fulfilled + { + validVoxelNotYetFound = false; + chosenRegion = chosenRegionChanged; + } + else //Constraints are not fulfilled + { + validVoxelNotYetFound = true; //So we are still in the while loop + distance.erase(distance.begin() + possibleNeighbor[thisNeighbor]); + indexNewVoxelVector.erase(indexNewVoxelVector.begin() + possibleNeighbor[thisNeighbor]); + + if (distance.size() == 0) + { + if (checkRegionsOfOddSize == true) + { + m_InvalidRegions.push_back(chosenRegion); + m_OddRegions.erase(m_OddRegions.begin() + thisRegion); + } + else + { + m_InvalidRegions.push_back(chosenRegion); + m_EvenRegions.erase(m_EvenRegions.begin() + thisRegion); + } + } + } + } + + + if (distance.size() > 0) + { + //Change the value of the new voxel + itk::ImageRegionIterator it_region(m_Image, m_Image->GetLargestPossibleRegion()); + it_region.SetIndex(indexChosenVoxel); + it_region.Value() = chosenRegion.second; + + //Change from even to odd or vice versa + if (checkRegionsOfOddSize == true) + { + m_EvenRegions.push_back(chosenRegion); + m_OddRegions.erase(m_OddRegions.begin() + thisRegion); + } + else + { + m_OddRegions.push_back(chosenRegion); + m_EvenRegions.erase(m_EvenRegions.begin() + thisRegion); + } + + distance.clear(); + indexNewVoxelVector.clear(); + } + } + else + { + //The region can't be extended, put it into the m_InvalidRegions vector + m_InvalidRegions.push_back((*possibleRegions)[thisRegion]); + possibleRegions->erase(possibleRegions->begin() + thisRegion); + } + } +} + +template < typename TPixel, unsigned int VImageDimension > +void mitk::RandomParcellationGenerator::FillOverEdgeOrVertex() +{ + typedef itk::Image< int, VImageDimension > IntegerImageType; + typedef itk::NeighborhoodIterator< IntegerImageType > NeighborhoodIteratorType; + typename NeighborhoodIteratorType::RadiusType radius; + radius.Fill(1); + NeighborhoodIteratorType it_neighborhood(radius, m_Image, m_Image->GetLargestPossibleRegion()); + + std::vector valueOfRegions; + std::vector sizeOfPossibleRegions; + std::vector valueOfPossibleRegions; + std::vector indexInvalidRegions; + std::vector indexOfPossibleInvalidRegions; + std::vector distance; + std::vector possibleNeighbor; + typename IntegerImageType::IndexType indexNewVoxel; + std::vector centerOfMass; + int thisNeighbor; + std::pair chosenRegion; + typename IntegerImageType::IndexType indexChosenVoxel; + + RegionVoxelCounter wholeImageCounter; + wholeImageCounter.SetImage(m_Image); + wholeImageCounter.SetRegion(m_Image->GetLargestPossibleRegion()); + int voxelsWithValueOne = wholeImageCounter.VoxelWithValue(1); + + if (voxelsWithValueOne > 0) + { + std::stringstream message; + message << "Edge " << voxelsWithValueOne << endl; + MITK_DEBUG << message.str(); + for (it_neighborhood.GoToBegin(); !it_neighborhood.IsAtEnd(); ++it_neighborhood) + { + if (it_neighborhood.GetCenterPixel() == 1) //Found Voxel with Value 1 + { + m_SizeOfRegions.clear(); + distance.clear(); + valueOfRegions.clear(); + possibleNeighbor.clear(); + indexInvalidRegions.clear(); + indexOfPossibleInvalidRegions.clear(); + indexNewVoxel = it_neighborhood.GetIndex(); + + //Add this voxel to a region + //first check if it shares an edge or vertex with (at least) one region + for (int k = 0; k <27; k++) + { + if (it_neighborhood.GetPixel(k) > 2) + { + for (int i = 0; i < m_InvalidRegions.size(); i++) + { + if (it_neighborhood.GetPixel(k) == m_InvalidRegions[i].second) + { + valueOfRegions.push_back(m_InvalidRegions[i].second); + itk::ImageRegionIterator it_region(m_Image, m_InvalidRegions[i].first); + + //Gets center of mass and the m_SizeOfRegions + centerOfMass = this->GetCenterOfMass(it_region, m_InvalidRegions[i].second, true); + distance.push_back(this->GetDistance(centerOfMass, indexNewVoxel)); + indexInvalidRegions.push_back(i); + break; + } + } + } + } + //Minimal distance + if (distance.size() != 0) + { + for (int i = 0; i < distance.size(); i++) + { + if (distance[i] == this->SmallestValue(distance)) + { + possibleNeighbor.push_back(i); + } + } + distance.clear(); + + //Check the Size of the Regions and get the smallest one! + //First get the regions with the same distance to COM + for (int i = 0; i < possibleNeighbor.size(); i++) + { + sizeOfPossibleRegions.push_back(m_SizeOfRegions[possibleNeighbor[i]]); + valueOfPossibleRegions.push_back(valueOfRegions[possibleNeighbor[i]]); + indexOfPossibleInvalidRegions.push_back(indexInvalidRegions[possibleNeighbor[i]]); + } + possibleNeighbor.clear(); + indexInvalidRegions.clear(); + + for (int i = 0; i < sizeOfPossibleRegions.size(); i++) + { + if (sizeOfPossibleRegions[i] == this->SmallestValue(sizeOfPossibleRegions)) + { + possibleNeighbor.push_back(i); + } + } + sizeOfPossibleRegions.clear(); + + thisNeighbor = xrand() % possibleNeighbor.size(); + + it_neighborhood.SetCenterPixel(valueOfPossibleRegions[thisNeighbor]); + valueOfPossibleRegions.clear(); + + //region extansion if necessary + //first we need to get the right region + chosenRegion = m_InvalidRegions[indexOfPossibleInvalidRegions[thisNeighbor]]; + indexChosenVoxel = it_neighborhood.GetIndex(); + + m_InvalidRegions[indexOfPossibleInvalidRegions[thisNeighbor]].first = this->ExtendedRegion(chosenRegion.first, indexChosenVoxel); + + indexOfPossibleInvalidRegions.clear(); + + } + } + } + } +} + +template < typename TPixel, unsigned int VImageDimension > +void mitk::RandomParcellationGenerator::AllocateIsolatedVoxels() +{ + typedef itk::Image< int, VImageDimension > IntegerImageType; + + std::vector valueOfRegions; + std::vector sizeOfPossibleRegions; + std::vector valueOfPossibleRegions; + std::vector indexInvalidRegions; + std::vector indexOfPossibleInvalidRegions; + std::vector distance; + std::vector possibleNeighbor; + typename IntegerImageType::IndexType indexNewVoxel; + std::vector centerOfMass; + int thisNeighbor; + std::pair chosenRegion; + typename IntegerImageType::IndexType indexChosenVoxel; + + RegionVoxelCounter wholeImageCounter; + wholeImageCounter.SetImage(m_Image); + wholeImageCounter.SetRegion(m_Image->GetLargestPossibleRegion()); + int voxelsWithValueOne = wholeImageCounter.VoxelWithValue(1); + + if (voxelsWithValueOne > 0) + { + std::stringstream message; + message << "Isolated " << voxelsWithValueOne << endl; + MITK_DEBUG << message.str(); + std::vector > comOfRegions; + m_SizeOfRegions.clear(); + + //Calculate all center of mass + for (int i = 0; i < m_InvalidRegions.size(); i++) + { + valueOfRegions.push_back(m_InvalidRegions[i].second); + itk::ImageRegionIterator it_region(m_Image, m_InvalidRegions[i].first); + + centerOfMass = this->GetCenterOfMass(it_region, m_InvalidRegions[i].second, true); + comOfRegions.push_back(centerOfMass); + } + + itk::ImageRegionIterator it_region(m_Image, m_Image->GetLargestPossibleRegion()); + + for (it_region.GoToBegin(); !it_region.IsAtEnd(); ++it_region) + { + if (it_region.Value() == 1) //Found Voxel with Value 1 + { + indexNewVoxel = it_region.GetIndex(); + + //distance calculation + for (int j = 0; j < m_InvalidRegions.size(); j++) + { + distance.push_back(this->GetDistance(comOfRegions[j], indexNewVoxel)); + indexInvalidRegions.push_back(j); + + } + + //Minimal distance + if (distance.size() != 0) + { + for (int i = 0; i < distance.size(); i++) + { + if (distance[i] == this->SmallestValue(distance)) + { + possibleNeighbor.push_back(i); + } + } + distance.clear(); + + //Check the Size of the Regions and get the smallest one! + //First get the regions with the same distance to COM + for (int i = 0; i < possibleNeighbor.size(); i++) + { + sizeOfPossibleRegions.push_back(m_SizeOfRegions[possibleNeighbor[i]]); + valueOfPossibleRegions.push_back(valueOfRegions[possibleNeighbor[i]]); + indexOfPossibleInvalidRegions.push_back(indexInvalidRegions[possibleNeighbor[i]]); + } + possibleNeighbor.clear(); + indexInvalidRegions.clear(); + + for (int i = 0; i < sizeOfPossibleRegions.size(); i++) + { + if (sizeOfPossibleRegions[i] == this->SmallestValue(sizeOfPossibleRegions)) + { + possibleNeighbor.push_back(i); + } + } + sizeOfPossibleRegions.clear(); + + thisNeighbor = xrand() % possibleNeighbor.size(); + + it_region.Value() = valueOfPossibleRegions[thisNeighbor]; + valueOfPossibleRegions.clear(); + possibleNeighbor.clear(); + + //region extansion if necessary + //first we need to get the right region + chosenRegion = m_InvalidRegions[indexOfPossibleInvalidRegions[thisNeighbor]]; + indexChosenVoxel = it_region.GetIndex(); + RegionType voxelRegion; + voxelRegion.SetIndex(indexChosenVoxel); + itk::Size<3> voxelSize; + voxelSize.Fill(1); + voxelRegion.SetSize(voxelSize); + + m_InvalidRegions[indexOfPossibleInvalidRegions[thisNeighbor]].first = this->ExtendedRegionNotNeighbor(chosenRegion.first, voxelRegion); + + indexOfPossibleInvalidRegions.clear(); + } + } + } + } +} + +template < typename TPixel, unsigned int VImageDimension > +int mitk::RandomParcellationGenerator::MergeParcels() +{ + typedef itk::Image< int, VImageDimension > IntegerImageType; + typedef itk::NeighborhoodIterator< IntegerImageType > NeighborhoodIteratorType; + typename NeighborhoodIteratorType::RadiusType radius; + radius.Fill(1); + + //Calculate the m_SizeOfRegions + this->GetSizeOfRegions(); + + int sizeOfSmallestRegion = this->SmallestValue(m_SizeOfRegions); + + std::vector smallRegions; + std::vector indexSmallRegions; + int thisIndex; + int thisSmallRegion; + bool mergingStillPossible(true); + std::vector smallDistances; + std::vector centerOfMassPossibleRegion; + std::vector > comOfRegions; + std::vector sizeSmallRegions; + std::vector smallestRegions; + bool tooManyParcels(true); + int currentNumberOfParcels = m_NumberNodes; + int sizeNewParcel; + std::vector costFunctionValue; + std::vector smallestCostFunctionValues; + std::vector valueOfPossibleRegions; + std::vector distance; + std::pair chosenRegion; + std::vector centerOfMass; + bool smallRegionFound(false); + bool hasNeighbors(false); + + while (sizeOfSmallestRegion < m_GivenSizeOfSmallestRegion && mergingStillPossible && tooManyParcels) + { + smallRegions.clear(); + sizeSmallRegions.clear(); + smallestRegions.clear(); + + //Find all small Regions + for (int i = 0; i < m_SizeOfRegions.size(); i++) + { + if (m_SizeOfRegions[i] < m_GivenSizeOfSmallestRegion) + { + smallRegions.push_back(i); + sizeSmallRegions.push_back(m_SizeOfRegions[i]); + } + } + + //Find one of the smallest regions + for (int i = 0; i < sizeSmallRegions.size(); i++) + { + if (sizeSmallRegions[i] == this->SmallestValue(sizeSmallRegions)) + { + smallestRegions.push_back(smallRegions[i]); + } + } + + if (smallestRegions.size() > 0 && this->SmallestValue(sizeSmallRegions) < m_GivenSizeOfSmallestRegionBeginning) + { + thisSmallRegion = rand() % smallestRegions.size(); + + //Choose a random small region + //First check if it has direct neighbors + NeighborhoodIteratorType it_neighborhood(radius, m_Image, m_InvalidRegions[smallestRegions[thisSmallRegion]].first); + valueOfPossibleRegions.clear(); + smallRegionFound = false; + hasNeighbors = false; + + for (it_neighborhood.GoToBegin(); !it_neighborhood.IsAtEnd(); ++it_neighborhood) + { + for (int k = 0; k <27; k++) + { + if ((k == 4 || k == 10 || k == 12 || k == 14 || k == 16 || k == 22) &&//over faces + it_neighborhood.GetPixel(k) > 2 //found value which belongs to a region != the chosen region + && it_neighborhood.GetPixel(k) != m_InvalidRegions[smallestRegions[thisSmallRegion]].second) + { + hasNeighbors = true; + for (int i = 0; i < smallRegions.size(); i++) + { + if (it_neighborhood.GetPixel(k) == m_InvalidRegions[smallRegions[i]].second) //The value belongs to a small region + { + valueOfPossibleRegions.push_back(it_neighborhood.GetPixel(k)); + smallRegionFound = true; + break; + } + } + } + } + } + + if (hasNeighbors == true) + { + if (smallRegionFound == true)//the region has direct neighbors + { + //valueOfPossibleRegions may contain some values, that are the same. Erase the duplicates and sort the vector. + std::sort(valueOfPossibleRegions.begin(), valueOfPossibleRegions.end()); + valueOfPossibleRegions.erase(std::unique(valueOfPossibleRegions.begin(), valueOfPossibleRegions.end()), valueOfPossibleRegions.end()); + + indexSmallRegions.clear(); + + //Get the values of the possible regions! + for (int i = 0; i < valueOfPossibleRegions.size() ; i++) + { + for (int j = 0; j < m_InvalidRegions.size(); j++) + { + if (valueOfPossibleRegions[i] == m_InvalidRegions[j].second) + { + indexSmallRegions.push_back(j); + break; + } + } + } + + //take the region with the greatest value of the cost function + //the cost function depends on the distance (btw the 2 COMs) and the size of the merged parcel + + //First get all the distances + itk::ImageRegionIterator it_regionSmallest(m_Image, m_InvalidRegions[smallestRegions[thisSmallRegion]].first); + std::vector centerOfMassCurrentRegion = this->GetCenterOfMass(it_regionSmallest, m_InvalidRegions[smallestRegions[thisSmallRegion]].second, false); + + distance.clear(); + + for (int i = 0; i < indexSmallRegions.size(); i++) + { + itk::ImageRegionIterator it_region(m_Image, m_InvalidRegions[indexSmallRegions[i]].first); + centerOfMassPossibleRegion = this->GetCenterOfMass(it_region, m_InvalidRegions[indexSmallRegions[i]].second, false); + distance.push_back(this->GetDistanceVector(centerOfMassCurrentRegion, centerOfMassPossibleRegion)); + } + smallDistances.clear(); + + if (m_MergingWithSmallestParcel && m_JustMergeSmallParcels) + { + //If there are small Regions with equal distance btw the COMs choose a random one + for (int i = 0; i < distance.size(); i++) + { + if (distance[i] == this->SmallestValue(distance)) + { + smallDistances.push_back(indexSmallRegions[i]); + } + } + thisIndex = smallDistances[rand() % smallDistances.size()]; + } + + //Calculate the cost function values + + if (m_MergingWithNumberParcels || (m_MergingWithSmallestParcel && !m_JustMergeSmallParcels)) + { + costFunctionValue.clear(); + + for (int i = 0; i < indexSmallRegions.size(); i++) + { + if (distance[i] == 0) + { + distance[i] = 0.01; + } + sizeNewParcel = (m_SizeOfRegions[smallestRegions[thisSmallRegion]] + m_SizeOfRegions[indexSmallRegions[i]]); + + costFunctionValue.push_back(-(1.0/distance[i]) - (1.0/sizeNewParcel)); //1, 2 or 3 at sizeNewParcel + } + smallestCostFunctionValues.clear(); + + for (int i = 0; i < indexSmallRegions.size(); i++) + { + if (costFunctionValue[i] == this->SmallestValue(costFunctionValue)) + { + smallestCostFunctionValues.push_back(indexSmallRegions[i]); + } + } + thisIndex = smallestCostFunctionValues[rand() % smallestCostFunctionValues.size()]; + } + + //m_InvalidRegions[thisIndex].first is the region we want to merge with our current one + + //Colour the small parcel like the found one + for (it_regionSmallest.GoToBegin(); !it_regionSmallest.IsAtEnd(); ++it_regionSmallest) + { + if (it_regionSmallest.Value() == m_InvalidRegions[smallestRegions[thisSmallRegion]].second) + { + it_regionSmallest.Value() = m_InvalidRegions[thisIndex].second; + } + } + + //Expand the region of the new parcel if necessary! + + chosenRegion = m_InvalidRegions[thisIndex]; + chosenRegion.first = this->ExtendedRegionNotNeighbor(chosenRegion.first, m_InvalidRegions[smallestRegions[thisSmallRegion]].first); + m_InvalidRegions[thisIndex] = chosenRegion; + + //Erase the smallest Region from m_InvalidRegions + m_InvalidRegions.erase(m_InvalidRegions.begin() + smallestRegions[thisSmallRegion]); + currentNumberOfParcels--; + + if (currentNumberOfParcels <= m_DesiredNumberOfParcels) + { + tooManyParcels = false; + } + + //m_SizeOfRegions changed, get the new one + this->GetSizeOfRegions(); + } + + else //No merging possible, erase this small region from m_InvalidRegions and from m_SizeOfRegions + { + m_InvalidRegions.erase(m_InvalidRegions.begin() + smallestRegions[thisSmallRegion]); + currentNumberOfParcels--; + m_SizeOfFinishedRegions.push_back(m_SizeOfRegions[smallestRegions[thisSmallRegion]]); + m_SizeOfRegions.erase(m_SizeOfRegions.begin() + smallestRegions[thisSmallRegion]); + + if (currentNumberOfParcels <= m_DesiredNumberOfParcels) + { + tooManyParcels = false; + } + } + } + else //There are no 6-connected neighborhood-regions. Try to merge this small region to a near region (according to the Center of Mass) + { + comOfRegions.clear(); + //Calculate the center of mass of all small regions + for (int i = 0; i < smallRegions.size(); i++) + { + itk::ImageRegionIterator it_region(m_Image, m_InvalidRegions[smallRegions[i]].first); + + centerOfMass = this->GetCenterOfMass(it_region, m_InvalidRegions[smallRegions[i]].second, false); + comOfRegions.push_back(centerOfMass); + } + + //Calculate the distance between the center of mass of our small region and all other regions + itk::ImageRegionIterator it_regionSmallest(m_Image, m_InvalidRegions[smallestRegions[thisSmallRegion]].first); + std::vector centerOfMassCurrentRegion = this->GetCenterOfMass(it_regionSmallest, m_InvalidRegions[smallestRegions[thisSmallRegion]].second, false); + + distance.clear(); + + for (int i = 0; i < smallRegions.size(); i++) + { + itk::ImageRegionIterator it_region(m_Image, m_InvalidRegions[smallRegions[i]].first); + centerOfMassPossibleRegion = this->GetCenterOfMass(it_region, m_InvalidRegions[smallRegions[i]].second, false); + distance.push_back(this->GetDistanceVector(centerOfMassCurrentRegion, centerOfMassPossibleRegion)); + } + smallDistances.clear(); + std::vector distanceWithoutZero = distance; + for (int i = 0; i < distanceWithoutZero.size(); i++) + { + if (distanceWithoutZero[i] == 0) + { + distanceWithoutZero.erase(distanceWithoutZero.begin() + i); //Our smallestRegion is calculated too, erase the zero entry + break; + } + } + + if (distanceWithoutZero.size() > 0) + { + //If there are small Regions with equal distance btw the COM's choose a random one + for (int i = 0; i < distance.size(); i++) + { + if (distance[i] == this->SmallestValue(distanceWithoutZero)) + { + smallDistances.push_back(smallRegions[i]); + } + } + + thisIndex = smallDistances[rand() % smallDistances.size()]; + + //Colour the small parcel like the found one + for (it_regionSmallest.GoToBegin(); !it_regionSmallest.IsAtEnd(); ++it_regionSmallest) + { + if (it_regionSmallest.Value() == m_InvalidRegions[smallestRegions[thisSmallRegion]].second) + { + it_regionSmallest.Value() = m_InvalidRegions[thisIndex].second; + } + } + + //Expand the region of the new parcel if necessary! + chosenRegion = m_InvalidRegions[thisIndex]; + chosenRegion.first = this->ExtendedRegionNotNeighbor(chosenRegion.first , m_InvalidRegions[smallestRegions[thisSmallRegion]].first); + m_InvalidRegions[thisIndex] = chosenRegion; + + //Erase the smallest Region from m_InvalidRegions + m_InvalidRegions.erase(m_InvalidRegions.begin() + smallestRegions[thisSmallRegion]); + currentNumberOfParcels--; + + if (currentNumberOfParcels <= m_DesiredNumberOfParcels) + { + tooManyParcels = false; + } + + //m_SizeOfRegions changed, get the new one + this->GetSizeOfRegions(); + } + + else//No merging possible, erase this small region from m_InvalidRegions and from m_SizeOfRegions + { + m_InvalidRegions.erase(m_InvalidRegions.begin() + smallestRegions[thisSmallRegion]); + currentNumberOfParcels--; + m_SizeOfFinishedRegions.push_back(m_SizeOfRegions[smallestRegions[thisSmallRegion]]); + m_SizeOfRegions.erase(m_SizeOfRegions.begin() + smallestRegions[thisSmallRegion]); + + if (currentNumberOfParcels <= m_DesiredNumberOfParcels) + { + tooManyParcels = false; + } + } + } + } + else //there are no parcels left to merge with + { + mergingStillPossible = false; + } + } + return (m_SizeOfFinishedRegions.size() + m_SizeOfRegions.size()); +} + +template < typename TPixel, unsigned int VImageDimension > +void mitk::RandomParcellationGenerator::GetSizeOfRegions() +{ + m_SizeOfRegions.clear(); + RegionVoxelCounter voxelCounter; + voxelCounter.SetImage(m_Image); + for (int i = 0; i < m_InvalidRegions.size(); i++) + { + voxelCounter.SetRegion(m_InvalidRegions[i].first); + m_SizeOfRegions.push_back(voxelCounter.VoxelWithValue(m_InvalidRegions[i].second)); + } +} + +template < typename TPixel, unsigned int VImageDimension > +void mitk::RandomParcellationGenerator::ShowSizeOfRegions() +{ + RegionVoxelCounter voxelCounter; + voxelCounter.SetImage(m_Image); + std::stringstream message; + for (int i = 0; i < m_InvalidRegions.size(); i++) + { + voxelCounter.SetRegion(m_InvalidRegions[i].first); + m_SizeOfRegions.push_back(voxelCounter.VoxelWithValue(m_InvalidRegions[i].second)); + message << voxelCounter.VoxelWithValue(m_InvalidRegions[i].second) << " , "; + } + MITK_DEBUG << message.str(); +} diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.h b/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.h new file mode 100644 index 0000000000..1758fb5abd --- /dev/null +++ b/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.h @@ -0,0 +1,127 @@ +/*=================================================================== + +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 mitkRandomParcellationGenerator_h +#define mitkRandomParcellationGenerator_h + +#include + +#include "mitkCommon.h" +#include "MitkConnectomicsExports.h" + +// mitk +#include +#include + +//Itk Iterators +#include +#include + +#include + +//To use pair +#include + +namespace mitk +{ + + template + class RandomParcellationGenerator + { + public: + typedef itk::Image< TPixel, VImageDimension > ImageType; + + //Set-Functions + void SetImage(itk::Image *); + void SetNumberNodes(int inputNumberNodes); + void SetVariablesForMerging(int givenSizeOfSmallestRegion, int desiredNumberOfParcels, int givenSizeOfSmallestRegionBeginning); + void SetBoolsForMerging(bool mergingWithNumberParcels, bool mergingWithSmallestParcel, bool justMergeSmallParcels); + + //Main Functions + + /** \brief Sets randomly chosen seed voxels (1x1x1 regions) on the segmented image + * This is done by creating a vector with unique values, which represents the position of a voxel respectively. + * For this purpose we count all voxels with value one and choose random numbers. + */ + void GetRandomSeedVoxels(); + /** \brief Add appropriate voxels of the segmented part to a region (just 6-connected neighborhood) + * A voxel is appropriate if the cost function value is high enough. Several constraints have to be fulfilled for this purpose. + */ + void ParcelGrowthOverFaces(); + /** \brief Add voxels of the segmented part to an appropriate region (26-connected neighborhood) + * Checks which voxels still have value one and to which neighborhood-region each one should be added. + */ + void FillOverEdgeOrVertex(); + /** \brief Add voxels of the segmented part to an appropriate region (no neighbors necessary) + * Checks which voxels still have value one and calculates the distance to all parcels. + * Finally each voxel is added to the region with the smallest distance to it. + */ + void AllocateIsolatedVoxels(); + /** \brief Merge parcels according to a cost function + * Looks for the parcel with the smallest number of voxels. + * Then merges it to a neighborhood-parcel such that the cost function value is small enough. + * The new number of nodes is returned so we can show them on the GUI. + */ + int MergeParcels(); + /** \brief Changes the values of the nodes, such that no gaps exist and it starts with value 1*/ + void SetAppropriateValues(); + /** \brief Calculates and shows the size (number of voxels) of all regions on the console*/ + void ShowSizeOfRegions(); + + protected: + //Sub-Functions + /** \brief Gives back the center of mass and -if wanted- the size (number of voxels) of a parcel*/ + std::vector GetCenterOfMass( itk::ImageRegionIterator it_region, int valueOfRegion, bool getSizeOfRegions ); + /** \brief Calculates the distance between two voxels, the position of the first one is given by an index and the position of the second one is given by a vector*/ + double GetDistance( std::vector centerOfMass, typename ImageType::IndexType indexNewVoxel); + /** \brief Calculates the distance between two voxels, both positions are given by vectors*/ + double GetDistanceVector( std::vector centerOfMass, std::vector indexNewVoxel); + /** \brief Gives back the smallest value of an int-vector*/ + int SmallestValue (std::vector distance); + /** \brief Gives back the smallest value of a double-vector*/ + double SmallestValue (std::vector distance); + /** \brief Extends the region if the chosen voxel lies outside*/ + typename ImageType::RegionType ExtendedRegion(typename ImageType::RegionType chosenRegion, typename ImageType::IndexType indexChosenVoxel); + /** \brief Extends the region of a parcel such that the second region lies within*/ + typename ImageType::RegionType ExtendedRegionNotNeighbor(typename ImageType::RegionType chosenRegion, typename ImageType::RegionType smallestRegion); + /** \brief Checks if a number is an element of the vector already*/ + bool IsUnique (int number, std::vector vec); + /** \brief Calculates the size (number of voxels) of all regions*/ + void GetSizeOfRegions(); + + typedef itk::ImageRegion<3> RegionType; + //Start the algorithm ParcelGrowthOverFaces with m_OddRegions and transfer them to m_EvenRegions or m_InvalidRegions respectively + std::vector > m_EvenRegions; + std::vector > m_OddRegions; + std::vector > m_InvalidRegions; + std::vector m_SizeOfRegions; + //For merging; regions that can't be merged any more + std::vector m_SizeOfFinishedRegions; + + ImageType * m_Image; + int m_NumberNodes; + int m_GivenSizeOfSmallestRegion; + int m_DesiredNumberOfParcels; + int m_GivenSizeOfSmallestRegionBeginning; + bool m_MergingWithNumberParcels; + bool m_MergingWithSmallestParcel; + bool m_JustMergeSmallParcels; + }; +} + +#include "mitkRandomParcellationGenerator.cpp" + +#endif /* mitkRandomParcellationGenerator_h */ \ No newline at end of file diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.cpp b/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.cpp new file mode 100644 index 0000000000..4c4f8ad725 --- /dev/null +++ b/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.cpp @@ -0,0 +1,61 @@ +/*=================================================================== + +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. + +===================================================================*/ + +//#include + +//Itk Iterators +#include +#include + +//Set Functions +template +void mitk::RegionVoxelCounter::SetRegion(typename ImageType::RegionType region) +{ + m_Region = region; +} + +template +void mitk::RegionVoxelCounter::SetImage(itk::Image * image) +{ + m_Image = image; +} + +//Other Functions +template +int mitk::RegionVoxelCounter::VoxelWithValue(int value) +{ + itk::ImageRegionIterator it_region(m_Image, m_Region); + int counter(0); + + for (it_region.GoToBegin(); !it_region.IsAtEnd(); ++it_region) + { + if (it_region.Value() == value) //Found Voxel with chosen value + { + counter++; + } + } + return counter; +} + +template +double mitk::RegionVoxelCounter::PercentageVoxelWithValueZeroExcluded(int value) +{ + itk::Size<3> regionSize = m_Region.GetSize(); + double volume = regionSize[0] * regionSize[1] * regionSize[2]; + + double measurement = this->VoxelWithValue(value) / (volume - this->VoxelWithValue(0)); + return measurement; +} \ No newline at end of file diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.h b/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.h new file mode 100644 index 0000000000..0284dc0061 --- /dev/null +++ b/Modules/DiffusionImaging/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.h @@ -0,0 +1,51 @@ +/*=================================================================== + +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 mitkRegionVoxelCounter_h +#define mitkRegionVoxelCounter_h + +#include + +#include "mitkCommon.h" +#include "MitkConnectomicsExports.h" + +namespace mitk +{ + + template + class RegionVoxelCounter + { + public: + typedef itk::Image< TPixel, VImageDimension > ImageType; + + void SetRegion(typename ImageType::RegionType); + void SetImage(itk::Image *); + + /** \brief Counts all voxels with the chosen value in the set region*/ + int VoxelWithValue(int value); + /** \brief Gives back the percentage of the number of voxels with the chosen value in comparison to the number of voxels with other values (except zero)*/ + double PercentageVoxelWithValueZeroExcluded(int value); + + private: + typename ImageType::RegionType m_Region; + ImageType * m_Image; + }; + +} + +#include "mitkRegionVoxelCounter.cpp" + +#endif /* mitkRegionVoxelCounter_h */ \ No newline at end of file diff --git a/Modules/DiffusionImaging/Connectomics/CMakeLists.txt b/Modules/DiffusionImaging/Connectomics/CMakeLists.txt index e6c1373f33..8da95239a6 100644 --- a/Modules/DiffusionImaging/Connectomics/CMakeLists.txt +++ b/Modules/DiffusionImaging/Connectomics/CMakeLists.txt @@ -1,28 +1,28 @@ # With apple clang 5.0 the following waring leads to an build error if boost is enabled if(APPLE) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=tautological-constant-out-of-range-compare" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() # Boost throws a lot of unused variable warnings on linux if(UNIX) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=unused-variable" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=unneeded-internal-declaration" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() # there are additional warnings in boost headers in Release mode with special gcc versions if(CMAKE_COMPILER_IS_GNUCXX) if (CMAKE_BUILD_TYPE STREQUAL "Release" AND (${GCC_VERSION} VERSION_EQUAL "4.8" OR ${GCC_VERSION} VERSION_GREATER "4.8")) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=maybe-uninitialized" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=unused-parameter" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() endif() MITK_CREATE_MODULE( SUBPROJECTS MITK-DTI - INCLUDE_DIRS Algorithms IODataStructures Rendering ${CMAKE_CURRENT_BINARY_DIR} + INCLUDE_DIRS Algorithms Algorithms/BrainParcellation IODataStructures Rendering ${CMAKE_CURRENT_BINARY_DIR} DEPENDS MitkDiffusionCore MitkFiberTracking PACKAGE_DEPENDS VTK|vtkInfovisLayout WARNINGS_AS_ERRORS ) add_subdirectory(Testing) diff --git a/Modules/DiffusionImaging/Connectomics/files.cmake b/Modules/DiffusionImaging/Connectomics/files.cmake index 331440c0bd..71f64af741 100644 --- a/Modules/DiffusionImaging/Connectomics/files.cmake +++ b/Modules/DiffusionImaging/Connectomics/files.cmake @@ -1,75 +1,78 @@ set(CPP_FILES # DataStructures Connectomics IODataStructures/mitkConnectomicsNetwork.cpp IODataStructures/mitkConnectomicsConstantsManager.cpp # Rendering Connectomics Rendering/mitkConnectomicsNetworkMapper3D.cpp Rendering/mitkConnectomicsRenderingSchemeProperty.cpp Rendering/mitkConnectomicsRenderingEdgeFilteringProperty.cpp Rendering/mitkConnectomicsRenderingNodeFilteringProperty.cpp Rendering/mitkConnectomicsRenderingEdgeColorParameterProperty.cpp Rendering/mitkConnectomicsRenderingEdgeRadiusParameterProperty.cpp Rendering/mitkConnectomicsRenderingNodeColorParameterProperty.cpp Rendering/mitkConnectomicsRenderingNodeRadiusParameterProperty.cpp Rendering/mitkConnectomicsRenderingNodeThresholdParameterProperty.cpp Rendering/mitkConnectomicsRenderingEdgeThresholdParameterProperty.cpp Rendering/mitkConnectomicsEnumerationSubclassesSerializer.cpp # Algorithms Connectomics Algorithms/mitkConnectomicsNetworkCreator.cpp Algorithms/mitkConnectomicsHistogramBase.cpp Algorithms/mitkConnectomicsDegreeHistogram.cpp Algorithms/mitkConnectomicsShortestPathHistogram.cpp Algorithms/mitkConnectomicsBetweennessHistogram.cpp Algorithms/mitkConnectomicsHistogramCache.cpp Algorithms/mitkConnectomicsSyntheticNetworkGenerator.cpp Algorithms/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp Algorithms/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp Algorithms/mitkConnectomicsSimulatedAnnealingManager.cpp Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp Algorithms/mitkConnectomicsStatisticsCalculator.cpp Algorithms/mitkConnectomicsNetworkConverter.cpp Algorithms/mitkConnectomicsNetworkThresholder.cpp ) set(H_FILES # Rendering Connectomics Rendering/mitkConnectomicsNetworkMapper3D.h Rendering/mitkConnectomicsRenderingProperties.h Rendering/mitkConnectomicsRenderingSchemeProperty.h Rendering/mitkConnectomicsRenderingEdgeFilteringProperty.h Rendering/mitkConnectomicsRenderingNodeFilteringProperty.h Rendering/mitkConnectomicsRenderingEdgeColorParameterProperty.h Rendering/mitkConnectomicsRenderingEdgeRadiusParameterProperty.h Rendering/mitkConnectomicsRenderingNodeColorParameterProperty.h Rendering/mitkConnectomicsRenderingNodeRadiusParameterProperty.h Rendering/mitkConnectomicsRenderingNodeThresholdParameterProperty.h Rendering/mitkConnectomicsRenderingEdgeThresholdParameterProperty.h # Datastructures Connectomics IODataStructures/mitkConnectomicsNetwork.h IODataStructures/mitkConnectomicsConstantsManager.h # Algorithms Connectomics Algorithms/mitkConnectomicsNetworkCreator.h Algorithms/mitkConnectomicsHistogramBase.h Algorithms/mitkConnectomicsDegreeHistogram.h Algorithms/mitkConnectomicsShortestPathHistogram.h Algorithms/mitkConnectomicsBetweennessHistogram.h Algorithms/mitkConnectomicsHistogramCache.h Algorithms/mitkConnectomicsSyntheticNetworkGenerator.h Algorithms/mitkConnectomicsSimulatedAnnealingPermutationBase.h Algorithms/mitkConnectomicsSimulatedAnnealingPermutationModularity.h Algorithms/mitkConnectomicsSimulatedAnnealingManager.h Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h Algorithms/itkConnectomicsNetworkToConnectivityMatrixImageFilter.h Algorithms/mitkConnectomicsStatisticsCalculator.h Algorithms/mitkConnectomicsNetworkConverter.h + Algorithms/BrainParcellation/mitkCostFunctionBase.h + Algorithms/BrainParcellation/mitkRandomParcellationGenerator.h + Algorithms/BrainParcellation/mitkRegionVoxelCounter.h ) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake index 12233dbd7d..744c3dea44 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake @@ -1,181 +1,185 @@ set(SRC_CPP_FILES QmitkODFDetailsWidget.cpp QmitkODFRenderWidget.cpp QmitkPartialVolumeAnalysisWidget.cpp QmitkIVIMWidget.cpp QmitkTbssRoiAnalysisWidget.cpp QmitkResidualAnalysisWidget.cpp QmitkResidualViewWidget.cpp QmitkTensorModelParametersWidget.cpp QmitkZeppelinModelParametersWidget.cpp QmitkStickModelParametersWidget.cpp QmitkDotModelParametersWidget.cpp QmitkBallModelParametersWidget.cpp QmitkAstrosticksModelParametersWidget.cpp ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp QmitkQBallReconstructionView.cpp QmitkPreprocessingView.cpp QmitkDiffusionDicomImportView.cpp QmitkDiffusionQuantificationView.cpp QmitkTensorReconstructionView.cpp QmitkDiffusionImagingPublicPerspective.cpp QmitkControlVisualizationPropertiesView.cpp QmitkODFDetailsView.cpp QmitkGibbsTrackingView.cpp QmitkStochasticFiberTrackingView.cpp QmitkStreamlineTrackingView.cpp QmitkFiberProcessingView.cpp # QmitkFiberBundleDeveloperView.cpp QmitkPartialVolumeAnalysisView.cpp QmitkIVIMView.cpp QmitkTractbasedSpatialStatisticsView.cpp QmitkTbssTableModel.cpp QmitkTbssMetaTableModel.cpp QmitkTbssSkeletonizationView.cpp Connectomics/QmitkConnectomicsDataView.cpp Connectomics/QmitkConnectomicsNetworkOperationsView.cpp Connectomics/QmitkConnectomicsStatisticsView.cpp Connectomics/QmitkNetworkHistogramCanvas.cpp + Connectomics/QmitkRandomParcellationView.cpp QmitkDwiSoftwarePhantomView.cpp QmitkOdfMaximaExtractionView.cpp QmitkFiberfoxView.cpp QmitkFiberExtractionView.cpp QmitkFieldmapGeneratorView.cpp QmitkDiffusionRegistrationView.cpp QmitkDenoisingView.cpp ) set(UI_FILES src/internal/QmitkQBallReconstructionViewControls.ui src/internal/QmitkPreprocessingViewControls.ui src/internal/QmitkDiffusionDicomImportViewControls.ui src/internal/QmitkDiffusionQuantificationViewControls.ui src/internal/QmitkTensorReconstructionViewControls.ui src/internal/QmitkControlVisualizationPropertiesViewControls.ui src/internal/QmitkODFDetailsViewControls.ui src/internal/QmitkGibbsTrackingViewControls.ui src/internal/QmitkStochasticFiberTrackingViewControls.ui src/internal/QmitkStreamlineTrackingViewControls.ui src/internal/QmitkFiberProcessingViewControls.ui # src/internal/QmitkFiberBundleDeveloperViewControls.ui src/internal/QmitkPartialVolumeAnalysisViewControls.ui src/internal/QmitkIVIMViewControls.ui src/internal/QmitkTractbasedSpatialStatisticsViewControls.ui src/internal/QmitkTbssSkeletonizationViewControls.ui src/internal/Connectomics/QmitkConnectomicsDataViewControls.ui src/internal/Connectomics/QmitkConnectomicsNetworkOperationsViewControls.ui src/internal/Connectomics/QmitkConnectomicsStatisticsViewControls.ui + src/internal/Connectomics/QmitkRandomParcellationViewControls.ui src/internal/QmitkDwiSoftwarePhantomViewControls.ui src/internal/QmitkOdfMaximaExtractionViewControls.ui src/internal/QmitkFiberfoxViewControls.ui src/internal/QmitkFiberExtractionViewControls.ui src/QmitkTensorModelParametersWidgetControls.ui src/QmitkZeppelinModelParametersWidgetControls.ui src/QmitkStickModelParametersWidgetControls.ui src/QmitkDotModelParametersWidgetControls.ui src/QmitkBallModelParametersWidgetControls.ui src/QmitkAstrosticksModelParametersWidgetControls.ui src/internal/QmitkFieldmapGeneratorViewControls.ui src/internal/QmitkDiffusionRegistrationViewControls.ui src/internal/QmitkDenoisingViewControls.ui ) set(MOC_H_FILES src/internal/mitkPluginActivator.h src/internal/QmitkQBallReconstructionView.h src/internal/QmitkPreprocessingView.h src/internal/QmitkDiffusionDicomImportView.h src/internal/QmitkDiffusionImagingPublicPerspective.h src/internal/QmitkDiffusionQuantificationView.h src/internal/QmitkTensorReconstructionView.h src/internal/QmitkControlVisualizationPropertiesView.h src/internal/QmitkODFDetailsView.h src/QmitkODFRenderWidget.h src/QmitkODFDetailsWidget.h src/internal/QmitkGibbsTrackingView.h src/internal/QmitkStochasticFiberTrackingView.h src/internal/QmitkStreamlineTrackingView.h src/internal/QmitkFiberProcessingView.h # src/internal/QmitkFiberBundleDeveloperView.h src/internal/QmitkPartialVolumeAnalysisView.h src/QmitkPartialVolumeAnalysisWidget.h src/internal/QmitkIVIMView.h src/internal/QmitkTractbasedSpatialStatisticsView.h src/internal/QmitkTbssSkeletonizationView.h src/QmitkTbssRoiAnalysisWidget.h src/QmitkResidualAnalysisWidget.h src/QmitkResidualViewWidget.h src/internal/Connectomics/QmitkConnectomicsDataView.h src/internal/Connectomics/QmitkConnectomicsNetworkOperationsView.h src/internal/Connectomics/QmitkConnectomicsStatisticsView.h src/internal/Connectomics/QmitkNetworkHistogramCanvas.h + src/internal/Connectomics/QmitkRandomParcellationView.h src/internal/QmitkDwiSoftwarePhantomView.h src/internal/QmitkOdfMaximaExtractionView.h src/internal/QmitkFiberfoxView.h src/internal/QmitkFiberExtractionView.h src/QmitkTensorModelParametersWidget.h src/QmitkZeppelinModelParametersWidget.h src/QmitkStickModelParametersWidget.h src/QmitkDotModelParametersWidget.h src/QmitkBallModelParametersWidget.h src/QmitkAstrosticksModelParametersWidget.h src/internal/QmitkFieldmapGeneratorView.h src/internal/QmitkDiffusionRegistrationView.h src/internal/QmitkDenoisingView.h ) set(CACHED_RESOURCE_FILES # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench plugin.xml resources/preprocessing.png resources/dwiimport.png resources/quantification.png resources/reconodf.png resources/recontensor.png resources/vizControls.png resources/OdfDetails.png resources/GibbsTracking.png resources/FiberBundleOperations.png resources/PartialVolumeAnalysis_24.png resources/IVIM_48.png resources/stochFB.png resources/tbss.png resources/connectomics/QmitkConnectomicsDataViewIcon_48.png resources/connectomics/QmitkConnectomicsNetworkOperationsViewIcon_48.png resources/connectomics/QmitkConnectomicsStatisticsViewIcon_48.png + resources/connectomics/QmitkRandomParcellationIcon.png resources/arrow.png resources/qball_peaks.png resources/phantom.png resources/tensor.png resources/qball.png resources/StreamlineTracking.png resources/dwi2.png resources/odf.png resources/refresh.xpm resources/diffusionregistration.png resources/denoisingicon.png ) set(QRC_FILES # uncomment the following line if you want to use Qt resources resources/QmitkDiffusionImaging.qrc #resources/QmitkTractbasedSpatialStatisticsView.qrc ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/plugin.xml b/Plugins/org.mitk.gui.qt.diffusionimaging/plugin.xml index b62e7906c4..f2fdaffc50 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/plugin.xml +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/plugin.xml @@ -1,188 +1,194 @@ Q-Ball reconstruction view Diffusion DICOM data import + + This is a short information about this perspective diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkDiffusionImaging.qrc b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkDiffusionImaging.qrc index 03fff7a423..433010c36f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkDiffusionImaging.qrc +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkDiffusionImaging.qrc @@ -1,63 +1,64 @@ qball.png tensor.png dwi.png dwiimport.png quantification.png reconodf.png recontensor.png texIntONIcon.png texIntOFFIcon.png vizControls.png Refresh_48.png QBallData24.png glyphsoff_C.png glyphsoff_S.png glyphsoff_T.png glyphson_C.png glyphson_S.png glyphson_T.png FiberBundle.png FiberBundleX.png connectomics/ConnectomicsNetwork.png + connectomics/QmitkRandomParcellationIcon.png rectangle.png circle.png polygon.png color24.gif color48.gif color64.gif crosshair.png paint2.png IVIM_48.png reset.png MapperEfx2D.png refresh.xpm odf.png general_icons/download.ico general_icons/play.ico general_icons/plus.ico general_icons/refresh.ico general_icons/right.ico general_icons/save.ico general_icons/undo.ico general_icons/upload.ico general_icons/abort.ico general_icons/copy1.ico general_icons/copy2.ico general_icons/cut.ico general_icons/deny1.ico general_icons/deny2.ico general_icons/down.ico general_icons/left.ico general_icons/magn_minus.ico general_icons/magn_plus.ico general_icons/search.ico general_icons/stop.ico general_icons/up.ico general_icons/help.ico general_icons/pencil.ico general_icons/edit.ico denoisingicon.png diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/connectomics/QmitkRandomParcellationIcon.png b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/connectomics/QmitkRandomParcellationIcon.png new file mode 100644 index 0000000000..10728e8e8a Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/connectomics/QmitkRandomParcellationIcon.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkRandomParcellationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkRandomParcellationView.cpp new file mode 100644 index 0000000000..c061ffc7d9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkRandomParcellationView.cpp @@ -0,0 +1,359 @@ +/*=================================================================== + +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 "QmitkRandomParcellationView.h" + +// Blueberry +#include +#include + +// Qt +#include + +// Includes for image casting between ITK and MITK +#include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" +#include "mitkITKImageImport.h" + +//To convert integer to string +#include +#include + +//Itk Iterators +#include +#include + +// mitk +#include +#include + + +//Child +const std::string QmitkRandomParcellationView::PROPERTYNAME = "name"; +const std::string QmitkRandomParcellationView::PROPERTYOPACITY = "opacity"; +const std::string QmitkRandomParcellationView::m_NAMEFORRANDOMVOXELIMAGE = "Random Voxel Image"; + +const std::string QmitkRandomParcellationView::VIEW_ID = "org.mitk.views.randomparcellationview"; + + +void QmitkRandomParcellationView::SetFocus() +{ + m_Controls.buttonSelectRandomNodes->setFocus(); +} + +void QmitkRandomParcellationView::CreateQtPartControl( QWidget *parent ) +{ + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi( parent ); + connect( m_Controls.buttonSelectRandomNodes, SIGNAL(clicked()), this, SLOT(SelectRandomNodes()) ); + connect( m_Controls.checkBoxMerging, SIGNAL(stateChanged(int)),this, SLOT(OnMergingCheckboxChanged(int))); + connect( m_Controls.radioButtonNumberParcels, SIGNAL(clicked()), this, SLOT(OnRadioButtonNumberParcelsChanged(int))); + connect( m_Controls.radioButtonSmallestParcel, SIGNAL(clicked()), this, SLOT(OnRadioButtonSmallestParcelChanged(int))); +} + +void QmitkRandomParcellationView::OnMergingCheckboxChanged(int state) +{ + if (m_Controls.checkBoxMerging->isChecked()) + { + //Make the frame visible + m_Controls.frameMerging->setEnabled(true); + m_Controls.frameNumberParcels->setEnabled(true); + m_Controls.frameSmallestParcel->setEnabled(true); + } + else + { + m_Controls.frameMerging->setEnabled(false); + } +} + +void QmitkRandomParcellationView::OnRadioButtonNumberParcelsChanged(int state) +{ + if (m_Controls.radioButtonNumberParcels->isChecked()) + { + m_Controls.frameNumberParcels->setEnabled(true); + m_Controls.radioButtonSmallestParcel->setChecked(false); + } + else + { + m_Controls.frameNumberParcels->setEnabled(false); + } +} + +void QmitkRandomParcellationView::OnRadioButtonSmallestParcelChanged(int state) +{ + if (m_Controls.radioButtonSmallestParcel->isChecked()) + { + m_Controls.frameSmallestParcel->setEnabled(true); + m_Controls.radioButtonNumberParcels->setChecked(false); + } + else + { + m_Controls.frameSmallestParcel->setEnabled(false); + } +} + +void QmitkRandomParcellationView::OnSelectionChanged(std::vector nodes ) +{ + // iterate all selected objects, adjust warning visibility + foreach( mitk::DataNode::Pointer node, nodes ) + { + if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + { + m_Controls.labelWarning->setVisible( false ); + m_Controls.buttonSelectRandomNodes->setEnabled( true ); + mitk::Image* imageDisplay = dynamic_cast(node->GetData()); + AccessFixedDimensionByItk(imageDisplay, ShowNumberOfVoxels, 3); + return; + } + } + + m_Controls.labelWarning->setVisible( true ); + m_Controls.buttonSelectRandomNodes->setEnabled( false ); +} + +template +void QmitkRandomParcellationView::ShowNumberOfVoxels( itk::Image * inputImage) +{ + typedef itk::Image< TPixel, VImageDimension > ImageType; + + mitk::RegionVoxelCounter counter; + counter.SetRegion(inputImage->GetLargestPossibleRegion()); + counter.SetImage(inputImage); + int numberVoxelsDisplay = counter.VoxelWithValue(1); + std::string stringDisplay = "Number of voxels with value 1: "; + std::ostringstream convertDisplay; + convertDisplay << numberVoxelsDisplay; + std::string stringNumberVoxels = convertDisplay.str(); + stringDisplay += stringNumberVoxels; + QString textNumberVoxelsDisplay = QString::fromStdString(stringDisplay); + m_Controls.labelNumberVoxels->setText(textNumberVoxelsDisplay); +} + + +void QmitkRandomParcellationView::SelectRandomNodes() +{ + std::vector nodes = this->GetDataManagerSelection(); + if (nodes.empty()) return; + + mitk::DataNode* node = nodes.front(); + + if (!node) + { + // Nothing selected. Inform the user and return + QMessageBox::information( NULL, "No image available", "Please load and select an image before starting image processing."); + return; + } + + // here we have a valid mitk::DataNode + + // a node itself is not very useful, we need its data item (the image) + mitk::BaseData* data = node->GetData(); + if (data) + { + // test if this data item is an image or not (could also be a surface or something totally different) + mitk::Image* image = dynamic_cast( data ); + if (image) + { + //get numberNodes (number of nodes) with SpinBox + int numberNodes( 0 ); + numberNodes = m_Controls.spinBoxNumberNodes->value(); + + std::stringstream message; + std::string name; + message << "Selecting " << numberNodes << " random nodes for "; + if (node->GetName(name)) + { + // a property called "name" was found for this DataNode + message << "'" << name << "'"; + } + message << "."; + MITK_INFO << message.str(); + + //MITK into ITK image, function GetRandomParcels gets executed, Dimension is 3 + AccessFixedDimensionByItk(image, GetRandomParcels, 3); + + } + } +} + + + +template +void QmitkRandomParcellationView::GetRandomParcels( itk::Image * inputImage) +{ + typedef itk::Image< TPixel, VImageDimension > ImageType; + typedef itk::Image< int, VImageDimension > IntegerImageType; + + //new Image which will contain the parcellation + typename IntegerImageType::Pointer voxelImage = IntegerImageType::New(); + + voxelImage->SetRegions(inputImage->GetLargestPossibleRegion().GetSize()); + voxelImage->SetSpacing(inputImage->GetSpacing()); + voxelImage->SetOrigin(inputImage->GetOrigin()); + voxelImage->Allocate(); + + //Voxel iterators + itk::ImageRegionIterator it_inputImage(inputImage, inputImage->GetLargestPossibleRegion()); + itk::ImageRegionIterator it_voxelImage(voxelImage, voxelImage->GetLargestPossibleRegion()); + + //Copy the inputImage -> voxelImage + for (it_inputImage.GoToBegin(), it_voxelImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage, ++it_voxelImage) + { + it_voxelImage.Value() = it_inputImage.Value(); + } + + //Neighborhood Iterator + typedef itk::NeighborhoodIterator< IntegerImageType > NeighborhoodIteratorType; + typename NeighborhoodIteratorType::RadiusType radius; + radius.Fill(1); + + //Counter for voxels with value 1 + mitk::RegionVoxelCounter counter; + counter.SetImage(voxelImage); + counter.SetRegion(voxelImage->GetLargestPossibleRegion()); + + int numberVoxels = counter.VoxelWithValue(1); + + //Get numberNodes with SpinBox + int numberNodes(0); + numberNodes = m_Controls.spinBoxNumberNodes->value(); + + //WARNINGS + if (numberNodes > numberVoxels ) + { + QMessageBox::information( NULL, "Smaller Number of Nodes", "The number of nodes is greater than the number of voxels. Please choose a smaller number!"); + return; + } + + if (m_Controls.checkBoxMerging->isChecked() && m_Controls.radioButtonNumberParcels->isChecked()) + { + int numberParcels = m_Controls.spinBoxNumberParcels->value(); + if (numberNodesisChecked() && m_Controls.radioButtonSmallestParcel->isChecked()) + { + int sizeSmallestParcel = m_Controls.spinBoxSmallestParcel->value(); + if (sizeSmallestParcel > numberVoxels ) + { + QMessageBox::information( NULL, "Smaller Size", "The size of the smallest parcel is greater than the number of voxels. Please choose a smaller size!"); + return; + } + } + + //Get a RandomParcellationGenerator to generate the parcels + mitk::RandomParcellationGenerator generator; + generator.SetImage(voxelImage); + generator.SetNumberNodes(numberNodes); + + //Chooses random initial voxels, with which we can start the parcellation growth + generator.GetRandomSeedVoxels(); + //Now we add all the voxels (which share a face with one of the voxels of a region) to a region, particular constraints have to be fulfilled + generator.ParcelGrowthOverFaces(); + //Because of the constraints or the position of some voxels we now add voxels to the regions which just share an edge or vertex with one region + generator.FillOverEdgeOrVertex(); + //Isolated voxels also have to be allocated to the regions + generator.AllocateIsolatedVoxels(); + + //Show the sizeOfRegions in the window + MITK_DEBUG << "Without merging we get the following size of regions: " << endl; + generator.ShowSizeOfRegions(); + + //Check if the Merge-Buttons are chosen + int newNumberNodes; + + if (m_Controls.checkBoxMerging->isChecked()) + { + int givenSizeOfSmallestRegion(0); + int desiredNumberOfParcels(0); + int givenSizeOfSmallestRegionBeginning = numberVoxels; + bool mergingWithNumberParcels(false); + bool mergingWithSmallestParcel(false); + bool justMergeSmallParcels(false); + + if (m_Controls.radioButtonSmallestParcel->isChecked() ) + { + mergingWithSmallestParcel = true; + givenSizeOfSmallestRegionBeginning = m_Controls.spinBoxSmallestParcel->value(); + if( m_Controls.checkBoxJustMergeSmallParcels-> isChecked() ) + { + //Spinbox: How many voxels should the smallest parcel have? + givenSizeOfSmallestRegion = m_Controls.spinBoxSmallestParcel->value(); + justMergeSmallParcels = true; + } + else + { + givenSizeOfSmallestRegion = numberVoxels; + } + } + else if (m_Controls.radioButtonNumberParcels->isChecked()) + { + givenSizeOfSmallestRegion = numberVoxels; + desiredNumberOfParcels = m_Controls.spinBoxNumberParcels->value(); + mergingWithNumberParcels = true; + } + + //Merge parcels according to a costfunction + generator.SetVariablesForMerging(givenSizeOfSmallestRegion, desiredNumberOfParcels, givenSizeOfSmallestRegionBeginning); + generator.SetBoolsForMerging(mergingWithNumberParcels, mergingWithSmallestParcel, justMergeSmallParcels); + newNumberNodes = generator.MergeParcels(); + + MITK_DEBUG << "After merging we get the following size of regions:" << endl; + generator.ShowSizeOfRegions(); + } + + //Show NumberOfNodes on the GUI + if (m_Controls.checkBoxMerging->isChecked()) //merging was used + { + ShowNumberOfNodes(newNumberNodes); + } + else + { + ShowNumberOfNodes(numberNodes); + } + + //Change the values of the nodes, such that no gaps exist and the values starts with 1 + generator.SetAppropriateValues(); + + //Get a new data node which contains the random parcellation + mitk::Image::Pointer mitkRandomVoxelImage = mitk::ImportItkImage( voxelImage ); + mitk::DataNode::Pointer newRandomVoxelImageNode = mitk::DataNode::New(); + newRandomVoxelImageNode->SetData(mitkRandomVoxelImage); + newRandomVoxelImageNode->SetProperty(PROPERTYNAME.c_str(), + mitk::StringProperty::New(m_NAMEFORRANDOMVOXELIMAGE)); + newRandomVoxelImageNode->SetProperty(PROPERTYOPACITY.c_str(), + mitk::FloatProperty::New(1.0)); + this->GetDefaultDataStorage()->Add( newRandomVoxelImageNode ); + + return; +} + +void QmitkRandomParcellationView::ShowNumberOfNodes(int numberNodes) +{ + std::string string = "Number of nodes: "; + std::string stringNumberNodes; + std::ostringstream convert; + convert << numberNodes; + stringNumberNodes = convert.str(); + string += stringNumberNodes; + QString textNumberNodes = QString::fromStdString(string); + m_Controls.labelNumberNodes->setText(textNumberNodes); +} diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkRandomParcellationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkRandomParcellationView.h new file mode 100644 index 0000000000..684bae40c9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkRandomParcellationView.h @@ -0,0 +1,101 @@ +/*=================================================================== + +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 RandomParcellationView_h +#define RandomParcellationView_h + +#include + +#include + +#include "ui_QmitkRandomParcellationViewControls.h" + +#include + +#include + +//To use pair +#include + + +/** +\brief QmitkRandomParcellationView for GUI Interactions +\sa QmitkFunctionality +\ingroup ${plugin_target}_internal +*/ +class QmitkRandomParcellationView : public QmitkFunctionality +{ + Q_OBJECT + +public: + static const std::string VIEW_ID; + virtual void CreateQtPartControl(QWidget *parent); + + /** \brief Interaction with GUI and mitkRandomParcellationGenerator to get random parcels.*/ + template + void GetRandomParcels( itk::Image* ); + + /** \brief Method to set the default data storage.*/ + virtual void SetDataStorage(mitk::DataStorage* dataStorage) + { + m_DataStorage = dataStorage; + } + + protected slots: + + /** \brief Called when the user clicks the GUI button*/ + void SelectRandomNodes(); + + /** \brief Called when the user checks the GUI checkbox*/ + void OnMergingCheckboxChanged(int state); + + /** \brief Called when the user ckecks the GUI radio button*/ + void OnRadioButtonNumberParcelsChanged(int state); + + /** \brief Called when the user ckecks the GUI radio button*/ + void OnRadioButtonSmallestParcelChanged(int state); + +protected: + + QmitkStdMultiWidget* m_MultiWidget; + + mitk::DataStorage* m_DataStorage; + + //to save an itk image + mitk::DataNode::Pointer m_InputImageNode; + + /** \brief Shows the number of voxels with value one on the GUI*/ + template + void ShowNumberOfVoxels( itk::Image * inputImage); + + /** \brief Shows the number of nodes on the GUI (may have changed after merging)*/ + void ShowNumberOfNodes(int numberNodes); + + virtual void SetFocus(); + + /** \brief called by QmitkFunctionality when DataManager's selection has changed*/ + virtual void OnSelectionChanged(std::vector nodes); + + Ui::QmitkRandomParcellationViewControls m_Controls; + + static const std::string PROPERTYNAME; + static const std::string PROPERTYOPACITY; + static const std::string m_NAMEFORRANDOMVOXELIMAGE; + +}; + +#endif // RandomParcellationView_h diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkRandomParcellationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkRandomParcellationViewControls.ui new file mode 100644 index 0000000000..e3bfb6b02a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkRandomParcellationViewControls.ui @@ -0,0 +1,247 @@ + + + QmitkRandomParcellationViewControls + + + true + + + + 0 + 0 + 547 + 517 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + QLabel { color: rgb(255, 0, 0) } + + + Please select an image! + + + + + + + true + + + Nodes + + + false + + + + + + true + + + Choose the number of nodes: + + + + + + + 1 + + + 5000 + + + + + + + + + + true + + + Merging + + + + + + Merging on + + + + + + + false + + + QFrame::StyledPanel + + + QFrame::Raised + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + According to the number of parcels + + + + + + + false + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Number of Parcels: + + + + + + + 1 + + + 5000 + + + + + + + + + + According to the size of parcels + + + + + + + false + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Size of the smallest parcel: + + + + + + + 2 + + + 100000 + + + + + + + Just merge small parcels + + + + + + + + + + + + + + + + false + + + Do image processing + + + Select random nodes + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Counting + + + + + + Number of voxels with value 1: + + + + + + + Number of nodes: + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp index c2db49d785..b914d02253 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp @@ -1,89 +1,91 @@ /*=================================================================== 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. ===================================================================*/ #include "mitkPluginActivator.h" #include #include "src/internal/QmitkDiffusionImagingPublicPerspective.h" #include "src/internal/QmitkQBallReconstructionView.h" #include "src/internal/QmitkPreprocessingView.h" #include "src/internal/QmitkDiffusionDicomImportView.h" #include "src/internal/QmitkDiffusionQuantificationView.h" #include "src/internal/QmitkTensorReconstructionView.h" #include "src/internal/QmitkControlVisualizationPropertiesView.h" #include "src/internal/QmitkODFDetailsView.h" #include "src/internal/QmitkGibbsTrackingView.h" #include "src/internal/QmitkStochasticFiberTrackingView.h" #include "src/internal/QmitkFiberProcessingView.h" //#include "src/internal/QmitkFiberBundleDeveloperView.h" #include "src/internal/QmitkPartialVolumeAnalysisView.h" #include "src/internal/QmitkIVIMView.h" #include "src/internal/QmitkTractbasedSpatialStatisticsView.h" #include "src/internal/QmitkTbssSkeletonizationView.h" #include "src/internal/QmitkStreamlineTrackingView.h" #include "src/internal/Connectomics/QmitkConnectomicsDataView.h" #include "src/internal/Connectomics/QmitkConnectomicsNetworkOperationsView.h" #include "src/internal/Connectomics/QmitkConnectomicsStatisticsView.h" +#include "src/internal/Connectomics/QmitkRandomParcellationView.h" #include "src/internal/QmitkOdfMaximaExtractionView.h" #include "src/internal/QmitkFiberfoxView.h" #include "src/internal/QmitkFiberExtractionView.h" #include "src/internal/QmitkFieldmapGeneratorView.h" #include "src/internal/QmitkDiffusionRegistrationView.h" #include "src/internal/QmitkDenoisingView.h" namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionImagingPublicPerspective, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkQBallReconstructionView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPreprocessingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionDicomImport, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionQuantificationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkTensorReconstructionView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkControlVisualizationPropertiesView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkODFDetailsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkGibbsTrackingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkStochasticFiberTrackingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberProcessingView, context) // BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberBundleDeveloperView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPartialVolumeAnalysisView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkIVIMView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkTractbasedSpatialStatisticsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkTbssSkeletonizationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkConnectomicsDataView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkConnectomicsNetworkOperationsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkConnectomicsStatisticsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkStreamlineTrackingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkOdfMaximaExtractionView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberfoxView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberExtractionView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFieldmapGeneratorView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionRegistrationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDenoisingView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkRandomParcellationView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_diffusionimaging, mitk::PluginActivator)