Skip to content
Snippets Groups Projects
Commit 8324daaf authored by Emmanuel Christophe's avatar Emmanuel Christophe
Browse files

Seam carving

parent b958dcb3
No related branches found
No related tags found
No related merge requests found
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt 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 __otbAddCarvingPathFilter_h
#define __otbAddCarvingPathFilter_h
#include "itkImageAndPathToImageFilter.h"
#include "itkImageSliceConstIteratorWithIndex.h"
#include "itkImageSliceIteratorWithIndex.h"
namespace otb
{
/** \class AddCarvingPathFilter
* \brief This class add pixels given in one path
*
* This filter add pixels found by the otb::ImageToCarvingPathFilter
* thus increasing the image size.
* the image (if Direction is set to 0) or from left to right
* (if direction is set to 1). Pixel value is computed as the average
* between the neighborhood pixels.
*
* This is one component necessary to apply the seam carving algorithm
* published by Shai Avidan, Ariel Shamir,
* Seam Carving for Content-Aware Image Resizing,
* ACM Transactions on Graphics, Volume 26, Number 3,
* SIGGRAPH 2007
*
* \par INPUTS
* The first input is an image, usually, the same one provided to the
* otb::ImageToCarvingPathFilter
* The second input is a path, typically the output of otb::ImageToCarvingPathFilter.
*
* \par OUTPUTS
* The output is an image with a bigger size than the input image. There is one more
* column if direction is 0 and one more line if direction is 1.
*
* \sa ImageToCarvingPathFilter
*
*
* \ingroup PathFilters
* \ingroup ImageFilters
*/
template <class TInputImage, class TInputPath,class TOutputImage>
class ITK_EXPORT AddCarvingPathFilter : public itk::ImageAndPathToImageFilter<TInputImage,TInputPath,TOutputImage>
{
public:
/** Standard class typedefs. */
typedef AddCarvingPathFilter Self;
typedef itk::ImageAndPathToImageFilter<TInputImage,TInputPath,TOutputImage> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(AddCarvingPathFilter, itk::ImageAndPathToImageFilter);
/** Some convenient typedefs. */
typedef TInputImage InputImageType;
typedef typename InputImageType::Pointer InputImagePointer;
typedef typename InputImageType::ConstPointer InputImageConstPointer;
typedef typename InputImageType::RegionType InputImageRegionType;
typedef typename InputImageType::PixelType InputImagePixelType;
typedef TInputPath InputPathType;
typedef typename InputPathType::Pointer InputPathPointer;
typedef typename InputPathType::ConstPointer InputPathConstPointer;
typedef typename InputPathType::InputType InputPathInputType;
typedef typename InputPathType::OutputType InputPathOutputType;
typedef typename InputPathType::IndexType InputPathIndexType;
typedef typename InputPathType::OffsetType InputPathOffsetType;
typedef TOutputImage OutputImageType;
typedef typename OutputImageType::Pointer OutputImagePointer;
typedef typename OutputImageType::ConstPointer OutputImageConstPointer;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef typename OutputImageType::PixelType OutputImagePixelType;
typedef typename OutputImageType::ValueType OutputImageValueType;
// typedef typename itk::ImageRegionConstIterator<InputImageType> InputIteratorType;
// typedef typename itk::ImageRegionIterator<OutputImageType> OutputIteratorType;
typedef typename itk::ImageSliceConstIteratorWithIndex<InputImageType> InputIteratorType;
typedef typename itk::ImageSliceIteratorWithIndex<OutputImageType> OutputIteratorType;
itkSetMacro(Value, OutputImagePixelType);
itkGetConstReferenceMacro(Value, OutputImagePixelType);
/** Set and Get direction value */
itkSetMacro(Direction ,unsigned int);
itkGetConstMacro(Direction ,unsigned int);
virtual void GenerateOutputInformation();
virtual void GenerateInputRequestedRegion();
protected:
AddCarvingPathFilter();
virtual ~AddCarvingPathFilter() {};
virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
virtual void GenerateData();
private:
AddCarvingPathFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
OutputImagePixelType m_Value;
unsigned int m_Direction;
};
} // end namespace otb
#ifndef OTB_MANUAL_INSTANTIATION
#include "otbAddCarvingPathFilter.txx"
#endif
#endif
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt 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 __otbAddCarvingPathFilter_txx
#define __otbAddCarvingPathFilter_txx
#include "otbAddCarvingPathFilter.h"
namespace otb
{
/**
* Constructor
*/
template <class TInputImage, class TInputPath,class TOutputImage>
AddCarvingPathFilter<TInputImage,TInputPath,TOutputImage>
::AddCarvingPathFilter()
{
m_Value = static_cast<OutputImagePixelType>(255.0);
m_Direction = 0;
}
/**
* Main computation method.
*/
template <class TInputImage, class TInputPath,class TOutputImage>
void
AddCarvingPathFilter<TInputImage,TInputPath,TOutputImage>
::GenerateData(void)
{
const InputImageType * inputImage = this->GetInput();
OutputImageType * outputImage = this->GetOutput();
InputPathType * inputPath = static_cast<const InputPathType *>
(this->itk::ProcessObject::GetInput(1));
outputImage->SetBufferedRegion( outputImage->GetRequestedRegion() );
outputImage->Allocate();
InputIteratorType inputIterator(inputImage,
inputImage->GetLargestPossibleRegion());
OutputIteratorType outputIterator(outputImage,
outputImage->GetLargestPossibleRegion());
unsigned int dir0;
unsigned int dir1;
if (m_Direction == 0)
{
dir0=0;
dir1=1;
}
else
{
dir0=1;
dir1=0;
}
inputIterator.SetFirstDirection( dir0 );
inputIterator.SetSecondDirection( dir1 );
inputIterator.GoToBegin();
outputIterator.SetFirstDirection( dir0 );
outputIterator.SetSecondDirection( dir1 );
outputIterator.GoToBegin();
int line=-1;
typename InputImageType::IndexType index;
typename InputPathType::VertexListType::ConstPointer vertexList = inputPath->GetVertexList();
typename InputPathType::VertexListType::ConstIterator pathIterator;
typename InputImageType::IndexType indexToAdd;
typename InputImageType::SizeType inputSize;
inputSize = inputImage->GetLargestPossibleRegion().GetSize();
//go to the end of the path
pathIterator = vertexList->Begin();
while(pathIterator != vertexList->End())
{
++pathIterator;
}
--pathIterator;
while (!outputIterator.IsAtEnd())
{
while (!outputIterator.IsAtEndOfSlice())
{
bool flag = false;
while(!outputIterator.IsAtEndOfLine())
{
index = outputIterator.GetIndex();
if(index[dir1] != line)
{
line = index[dir1];
typename InputImageType::PointType tmpIndex;
inputImage->TransformContinuousIndexToPhysicalPoint(pathIterator.Value(),tmpIndex);
inputImage->TransformPhysicalPointToIndex(tmpIndex,indexToAdd);
--pathIterator;
if(index[dir1] != indexToAdd[dir1])
{
std::cout << "Error : " << index[dir1] << " , " << indexToAdd[dir1] << std::endl;
}
}
if (flag || ((index[dir0] != indexToAdd[dir0]) && (index[dir0] < inputSize[dir0])))
{
outputIterator.Set(inputIterator.Get());
++inputIterator;
}
else
{
// std::cout << "Adding the value at " << outputIterator.GetIndex() << std::endl;
flag = true;
// std::cout << "[" << index[0] << "," << index[1] << "] ";
OutputImagePixelType newValue;
newValue = (--inputIterator).Get();
newValue += (++inputIterator).Get();
newValue /= 2;
// newValue = 0; //TODO just for test
outputIterator.Set(newValue);
}
++outputIterator;
}
if((outputIterator.GetIndex())[dir0] != (inputIterator.GetIndex())[dir0]+1)
{
std::cout << "Error 2: "<< (outputIterator.GetIndex())[dir0] << " , " << (inputIterator.GetIndex())[dir0] << std::endl;
}
inputIterator.NextLine();
outputIterator.NextLine();
}
inputIterator.NextSlice();
outputIterator.NextSlice();
}
}
/**
* Printself Method
*/
template <class TInputImage, class TInputPath,class TOutputImage>
void
AddCarvingPathFilter<TInputImage,TInputPath,TOutputImage>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
os << indent << "Path Value: " << m_Value << std::endl;
}
template <class TInputImage, class TInputPath,class TOutputImage>
void
AddCarvingPathFilter<TInputImage,TInputPath,TOutputImage>
::GenerateOutputInformation()
{
// call the superclass' implementation of this method
Superclass::GenerateOutputInformation();
// get pointers to the input and output
typename Superclass::InputImageConstPointer inputPtr = this->GetInput();
typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
unsigned int dir0;
unsigned int dir1;
if (m_Direction == 0)
{
dir0=0;
dir1=1;
}
else
{
dir0=1;
dir1=0;
}
// we need to compute the output spacing, the output image size, and the
// output image start index
const typename TInputImage::SpacingType&
inputSpacing = inputPtr->GetSpacing();
const typename TInputImage::SizeType& inputSize
= inputPtr->GetLargestPossibleRegion().GetSize();
const typename TInputImage::IndexType& inputStartIndex
= inputPtr->GetLargestPossibleRegion().GetIndex();
typename TOutputImage::SpacingType outputSpacing;
typename TOutputImage::SizeType outputSize;
typename TOutputImage::IndexType outputStartIndex;
for (unsigned int i = 0; i < TOutputImage::ImageDimension; i++)
{
outputSpacing[i] = inputSpacing[i];
outputSize[i] = (unsigned int) (inputSize[i]);
outputStartIndex[i] = inputStartIndex[i];
}
// we remove one column of the image
outputSize[dir0] = inputSize[dir0] + 1;
outputPtr->SetSpacing( outputSpacing );
typename TOutputImage::RegionType outputLargestPossibleRegion;
outputLargestPossibleRegion.SetSize( outputSize );
outputLargestPossibleRegion.SetIndex( outputStartIndex );
outputPtr->SetLargestPossibleRegion( outputLargestPossibleRegion );
}
template <class TInputImage, class TInputPath,class TOutputImage>
void
AddCarvingPathFilter<TInputImage,TInputPath,TOutputImage>
::GenerateInputRequestedRegion()
{
// call the superclass' implementation of this method
Superclass::GenerateInputRequestedRegion();
// get pointers to the input and output
InputImagePointer inputPtr =
const_cast< InputImageType * >( this->GetInput() );
if ( !inputPtr )
{
itkExceptionMacro( << "Input has not been set." );
}
inputPtr->SetRequestedRegion( inputPtr->GetLargestPossibleRegion() );
}
} // end namespace otb
#endif
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt 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 __otbImageToCarvingPathFilter_h
#define __otbImageToCarvingPathFilter_h
#include "otbImageToPathFilter.h"
#include "itkImageSliceConstIteratorWithIndex.h"
namespace otb {
/**
* \class ImageToCarvingPathFilter
* \brief This filter find the minimum energy path of an image.
*
* This filter find the minimum energy path from top to bottom of
* the image (if Direction is set to 0) or from left to right
* (if direction is set to 1).
*
* This is one component necessary to apply the seam carving algorithm
* published by Shai Avidan, Ariel Shamir,
* Seam Carving for Content-Aware Image Resizing,
* ACM Transactions on Graphics, Volume 26, Number 3,
* SIGGRAPH 2007
*
* \par INPUTS
* The input is an image, typically the output of a gradient filter.
*
* \par OUTPUTS
* The output is
* a polyline parametric path comprising one and only one pixel per line
* (resp. column) if direction is 0 (resp. 1).
*
* \sa RemoveCarvingPathFilter
*
* \ingroup PathFilters
* \ingroup ImageFilters
*/
template <class TInputImage, class TOutputPath>
class ITK_EXPORT ImageToCarvingPathFilter
: public ImageToPathFilter<TInputImage, TOutputPath>
{
public:
/** standards typedefs */
typedef ImageToCarvingPathFilter Self;
typedef ImageToPathFilter<TInputImage, TOutputPath> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/// Creation througth the object factory
itkNewMacro(Self);
/// Runtime information
itkTypeMacro(ImageToCarvingPathFilter,ImageToPathFilter);
/// Template parameters typedef
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::InputImagePointerType InputImagePointerType;
typedef typename Superclass::OutputPathType OutputPathType;
typedef typename Superclass::OutputPathPointerType OutputPathPointerType;
typedef typename InputImageType::PixelType PixelType;
/** Set and Get foreground value */
itkSetMacro(ForegroundValue,PixelType);
itkGetConstMacro(ForegroundValue,PixelType);
/** Set and Get direction value */
itkSetMacro(Direction ,unsigned int);
itkGetConstMacro(Direction ,unsigned int);
/** Get EnergyPerPix value */
itkGetConstMacro(EnergyPerPix ,double);
protected:
ImageToCarvingPathFilter();
virtual ~ImageToCarvingPathFilter(){};
virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
virtual void GenerateOutputInformation() {}; //does nothing
virtual void GenerateData();
private:
ImageToCarvingPathFilter(const Self&); // purposely not implemented
void operator=(const Self&); // purposely not implemented
PixelType m_ForegroundValue;
unsigned int m_Direction;
double m_EnergyPerPix;
};
} // end namespace otb
#ifndef OTB_MANUAL_INSTANTIATION
#include "otbImageToCarvingPathFilter.txx"
#endif
#endif
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt 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 _otbImageToCarvingPathFilter_txx
#define _otbImageToCarvingPathFilter_txx
#include "otbImageToCarvingPathFilter.h"
#include "otbMacro.h"
#include "itkConstantPadImageFilter.h"
#include "itkConstShapedNeighborhoodIterator.h"
#include "itkImageRegionConstIterator.h"
#include "itkNumericTraits.h"
#include "itkImageLinearConstIteratorWithIndex.h"
namespace otb
{
/*
* Constructor.
*/
template <class TInputImage, class TOutputPath>
ImageToCarvingPathFilter<TInputImage, TOutputPath>
::ImageToCarvingPathFilter()
{
m_ForegroundValue = PixelType(255);
m_Direction = 0;
m_EnergyPerPix = 0.0;
}
/**
* Main computation method.
*/
template <class TInputImage, class TOutputPath>
void
ImageToCarvingPathFilter<TInputImage, TOutputPath>
::GenerateData(void)
{
const InputImageType * inputImage = this->GetInput();
OutputPathType * outputPath = this->GetOutput();
typedef itk::ImageSliceConstIteratorWithIndex
<InputImageType> IteratorType;
typedef itk::NeighborhoodIterator< InputImageType >
NeighborhoodIteratorType;
IteratorType it(inputImage,
inputImage->GetLargestPossibleRegion());
it.GoToBegin();
PixelType maxValue = itk::NumericTraits< PixelType >::max();
typename InputImageType::Pointer energyImage = InputImageType::New();
energyImage->SetRegions(inputImage-> GetLargestPossibleRegion());
energyImage->Allocate();
typename NeighborhoodIteratorType::RadiusType radius;
radius.Fill(1);
NeighborhoodIteratorType neighIt(radius, energyImage,
energyImage-> GetLargestPossibleRegion() );
neighIt.GoToBegin();
unsigned int dir0;
unsigned int dir1;
typename IteratorType::OffsetType UP0;
typename IteratorType::OffsetType UP1;
typename IteratorType::OffsetType UP2;
typename IteratorType::OffsetType NEXT;
if (m_Direction == 0)
{
dir0=0;
dir1=1;
const typename IteratorType::OffsetType LEFT ={{-1,0}};
const typename IteratorType::OffsetType RIGHT ={{1,0}};
const typename IteratorType::OffsetType UP ={{0,-1}};
const typename IteratorType::OffsetType DOWN ={{0,1}};
const typename IteratorType::OffsetType LEFTUP ={{-1,-1}};
const typename IteratorType::OffsetType RIGHTDOWN ={{1,1}};
const typename IteratorType::OffsetType RIGHTUP ={{1,-1}};
const typename IteratorType::OffsetType LEFTDOWN ={{-1,1}};
const typename IteratorType::OffsetType CENTER ={{0,0}};
UP0 = LEFTUP;
UP1 = UP;
UP2 = RIGHTUP;
NEXT = DOWN;
}
else
{
dir0=1;
dir1=0;
const typename IteratorType::OffsetType LEFT ={{-1,0}};
const typename IteratorType::OffsetType RIGHT ={{1,0}};
const typename IteratorType::OffsetType UP ={{0,-1}};
const typename IteratorType::OffsetType DOWN ={{0,1}};
const typename IteratorType::OffsetType LEFTUP ={{-1,-1}};
const typename IteratorType::OffsetType RIGHTDOWN ={{1,1}};
const typename IteratorType::OffsetType RIGHTUP ={{1,-1}};
const typename IteratorType::OffsetType LEFTDOWN ={{-1,1}};
const typename IteratorType::OffsetType CENTER ={{0,0}};
UP0 = LEFTUP;
UP1 = LEFT;
UP2 = LEFTDOWN;
NEXT = RIGHT;
}
/** Compute the energy image top-down or left-right
* with cumulative energy (dynamic programming first step) */
it.SetFirstDirection( dir0 );
it.SetSecondDirection( dir1 );
it.GoToBegin(); neighIt.GoToBegin();
while (!it.IsAtEnd())
{
while (!it.IsAtEndOfSlice())
{
while(!it.IsAtEndOfLine())
{
neighIt.SetLocation(it.GetIndex());//TODO bad for performances... find a better option
// this is really about 20% of total processing time !!!
PixelType min = maxValue;
bool isInside = false;
bool flag = false;
if (neighIt.GetPixel(UP0, isInside) < min)
{
if (isInside)
{
min=neighIt.GetPixel(UP0);
flag = true;
}
}
if (neighIt.GetPixel(UP1, isInside) < min)
{
if (isInside)
{
min=neighIt.GetPixel(UP1);
flag = true;
}
}
if (neighIt.GetPixel(UP2, isInside) < min)
{
if (isInside)
{
min=neighIt.GetPixel(UP2);
flag = true;
}
}
if (!flag) //no previous value
{
min = 0;
}
PixelType newValue = it.Get() + min;
neighIt.SetCenterPixel(newValue);
++it;
}
it.NextLine();
}
it.NextSlice();
}
/** Follow the minima bottom-up or right-left
* (dynamic programming second step) */
//find the starting point to follow on the last line
typedef itk::ImageLinearConstIteratorWithIndex< InputImageType >
LinearIteratorType;
LinearIteratorType LinIt(energyImage,
energyImage->GetLargestPossibleRegion());
LinIt.SetDirection(dir0);
LinIt.GoToReverseBegin();
typedef typename InputImageType::IndexType IndexType;
PixelType min = maxValue;
IndexType indexToAdd;
while(!LinIt.IsAtReverseEndOfLine())
{
if(LinIt.Get()<min)
{
min=LinIt.Get();
indexToAdd=LinIt.GetIndex();
}
--LinIt;
}
outputPath->AddVertex(indexToAdd);
m_EnergyPerPix = ((double) min)/ (inputImage->GetLargestPossibleRegion().GetSize())[dir1];
//follow the min
neighIt.SetLocation(indexToAdd);
bool flag=true;
while (flag)
{
flag=false;
PixelType min = maxValue;
IndexType indexToAdd;
bool isInside = false;
if (neighIt.GetPixel(UP0, isInside) < min)
{
if (isInside)
{
min=neighIt.GetPixel(UP0);
indexToAdd = neighIt.GetIndex(UP0);
flag = true;
}
}
if (neighIt.GetPixel(UP1, isInside) < min)
{
if (isInside)
{
min=neighIt.GetPixel(UP1);
indexToAdd = neighIt.GetIndex(UP1);
flag = true;
}
}
if (neighIt.GetPixel(UP2, isInside) < min)
{
if (isInside)
{
min=neighIt.GetPixel(UP2);
indexToAdd = neighIt.GetIndex(UP2);
flag = true;
}
}
if (flag)
{
outputPath->AddVertex(indexToAdd);
neighIt.SetLocation(indexToAdd);
}
}
}
template <class TInputImage, class TOutputPath>
void
ImageToCarvingPathFilter<TInputImage, TOutputPath>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os,indent);
os << "Foreground value : "<<m_ForegroundValue<<std::endl;
}
} // end namespace otb
#endif
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt 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 __otbRemoveCarvingPathFilter_h
#define __otbRemoveCarvingPathFilter_h
#include "itkImageAndPathToImageFilter.h"
#include "itkImageSliceConstIteratorWithIndex.h"
#include "itkImageSliceIteratorWithIndex.h"
namespace otb
{
/** \class RemoveCarvingPathFilter
* \brief This class remove pixels given in one path
*
*
*
* This filter remove pixels found by the otb::ImageToCarvingPathFilter
* thus decreasing the image size.
* the image (if Direction is set to 0) or from left to right
* (if direction is set to 1).
*
* This is one component necessary to apply the seam carving algorithm
* published by Shai Avidan, Ariel Shamir,
* Seam Carving for Content-Aware Image Resizing,
* ACM Transactions on Graphics, Volume 26, Number 3,
* SIGGRAPH 2007
*
* \par INPUTS
* The first input is an image, usually, the same one provided to the
* otb::ImageToCarvingPathFilter
* The second input is a path, typically the output of otb::ImageToCarvingPathFilter.
*
* \par OUTPUTS
* The output is an image with a smaller size than the input image. There is one less
* column if direction is 0 and one less line if direction is 1.
*
* \sa ImageToCarvingPathFilter
*
*
* \ingroup PathFilters
* \ingroup ImageFilters
*/
template <class TInputImage, class TInputPath,class TOutputImage>
class ITK_EXPORT RemoveCarvingPathFilter : public itk::ImageAndPathToImageFilter<TInputImage,TInputPath,TOutputImage>
{
public:
/** Standard class typedefs. */
typedef RemoveCarvingPathFilter Self;
typedef itk::ImageAndPathToImageFilter<TInputImage,TInputPath,TOutputImage> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(RemoveCarvingPathFilter, itk::ImageAndPathToImageFilter);
/** Some convenient typedefs. */
typedef TInputImage InputImageType;
typedef typename InputImageType::Pointer InputImagePointer;
typedef typename InputImageType::ConstPointer InputImageConstPointer;
typedef typename InputImageType::RegionType InputImageRegionType;
typedef typename InputImageType::PixelType InputImagePixelType;
typedef TInputPath InputPathType;
typedef typename InputPathType::Pointer InputPathPointer;
typedef typename InputPathType::ConstPointer InputPathConstPointer;
typedef typename InputPathType::InputType InputPathInputType;
typedef typename InputPathType::OutputType InputPathOutputType;
typedef typename InputPathType::IndexType InputPathIndexType;
typedef typename InputPathType::OffsetType InputPathOffsetType;
typedef TOutputImage OutputImageType;
typedef typename OutputImageType::Pointer OutputImagePointer;
typedef typename OutputImageType::ConstPointer OutputImageConstPointer;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef typename OutputImageType::PixelType OutputImagePixelType;
typedef typename OutputImageType::ValueType OutputImageValueType;
// typedef typename itk::ImageRegionConstIterator<InputImageType> InputIteratorType;
// typedef typename itk::ImageRegionIterator<OutputImageType> OutputIteratorType;
typedef typename itk::ImageSliceConstIteratorWithIndex<InputImageType> InputIteratorType;
typedef typename itk::ImageSliceIteratorWithIndex<OutputImageType> OutputIteratorType;
itkSetMacro(Value, OutputImagePixelType);
itkGetConstReferenceMacro(Value, OutputImagePixelType);
/** Set and Get direction value */
itkSetMacro(Direction ,unsigned int);
itkGetConstMacro(Direction ,unsigned int);
virtual void GenerateOutputInformation();
protected:
RemoveCarvingPathFilter();
virtual ~RemoveCarvingPathFilter() {};
virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
virtual void GenerateData();
private:
RemoveCarvingPathFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
OutputImagePixelType m_Value;
unsigned int m_Direction;
};
} // end namespace otb
#ifndef OTB_MANUAL_INSTANTIATION
#include "otbRemoveCarvingPathFilter.txx"
#endif
#endif
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt 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 __otbRemoveCarvingPathFilter_txx
#define __otbRemoveCarvingPathFilter_txx
#include "otbRemoveCarvingPathFilter.h"
namespace otb
{
/**
* Constructor
*/
template <class TInputImage, class TInputPath,class TOutputImage>
RemoveCarvingPathFilter<TInputImage,TInputPath,TOutputImage>
::RemoveCarvingPathFilter()
{
m_Value = static_cast<OutputImagePixelType>(255.0);
m_Direction = 0;
}
/**
* Main computation method.
*/
template <class TInputImage, class TInputPath,class TOutputImage>
void
RemoveCarvingPathFilter<TInputImage,TInputPath,TOutputImage>
::GenerateData(void)
{
const InputImageType * inputImage = this->GetInput();
OutputImageType * outputImage = this->GetOutput();
InputPathType * inputPath = static_cast<const InputPathType *>
(this->itk::ProcessObject::GetInput(1));
outputImage->SetBufferedRegion( outputImage->GetRequestedRegion() );
outputImage->Allocate();
InputIteratorType inputIterator(inputImage,
inputImage->GetLargestPossibleRegion());
OutputIteratorType outputIterator(outputImage,
outputImage->GetLargestPossibleRegion());
unsigned int dir0;
unsigned int dir1;
if (m_Direction == 0)
{
dir0=0;
dir1=1;
}
else
{
dir0=1;
dir1=0;
}
inputIterator.SetFirstDirection( dir0 );
inputIterator.SetSecondDirection( dir1 );
inputIterator.GoToBegin();
outputIterator.SetFirstDirection( dir0 );
outputIterator.SetSecondDirection( dir1 );
outputIterator.GoToBegin();
int line=-1;
typename InputImageType::IndexType index;
typename InputPathType::VertexListType::ConstPointer vertexList = inputPath->GetVertexList();
typename InputPathType::VertexListType::ConstIterator pathIterator;
typename InputImageType::IndexType indexToRemove;
//go to the end of the path
pathIterator = vertexList->Begin();
while(pathIterator != vertexList->End())
{
++pathIterator;
}
--pathIterator;
while (!inputIterator.IsAtEnd())
{
while (!inputIterator.IsAtEndOfSlice())
{
while(!inputIterator.IsAtEndOfLine())
{
index = inputIterator.GetIndex();
if(index[dir1] != line)
{
line = index[dir1];
typename InputImageType::PointType tmpIndex;
inputImage->TransformContinuousIndexToPhysicalPoint(pathIterator.Value(),tmpIndex);
inputImage->TransformPhysicalPointToIndex(tmpIndex,indexToRemove);
--pathIterator;
if(index[dir1] != indexToRemove[dir1])
{
std::cout << "Error!!!" << std::endl;
}
}
if (index[dir0] != indexToRemove[dir0])
{
outputIterator.Set(inputIterator.Get());
++outputIterator;
}
++inputIterator;
}
inputIterator.NextLine();
outputIterator.NextLine();
}
inputIterator.NextSlice();
outputIterator.NextSlice();
}
}
/**
* Printself Method
*/
template <class TInputImage, class TInputPath,class TOutputImage>
void
RemoveCarvingPathFilter<TInputImage,TInputPath,TOutputImage>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
os << indent << "Path Value: " << m_Value << std::endl;
}
template <class TInputImage, class TInputPath,class TOutputImage>
void
RemoveCarvingPathFilter<TInputImage,TInputPath,TOutputImage>
::GenerateOutputInformation()
{
// call the superclass' implementation of this method
Superclass::GenerateOutputInformation();
// get pointers to the input and output
typename Superclass::InputImageConstPointer inputPtr = this->GetInput();
typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
unsigned int dir0;
unsigned int dir1;
if (m_Direction == 0)
{
dir0=0;
dir1=1;
}
else
{
dir0=1;
dir1=0;
}
// we need to compute the output spacing, the output image size, and the
// output image start index
const typename TInputImage::SpacingType&
inputSpacing = inputPtr->GetSpacing();
const typename TInputImage::SizeType& inputSize
= inputPtr->GetLargestPossibleRegion().GetSize();
const typename TInputImage::IndexType& inputStartIndex
= inputPtr->GetLargestPossibleRegion().GetIndex();
typename TOutputImage::SpacingType outputSpacing;
typename TOutputImage::SizeType outputSize;
typename TOutputImage::IndexType outputStartIndex;
for (unsigned int i = 0; i < TOutputImage::ImageDimension; i++)
{
outputSpacing[i] = inputSpacing[i];
outputSize[i] = (unsigned int) (inputSize[i]);
outputStartIndex[i] = inputStartIndex[i];
}
// we remove one column of the image
outputSize[dir0] = inputSize[dir0] - 1;
outputPtr->SetSpacing( outputSpacing );
typename TOutputImage::RegionType outputLargestPossibleRegion;
outputLargestPossibleRegion.SetSize( outputSize );
outputLargestPossibleRegion.SetIndex( outputStartIndex );
outputPtr->SetLargestPossibleRegion( outputLargestPossibleRegion );
}
} // end namespace otb
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment