4 #include <itkImageRegionConstIterator.h>     5 #include <itkImageRegionIteratorWithIndex.h>     7 #include <itkExpNegativeImageFilter.h>     8 #include <itkDanielssonDistanceMapImageFilter.h>     9 #include <itkGrayscaleDilateImageFilter.h>    10 #include <itkBinaryBallStructuringElement.h>    11 #include <itkPoolMultiThreader.h>    16 template <
class PixelType, 
unsigned int NDimensions>
    17 std::vector < typename BlockMatchingInitializer<PixelType,NDimensions>::ImageRegionType > &
    26 template <
class PixelType, 
unsigned int NDimensions>
    27 std::vector < typename BlockMatchingInitializer<PixelType,NDimensions>::PointType > &
    33     return m_OutputPositions;
    36 template <
class PixelType, 
unsigned int NDimensions>
    37 std::vector <unsigned int> &
    40     if (m_MaskStartingIndexes.size() == 0)
    43     return m_MaskStartingIndexes;
    46 template <
class PixelType, 
unsigned int NDimensions>
    55         m_ReferenceScalarImages.push_back(tmpPtr);
    56         m_ReferenceScalarImages.back()->DisconnectPipeline();
    60         m_ReferenceVectorImages.push_back(dynamic_cast <VectorImageType *> (refImage));
    61         m_ReferenceVectorImages.back()->DisconnectPipeline();
    65 template <
class PixelType, 
unsigned int NDimensions>
    71         m_GenerationMasks.push_back(mask);
    74 template <
class PixelType, 
unsigned int NDimensions>
    75 itk::ImageBase <NDimensions> *
    79     if (m_ReferenceScalarImages.size() != 0)
    80         return m_ReferenceScalarImages[0];
    82     if (m_ReferenceVectorImages.size() != 0)
    83         return m_ReferenceVectorImages[0];
    88 template <
class PixelType, 
unsigned int NDimensions>
    92     if (val != m_PercentageKept)
    94         m_PercentageKept = val;
    99 template <
class PixelType, 
unsigned int NDimensions>
   103     if (val != m_ScalarVarianceThreshold)
   105         m_ScalarVarianceThreshold = val;
   110 template <
class PixelType, 
unsigned int NDimensions>
   114     if (val != m_OrientedModelVarianceThreshold)
   116         m_OrientedModelVarianceThreshold = val;
   121 template <
class PixelType, 
unsigned int NDimensions>
   125     if (val != m_RequestedRegion)
   127         m_RequestedRegion = val;
   132 template <
class PixelType, 
unsigned int NDimensions>
   136     if (val != m_BlockSpacing)
   138         m_BlockSpacing = val;
   143 template <
class PixelType, 
unsigned int NDimensions>
   147     if (val != m_BlockSize)
   154 template <
class PixelType, 
unsigned int NDimensions>
   158     if (m_GenerationMasks.size() == 0)
   162         wholeMask->Initialize();
   163         wholeMask->SetRegions(m_RequestedRegion);
   164         wholeMask->Allocate();
   165         wholeMask->FillBuffer(1);
   167         m_GenerationMasks.push_back(wholeMask);
   175     m_OutputPositions.clear();
   176     m_MaskStartingIndexes.resize(m_GenerationMasks.size());
   177     for (
unsigned int i = 0;i < m_GenerationMasks.size();++i)
   179         m_MaskStartingIndexes[i] = m_Output.size();
   180         this->ComputeBlocksOnGenerationMask(i);
   186 template <
class PixelType, 
unsigned int NDimensions>
   191     itk::PoolMultiThreader::Pointer threaderBlockGenerator = itk::PoolMultiThreader::New();
   194     this->InitializeThreading(maskIndex,tmpStr);
   196     threaderBlockGenerator->SetNumberOfWorkUnits(this->GetNumberOfThreads());
   197     threaderBlockGenerator->SetSingleMethod(this->ThreadBlockGenerator,tmpStr);
   198     threaderBlockGenerator->SingleMethodExecute();
   201     m_OutputPositions.clear();
   202     unsigned int totalNumberOfBlocks = 0;
   203     unsigned int realNumberOfBlocks = 0;
   205     for (
unsigned int i = 0;i < this->GetNumberOfThreads();++i)
   207         realNumberOfBlocks += tmpStr->
tmpOutput[i].size();
   211     double percentageBlocksKept = (double) realNumberOfBlocks / totalNumberOfBlocks;
   213     if (percentageBlocksKept > m_PercentageKept)
   215         std::vector < std::pair <double, std::pair <PointType, ImageRegionType> > > sortVector;
   216         for (
unsigned int i = 0;i < this->GetNumberOfThreads();++i)
   217             for (
unsigned int j = 0;j < tmpStr->
tmpOutput[i].size();++j)
   220                 sortVector.push_back(std::make_pair(tmpStr->
blocks_variances[i][j],tmpPair));
   223         unsigned int numRemoved = std::floor((1.0 - m_PercentageKept) * totalNumberOfBlocks);
   224         std::partial_sort(sortVector.begin(),sortVector.begin() + numRemoved,sortVector.end(),
pair_comparator());
   226         for (
unsigned int i = numRemoved;i < sortVector.size();++i)
   228             m_Output.push_back(sortVector[i].second.second);
   229             m_OutputPositions.push_back(sortVector[i].second.first);
   234         for (
unsigned int i = 0;i < this->GetNumberOfThreads();++i)
   236             m_Output.insert(m_Output.end(), tmpStr->
tmpOutput[i].begin(), tmpStr->
tmpOutput[i].end());
   237             m_OutputPositions.insert(m_OutputPositions.end(), tmpStr->
blocks_positions[i].begin(),
   245 template <
class PixelType, 
unsigned int NDimensions>
   252     minIndex = m_RequestedRegion.GetIndex() + m_RequestedRegion.GetSize();
   253     maxIndex = m_RequestedRegion.GetIndex();
   254     typedef itk::ImageRegionIteratorWithIndex <MaskImageType> MaskIteratorType;
   255     MaskIteratorType maskItr(m_GenerationMasks[maskIndex],m_RequestedRegion);
   257     while (!maskItr.IsAtEnd())
   259         if (maskItr.Get() != 0)
   261             tmpIndex = maskItr.GetIndex();
   262             for (
unsigned int i = 0;i < NDimensions;++i)
   264                 if (tmpIndex[i] < minIndex[i])
   265                     minIndex[i] = tmpIndex[i];
   267                 if (tmpIndex[i] > maxIndex[i])
   268                     maxIndex[i] = tmpIndex[i];
   275     for (
unsigned int i = 0;i < NDimensions;++i)
   277         workRegion.SetIndex(i,minIndex[i]);
   278         workRegion.SetSize(i,maxIndex[i] - minIndex[i] + 1);
   284     std::vector <unsigned int> totalNbBlocks(NDimensions);
   287     for (
unsigned int i = 0;i < NDimensions;++i)
   289         totalNbBlocks[i] = std::floor((
double)(workRegion.GetSize()[i] / this->GetBlockSpacing()) + 0.5);
   290         if (totalNbBlocks[i] < 1)
   291             totalNbBlocks[i] = 1;
   293         unsigned int spaceRequired = workRegion.GetSize()[i] - (totalNbBlocks[i] - 1) * this->GetBlockSpacing() - 1;
   295         workStr->
blockStartOffsets[i] = workRegion.GetIndex()[i] + std::floor(spaceRequired / 2.0);
   298     unsigned int nb_blocks_per_thread = (
unsigned int) std::floor((
double)(totalNbBlocks[NDimensions-1] / this->GetNumberOfThreads()));
   299     if (nb_blocks_per_thread < 1)
   301         nb_blocks_per_thread = 1;
   302         this->SetNumberOfThreads(totalNbBlocks[NDimensions-1]);
   305     workStr->
startBlocks.resize(this->GetNumberOfThreads());
   306     workStr->
nb_blocks.resize(this->GetNumberOfThreads());
   309     unsigned int currentCount = 0;
   310     for (
unsigned int i = 0;i < this->GetNumberOfThreads();++i)
   312         std::vector <unsigned int> startBlock(NDimensions,0);
   313         startBlock[NDimensions-1] = currentCount;
   316         std::vector <unsigned int> numBlockVec(NDimensions);
   317         for (
unsigned int j = 0;j < NDimensions-1;++j)
   318             numBlockVec[j] = totalNbBlocks[j];
   320         unsigned int numBlocksForThread = nb_blocks_per_thread;
   321         if (numBlocksForThread + currentCount > totalNbBlocks[NDimensions-1])
   322             numBlocksForThread = totalNbBlocks[NDimensions-1] - currentCount;
   325         if (i == this->GetNumberOfThreads()-1)
   326             numBlocksForThread = totalNbBlocks[NDimensions-1] - currentCount;
   328         numBlockVec[NDimensions-1] = numBlocksForThread;
   331         currentCount += numBlocksForThread;
   335     workStr->
tmpOutput.resize(this->GetNumberOfThreads());
   340     for (
unsigned int i = 0;i < this->GetNumberOfThreads();++i)
   349 template <
class PixelType, 
unsigned int NDimensions>
   350 ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION
   354     itk::MultiThreaderBase::WorkUnitInfo *threadArgs = (itk::MultiThreaderBase::WorkUnitInfo *)arg;
   356     unsigned int nbThread = threadArgs->WorkUnitID;
   360     tmpStr->
Filter->RegionBlockGenerator(tmpStr,nbThread);
   362     return ITK_THREAD_RETURN_DEFAULT_VALUE;
   365 template <
class PixelType, 
unsigned int NDimensions>
   369     typename ImageRegionType::IndexType startPosition, blockPosition;
   370     typename ImageRegionType::SizeType blockSize;
   372     ImageRegionType largestRegion = this->GetFirstReferenceImage()->GetLargestPossibleRegion();
   381     unsigned int block_half_size = std::floor ((this->GetBlockSize() - 1) / 2.0);
   383     bool continueLoop = 
true;
   384     std::vector <unsigned int> positionCounter(NDimensions,0);
   388         for (
unsigned int i = 0;i < NDimensions;++i)
   390             blockSize[i] = this->GetBlockSize();
   391             indexPos = workStr->
blockStartOffsets[i] + (workStr->
startBlocks[threadId][i] + positionCounter[i])*this->GetBlockSpacing() - block_half_size;
   392             if (indexPos < largestRegion.GetIndex()[i])
   394                 blockSize[i] += indexPos - largestRegion.GetIndex()[i];
   395                 indexPos = largestRegion.GetIndex()[i];
   397             startPosition[i] = indexPos;
   398             if (startPosition[i] + blockSize[i] > largestRegion.GetIndex()[i] + largestRegion.GetSize()[i])
   399                 blockSize[i] = largestRegion.GetIndex()[i] + largestRegion.GetSize()[i] - startPosition[i];
   402         tmpBlock.SetIndex(startPosition);
   403         tmpBlock.SetSize(blockSize);
   406         if (this->CheckBlockConditions(tmpBlock,blockVar,workStr,threadId))
   408             for (
unsigned int i = 0;i < NDimensions;++i)
   411             if (m_GenerationMasks[workStr->
maskIndex]->GetPixel(blockPosition) == 0)
   413                 continueLoop = this->ProgressCounter(positionCounter,workStr->
nb_blocks[threadId]);
   417             workStr->
tmpOutput[threadId].push_back(tmpBlock);
   420             this->GetFirstReferenceImage()->TransformIndexToPhysicalPoint(blockPosition,blockOrigin);
   424         continueLoop = this->ProgressCounter(positionCounter,workStr->
nb_blocks[threadId]);
   428 template <
class PixelType, 
unsigned int NDimensions>
   433     unsigned int pos = counter.size() - 1;
   435     bool needUpdate = 
false;
   441         if ((counter[pos] == bounds[pos])&&(pos > 0))
   447     } 
while (needUpdate);
   449     if (counter[pos] >= bounds[pos])
   455 template <
class PixelType, 
unsigned int NDimensions>
   459                        unsigned int threadId)
   461     ImageRegionType refRegion = this->GetFirstReferenceImage()->GetLargestPossibleRegion();
   463     for (
unsigned int i = 0;i < NDimensions;++i)
   465         if (refRegion.GetIndex()[i] > region.GetIndex()[i])
   468         if (refRegion.GetIndex()[i] + refRegion.GetSize()[i] < region.GetIndex()[i] + region.GetSize()[i])
   475     for (
unsigned int i = 0;i < m_ReferenceScalarImages.size();++i)
   477         if (!this->CheckScalarVariance(m_ReferenceScalarImages[i],region,tmpVar))
   480         if (tmpVar > blockVariance)
   481             blockVariance = tmpVar;
   484     for (
unsigned int i = 0;i < m_ReferenceVectorImages.size();++i)
   486         if (!this->CheckOrientedModelVariance(i,region,tmpVar,workStr,threadId))
   489         if (tmpVar > blockVariance)
   490             blockVariance = tmpVar;
   497 template <
class PixelType, 
unsigned int NDimensions>
   503     itk::ImageRegionConstIterator <VectorImageType> refItr(refImage,region);
   504     typedef typename VectorImageType::PixelType VectorType;
   506     unsigned int nbPts = 0;
   507     unsigned int vectorSize = refImage->GetNumberOfComponentsPerPixel();
   509     VectorType meanVal(vectorSize);
   511     std::vector <double> blockCovariance(vectorSize, 0.0);
   513     while (!refItr.IsAtEnd())
   515         VectorType tmpVal = refItr.Get();
   526     while (!refItr.IsAtEnd())
   528         VectorType tmpVal = refItr.Get();
   530         for (
unsigned int j = 0;j < vectorSize;++j)
   531             blockCovariance[j] += (tmpVal[j] - meanVal[j]) * (tmpVal[j] - meanVal[j]);
   541     for (
unsigned int j = 0;j < vectorSize;++j)
   543         double tmp = blockCovariance[j] / (nbPts - 1.0);
   544         blockVariance += tmp;
   547     blockVariance /= vectorSize;
   549     if (blockVariance > this->GetOrientedModelVarianceThreshold())
   555 template <
class PixelType, 
unsigned int NDimensions>
   559     itk::ImageRegionConstIterator <ScalarImageType> refItr(refImage,region);
   563     unsigned int nbPts = 0;
   564     while (!refItr.IsAtEnd())
   566         double tmpVal = refItr.Get();
   578     while (!refItr.IsAtEnd())
   580         double tmpVal = refItr.Get();
   581         blockVariance += (meanVal - tmpVal) * (meanVal - tmpVal);
   586     blockVariance /= (nbPts - 1.0);
   588     if (blockVariance > this->GetScalarVarianceThreshold())
 itk::Image< unsigned char, NDimensions > MaskImageType
 
std::vector< std::vector< unsigned int > > nb_blocks
 
std::vector< std::vector< ImageRegionType > > tmpOutput
 
std::vector< std::vector< unsigned int > > startBlocks
 
void RegionBlockGenerator(BlockGeneratorThreadStruct *workStr, unsigned int threadId)
 
virtual bool CheckOrientedModelVariance(unsigned int imageIndex, ImageRegionType ®ion, double &blockVariance, BlockGeneratorThreadStruct *workStr, unsigned int threadId)
 
ScalarImageType::PointType PointType
 
virtual void AddReferenceImage(itk::ImageBase< NDimensions > *refImage)
 
std::vector< unsigned int > totalNumberOfBlocks
 
void SetBlockSize(unsigned int val)
 
std::vector< unsigned int > blockStartOffsets
 
std::vector< PointType > & GetOutputPositions()
 
void SetRequestedRegion(const ImageRegionType &val)
 
ScalarImageType::IndexType IndexType
 
virtual void InitializeThreading(unsigned int maskIndex, BlockGeneratorThreadStruct *&workStr)
 
void SetPercentageKept(double val)
 
bool CheckScalarVariance(ScalarImageType *refImage, ImageRegionType ®ion, double &blockVariance)
 
void ComputeBlocksOnGenerationMask(unsigned int maskIndex)
 
std::vector< std::vector< PointType > > blocks_positions
 
static ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION ThreadBlockGenerator(void *arg)
 
ScalarImageType::RegionType ImageRegionType
 
void AddGenerationMask(MaskImageType *mask)
 
void SetOrientedModelVarianceThreshold(double val)
 
itk::VectorImage< PixelType, NDimensions > VectorImageType
 
itk::Image< PixelType, NDimensions > ScalarImageType
 
std::vector< std::vector< double > > blocks_variances
 
bool ProgressCounter(std::vector< unsigned int > &counter, std::vector< unsigned int > &bounds)
 
std::vector< unsigned int > & GetMaskStartingIndexes()
 
bool CheckBlockConditions(ImageRegionType ®ion, double &blockVariance, BlockGeneratorThreadStruct *workStr, unsigned int threadId)
 
void SetBlockSpacing(unsigned int val)
 
MaskImageType::Pointer MaskImagePointer
 
void SetScalarVarianceThreshold(double val)
 
itk::ImageBase< NDimensions > * GetFirstReferenceImage()
 
std::vector< ImageRegionType > & GetOutput()