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()