itk中的数据翻转算法

本文继续带大家了解itk,虽然数据翻转通常就是用来看一看(其实在DICOM浏览器中的图像翻转并不是这个思路,关键词:camera),但还是要深入了解下itk在翻转中的实现方法,我猜是矩阵变换。

itkFlipImageFilter (翻转)
实现代码:
itk::FixedArray<bool,2>flipAxes;
flipAxes[0]=false;
flipAxes[1]=true;
typedef itk::FlipImageFilter<ImageType>FlipImageFilterType;
FlipImageFilterType::PointerflipFilter=FlipImageFilterType::New();
flipFilter->SetInput(input_data);
//flipFilter->SetFlipAboutOrigin(bool);
/*
true:以图像原点翻转
false:以图像中心翻转
*/
flipFilter->SetFlipAxes(flipAxes);
/*
itkFixedArray:沿着哪个坐标轴翻转
*/
flipFilter->Updata();
1.构建输出数据的信息:这是到目前为止最长的一个GenerateOutputInformation,因为比起输入图像来,输出图像的信息有了一些改变。  
template <class TImage>
void
FlipImageFilter<TImage>
::GenerateOutputInformation()
{
  // call the superclass's implementation of this method 大赞超类!
  Superclass::GenerateOutputInformation();

  // get pointers to the input and output 获得输入和输出的指针
  InputImagePointer inputPtr = 
    const_cast< TImage * >( this->GetInput() );
  OutputImagePointer outputPtr = this->GetOutput();

  if( !inputPtr || !outputPtr ) //防爆安全代码
    {
    return;
    }
//获得输入数据的各种信息
  const typename TImage::DirectionType& inputDirection = inputPtr->GetDirection();
  const typename TImage::SizeType& inputSize =
    inputPtr->GetLargestPossibleRegion().GetSize();
  const typename TImage::IndexType& inputStartIndex =
    inputPtr->GetLargestPossibleRegion().GetIndex();

  typename TImage::PointType outputOrigin;
  typename TImage::IndexType newIndex = inputStartIndex;

  unsigned int j;
//看到没?翻转矩阵~!!哈哈,我猜就是。
  typename TImage::DirectionType flipMatrix;
  flipMatrix.SetIdentity();

  // Need the coordinate of the pixel that will become the first pixel
  // and need a matrix to model the flip
  for ( j = 0; j < ImageDimension; j++ )
    {
    if ( m_FlipAxes[j] )
      {
      // If flipping the axis, then we need to know the last pixel in
      // that dimension
//由于是翻转,直接倒着数像素
      newIndex[j] += (inputSize[j] - 1);

      // What we really want is the index padded out past this point
      // by the amount the start index is from [0,0,0] (because the
      // output regions have the same index layout as the input
      // regions)
      newIndex[j] += inputStartIndex[j];

      // Only flip the directions if we are NOT flipping about the
      // origin (when flipping about the origin, the pixels are
      // ordered in the same direction as the input directions. when
      // NOT flipping about the origin, the pixels traverse space in
      // the opposite direction. when flipping about the origin,
      // increasing indices traverse space in the same direction as
      // the original data.).
      if (!m_FlipAboutOrigin)
        {
        flipMatrix[j][j] = -1.0;
        }
      }
    }

  inputPtr->TransformIndexToPhysicalPoint( newIndex, outputOrigin );

  // Finally, flip about the origin if needed   
  if (m_FlipAboutOrigin)//默认true
    {
    for ( j = 0; j < ImageDimension; j++ )
      {
      if ( m_FlipAxes[j] )
        {
        outputOrigin[j] *= -1;//输出的原点
        }
      }
    }
                                           
  outputPtr->SetDirection( inputDirection * flipMatrix );
  outputPtr->SetOrigin( outputOrigin );
}
2.构建输入请求区域:这个也是itk工具包架构的亮点,可以在输入图像中设置一块计算区域。(实际上是通过指向目标区域的索引和面积来实现的)
template <class TImage>
void
FlipImageFilter<TImage>
::GenerateInputRequestedRegion()
{
//...只贴关键部分  
  IndexType inputRequestedIndex;
  unsigned int j;
  for ( j = 0; j < ImageDimension; j++ )
    {
    if ( m_FlipAxes[j] )
      { //重点在这里!!
      inputRequestedIndex[j] =
        2 * outputLargestPossibleIndex[j] 
        + static_cast<IndexValueType>( outputLargestPossibleSize[j] )
        - static_cast<IndexValueType>( outputRequestedSize[j] ) 
        - outputRequestedIndex[j];
      }
    else
      {
      inputRequestedIndex[j] = outputRequestedIndex[j];
      }
    }

  typename TImage::RegionType inputRequestedRegion;
  inputRequestedRegion.SetSize( outputRequestedSize );
  inputRequestedRegion.SetIndex( inputRequestedIndex );

  inputPtr->SetRequestedRegion( inputRequestedRegion );
}

3.计算
template <class TImage>
void
FlipImageFilter<TImage>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
                       int threadId)
{

  unsigned long i;
  unsigned int j;

  // Get the input and output pointers
  InputImageConstPointer inputPtr = this->GetInput();
  OutputImagePointer outputPtr = this->GetOutput();

  // Setup output region iterator
  typedef ImageRegionIteratorWithIndex<TImage> OutputIterator;
  OutputIterator outIt(outputPtr, outputRegionForThread);

  typename TImage::IndexType outputIndex;
  typename TImage::IndexType inputIndex;

  // support progress methods/callbacks
  ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
    
  const typename TImage::SizeType & outputLargestPossibleSize =
    outputPtr->GetLargestPossibleRegion().GetSize();
  const typename TImage::IndexType& outputLargestPossibleIndex =
    outputPtr->GetLargestPossibleRegion().GetIndex();

  IndexValueType offset[ImageDimension];//定义一个偏移量
  for ( j = 0; j < ImageDimension; j++ )
    {
    if ( m_FlipAxes[j] )//体现出定义m_FlipAxes的优势了
      {
      offset[j] = 2 * outputLargestPossibleIndex[j] 
        + static_cast<IndexValueType>( outputLargestPossibleSize[j] ) - 1;
      } 
    }

  // walk the output region, and sample the input image
  for ( i = 0; !outIt.IsAtEnd(); ++outIt, i++ )
    {
    // determine the index of the output pixel 确定输出像素的索引
    outputIndex = outIt.GetIndex();
//确定与此输出像素相关联的输入像素位置。
//这里体现出这个翻转算法的设计思路:将输出像素的索引与输入像素的索引对应起来!
    // determine the input pixel location associated with this output pixel
    for ( j = 0; j < ImageDimension; j++ )
      {
      if ( m_FlipAxes[j] )
        {
        inputIndex[j] = - 1 * outputIndex[j] + offset[j];
        }
      else 
        {
        inputIndex[j] = outputIndex[ j ];
        }
      }
    
    // copy the input pixel to the output
    outIt.Set( inputPtr->GetPixel(inputIndex) );
    progress.CompletedPixel();
    }
}

生命中,总会有为之奋斗的一些东西,或者,人。活着,从来都不是为了自己。
参考文献:
1.https://itk.org/Wiki/ITK/Examples/Images/FlipImageFilter

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值