📄 itkstatisticsalgorithm.txx
字号:
/*=========================================================================
Program: Insight Segmentation & Registration Toolkit
Module: $RCSfile: itkStatisticsAlgorithm.txx,v $
Language: C++
Date: $Date: 2008-04-29 23:00:07 $
Version: $Revision: 1.24 $
Copyright (c) Insight Software Consortium. All rights reserved.
See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef __itkStatisticsAlgorithm_txx
#define __itkStatisticsAlgorithm_txx
#include "itkStatisticsAlgorithm.h"
#include "itkNumericTraits.h"
namespace itk{
namespace Statistics{
template< class TSize >
inline TSize FloorLog(TSize size)
{
TSize k ;
for (k = 0; size != 1; size >>= 1)
{
++k;
}
return k;
}
/** The endIndex should points one point after the last elements if multiple
* partitionValue exist in the sample the return index will points the middle
* of such values. Implemented following the description of the partition
* algorithm in the QuickSelect entry of the Wikipedia.
* http://en.wikipedia.org/wiki/Selection_algorithm. */
template< class TSubsample >
inline int Partition(TSubsample* sample,
unsigned int activeDimension,
int beginIndex, int endIndex,
const typename TSubsample::MeasurementType partitionValue)
{
typedef typename TSubsample::MeasurementType MeasurementType;
int moveToFrontIndex = beginIndex;
int moveToBackIndex = endIndex-1;
//
// Move to the back all entries whose activeDimension component is equal to
// the partitionValue.
//
while( moveToFrontIndex < moveToBackIndex )
{
//
// Find the first element (from the back) that is in the wrong side of the partition.
//
while( moveToBackIndex >= beginIndex )
{
if( sample->GetMeasurementVectorByIndex(moveToBackIndex)[activeDimension] != partitionValue )
{
break;
}
moveToBackIndex--;
}
//
// Find the first element (from the front) that is in the wrong side of the partition.
//
while( moveToFrontIndex < endIndex )
{
if( sample->GetMeasurementVectorByIndex(moveToFrontIndex)[activeDimension] == partitionValue )
{
break;
}
moveToFrontIndex++;
}
if( moveToFrontIndex < moveToBackIndex )
{
//
// Swap them to place them in the correct side of the partition
//
sample->Swap( moveToBackIndex, moveToFrontIndex );
}
}
//
// Now, ignore the section at the end with all the values equal to the partition value,
// and start swapping entries that are in the wrong side of the partition.
//
moveToFrontIndex = beginIndex;
moveToBackIndex = endIndex-1;
while( moveToFrontIndex < moveToBackIndex )
{
//
// Find the first element (from the back) that is in the wrong side of the partition.
//
while( moveToBackIndex >= beginIndex )
{
if( sample->GetMeasurementVectorByIndex(moveToBackIndex)[activeDimension] < partitionValue )
{
break;
}
moveToBackIndex--;
}
//
// Find the first element (from the front) that is in the wrong side of the partition.
//
while( moveToFrontIndex < endIndex )
{
if( sample->GetMeasurementVectorByIndex(moveToFrontIndex)[activeDimension] > partitionValue )
{
break;
}
moveToFrontIndex++;
}
if( moveToFrontIndex < moveToBackIndex )
{
//
// Swap them to place them in the correct side of the partition
//
sample->Swap( moveToBackIndex, moveToFrontIndex );
}
}
//
// Take all the entries with activeDimension component equal to
// partitionValue, that were placed at the end of the list, and move them to
// the interface between smaller and larger values.
//
int beginOfSectionEqualToPartition = moveToFrontIndex;
moveToBackIndex = endIndex-1;
while( moveToFrontIndex < moveToBackIndex )
{
//
// Find the first element (from the back) that is in the wrong side of the partition.
//
while( moveToBackIndex >= beginIndex )
{
if( sample->GetMeasurementVectorByIndex(moveToBackIndex)[activeDimension] == partitionValue )
{
break;
}
moveToBackIndex--;
}
//
// Find the first element (from the front) that is in the wrong side of the partition.
//
while( moveToFrontIndex < endIndex )
{
if( sample->GetMeasurementVectorByIndex(moveToFrontIndex)[activeDimension] != partitionValue )
{
break;
}
moveToFrontIndex++;
}
if( moveToFrontIndex < moveToBackIndex )
{
//
// Swap them to place them in the correct side of the partition
//
sample->Swap( moveToBackIndex, moveToFrontIndex );
}
}
int endOfSectionEqualToPartition = moveToFrontIndex-1;
int storeIndex = ( beginOfSectionEqualToPartition + endOfSectionEqualToPartition ) / 2;
const MeasurementType pivotValue = sample->GetMeasurementVectorByIndex( storeIndex )[activeDimension];
if( pivotValue != partitionValue )
{
// The partition was done using a value that is not present in the sample.
// Therefore we must now find the largest value of the left section and
// swap it to the boundary between smaller and larger than the
// partitionValue.
for(int kk=beginIndex; kk<storeIndex; kk++)
{
MeasurementType nodeValue = sample->GetMeasurementVectorByIndex( kk )[activeDimension];
MeasurementType boundaryValue = sample->GetMeasurementVectorByIndex( storeIndex )[activeDimension];
if( nodeValue > boundaryValue )
{
sample->Swap(kk, storeIndex) ;
}
}
}
return storeIndex;
}
template< class TValue >
inline TValue MedianOfThree(const TValue a,
const TValue b,
const TValue c)
{
if (a < b) {
if (b < c) {
return b;
}
else if (a < c) {
return c;
}
else {
return a;
}
}
else if (a < c) {
return a ;
}
else if (b < c) {
return c;
}
else {
return b;
}
}
template< class TSample >
inline void FindSampleBound(const TSample* sample,
typename TSample::ConstIterator begin,
typename TSample::ConstIterator end,
typename TSample::MeasurementVectorType &min,
typename TSample::MeasurementVectorType &max)
{
typedef typename TSample::MeasurementVectorSizeType MeasurementVectorSizeType;
const MeasurementVectorSizeType Dimension = sample->GetMeasurementVectorSize();
if( Dimension == 0 )
{
itkGenericExceptionMacro(
<< "Length of a sample's measurement vector hasn't been set.");
}
// Sanity check
MeasurementVectorTraits::Assert( max, Dimension,
"Length mismatch StatisticsAlgorithm::FindSampleBound");
MeasurementVectorTraits::Assert( min, Dimension,
"Length mismatch StatisticsAlgorithm::FindSampleBound");
unsigned int dimension;
typename TSample::MeasurementVectorType temp ;
min = max = temp = begin.GetMeasurementVector() ;
while (true)
{
for (dimension= 0 ; dimension < Dimension ; dimension++)
{
if ( temp[dimension] < min[dimension])
{
min[dimension] = temp[dimension] ;
}
else if (temp[dimension] > max[dimension])
{
max[dimension] = temp[dimension] ;
}
}
++begin ;
if (begin == end)
{
break ;
}
temp = begin.GetMeasurementVector() ;
} // end of while
}
/** The endIndex should points one point after the last elements. */
template< class TSubsample >
inline void
FindSampleBoundAndMean(const TSubsample* sample,
int beginIndex,
int endIndex,
typename TSubsample::MeasurementVectorType &min,
typename TSubsample::MeasurementVectorType &max,
typename TSubsample::MeasurementVectorType &mean)
{
typedef typename TSubsample::MeasurementType MeasurementType ;
typedef typename TSubsample::MeasurementVectorType MeasurementVectorType ;
typedef typename TSubsample::MeasurementVectorSizeType MeasurementVectorSizeType;
const MeasurementVectorSizeType Dimension = sample->GetMeasurementVectorSize();
if( Dimension == 0 )
{
itkGenericExceptionMacro(
<< "Length of a sample's measurement vector hasn't been set.");
}
Array< double > sum( Dimension ) ;
MeasurementVectorSizeType dimension ;
MeasurementVectorType temp;
MeasurementVectorTraits::SetLength( temp, Dimension );
MeasurementVectorTraits::SetLength( mean, Dimension );
min = max = temp = sample->GetMeasurementVectorByIndex(beginIndex) ;
double frequencySum = sample->GetFrequencyByIndex(beginIndex) ;
sum.Fill(0.0) ;
while (true)
{
for (dimension= 0 ; dimension < Dimension ; dimension++)
{
if ( temp[dimension] < min[dimension])
{
min[dimension] = temp[dimension] ;
}
else if (temp[dimension] > max[dimension])
{
max[dimension] = temp[dimension] ;
}
sum[dimension] += temp[dimension] ;
}
++beginIndex ;
if (beginIndex == endIndex)
{
break ;
}
temp = sample->GetMeasurementVectorByIndex(beginIndex) ;
frequencySum += sample->GetFrequencyByIndex(beginIndex) ;
} // end of while
for (unsigned int i = 0 ; i < Dimension ; i++)
{
mean[i] = (MeasurementType)(sum[i] / frequencySum) ;
}
}
/** The endIndex should point one point after the last elements. Note that kth
* is an index in a different scale than [beginIndex,endIndex]. For example,
* it is possible to feed this function with beginIndex=15, endIndex=23, and
* kth=3, since we can ask for the element 3rd in the range [15,23]. */
template< class TSubsample >
inline typename TSubsample::MeasurementType
QuickSelect(TSubsample* sample,
unsigned int activeDimension,
int beginIndex,
int endIndex,
int kth,
typename TSubsample::MeasurementType medianGuess)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -