Commit bb5473e0 authored by Manuel Grizonnet's avatar Manuel Grizonnet

ENH: replace StreamingShrinkImageRegionSplitter by an encapsulation of...

ENH: replace StreamingShrinkImageRegionSplitter by an encapsulation of ImageRegionAdaptativeSplitter
parent 14fd7df4
......@@ -17,6 +17,8 @@
=========================================================================*/
#include "otbStreamingShrinkImageFilter.h"
//encapsulate adaptative splitter
#include "otbImageRegionAdaptativeSplitter.h"
namespace otb
{
......@@ -24,73 +26,96 @@ unsigned int
StreamingShrinkImageRegionSplitter
::GetNumberOfSplits(const RegionType& region, unsigned int requestedNumber)
{
unsigned int theoricalNbPixelPerTile = region.GetNumberOfPixels() / requestedNumber;
unsigned int theoricalTileDimension = static_cast<unsigned int> (vcl_sqrt(static_cast<double>(theoricalNbPixelPerTile)) );
// Take the previous multiple of m_TileSizeAlignment (eventually generate more splits than requested)
m_TileDimension = theoricalTileDimension / m_TileSizeAlignment * m_TileSizeAlignment;
// Minimal tile size is m_TileSizeAlignment * m_TileSizeAlignment
if (m_TileDimension < m_TileSizeAlignment)
//New method
// Set parameters
this->SetImageRegion(region);
this->SetRequestedNumberOfSplits(requestedNumber);
// Check if we need to compute split map again
m_Lock.Lock();
if(!m_IsUpToDate)
{
otbMsgDevMacro(<< "Using the minimal tile size : " << m_TileSizeAlignment << " * " << m_TileSizeAlignment);
m_TileDimension = m_TileSizeAlignment;
// Do so if we need to
this->EstimateSplitMap(requestedNumber);
}
m_Lock.Unlock();
otbMsgDevMacro(<<"Stream vector size " << m_StreamVector.size() << std::endl);
// Return the size of the split map
return m_StreamVector.size();
}
// Use the computed tile size, and generate (m_TileDimension * 1) tiles
const SizeType& regionSize = region.GetSize();
m_SplitsPerDimension[0] = (regionSize[0] + m_TileDimension - 1) / m_TileDimension;
m_SplitsPerDimension[1] = regionSize[1] / m_TileSizeAlignment;
if (m_SplitsPerDimension[1] == 0)
m_SplitsPerDimension[1] = 1;
StreamingShrinkImageRegionSplitter::RegionType
StreamingShrinkImageRegionSplitter
::GetSplit(unsigned int i, unsigned int numberOfPieces, const RegionType& region)
{
// Set parameters
this->SetImageRegion(region);
unsigned int numPieces = 1;
for (unsigned int j = 0; j < ImageDimension; ++j)
// Check if we need to compute split map agagin
m_Lock.Lock();
if(!m_IsUpToDate)
{
numPieces *= m_SplitsPerDimension[j];
// Do so if we need to
this->EstimateSplitMap(numberOfPieces);
}
m_Lock.Unlock();
otbMsgDevMacro(<< "Tile dimension : " << m_TileDimension)
otbMsgDevMacro(<< "Number of splits per dimension : " << m_SplitsPerDimension[0] << " " << m_SplitsPerDimension[1])
return numPieces;
// Return the requested split
return m_StreamVector.at(i);
}
StreamingShrinkImageRegionSplitter::RegionType
void
StreamingShrinkImageRegionSplitter
::GetSplit(unsigned int i, unsigned int numberOfPieces, const RegionType& region)
::EstimateSplitMap(unsigned int numberOfPieces)
{
RegionType splitRegion;
IndexType splitIndex;
// Clear previous split map
m_StreamVector.clear();
// Compute the actual number of splits
unsigned int numPieces = 1;
for (unsigned int j = 0; j < ImageDimension; ++j)
{
numPieces *= m_SplitsPerDimension[j];
}
//Encapsulate adpatative splitter to get a list of streams
//adapted to the tiling scheme
typedef ImageRegionAdaptativeSplitter<2> AdaptativeSplitterType;
AdaptativeSplitterType::Pointer internalSplitter = AdaptativeSplitterType::New();
if (i >= numPieces)
internalSplitter->SetTileHint(m_TileHint);
unsigned int nbSplits = internalSplitter->GetNumberOfSplits(m_ImageRegion,numberOfPieces);
//Iterate over streams computed by the adaptative splitter
for (unsigned int i = 0 ; i < nbSplits ; ++i)
{
itkExceptionMacro("Requested split number " << i << " but region contains only " << numPieces << " splits");
}
RegionType region;
IndexType index;
// Compute the split index in the streaming grid
splitIndex[1] = i / m_SplitsPerDimension[0];
splitIndex[0] = i % m_SplitsPerDimension[0];
region = internalSplitter->GetSplit(i,numberOfPieces,m_ImageRegion);
index = region.GetIndex();
// Transform the split index to the actual coordinates
splitRegion.SetIndex(0, region.GetIndex(0) + m_TileDimension * splitIndex[0]);
splitRegion.SetIndex(1, region.GetIndex(1) + m_TileSizeAlignment * splitIndex[1]);
const unsigned int sizeY = region.GetSize()[1] - 1;
splitRegion.SetSize(0, m_TileDimension);
splitRegion.SetSize(1, 1);
for (unsigned int j = 0 ; j < sizeY ; ++j)
{
//Add region aligned with the shrink factor
if (((index[1]+j) % m_TileSizeAlignment) == 0)
{
RegionType splitRegion;
// Handle the borders
splitRegion.Crop(region);
splitRegion.SetIndex(0, index[0]);
splitRegion.SetIndex(1, index[1]+j);
return splitRegion;
splitRegion.SetSize(0, region.GetSize()[0]);
splitRegion.SetSize(1, 1);
// Handle the borders
splitRegion.Crop(region);
//Add this split to the vector (we keep the order given by
//the adaptative splitter)
m_StreamVector.push_back(splitRegion);
}
}
}
m_IsUpToDate = true;
return;
}
void
......
......@@ -65,6 +65,8 @@ public:
/** Region typedef support. */
typedef itk::ImageRegion<ImageDimension> RegionType;
typedef std::vector<RegionType> StreamVectorType;
/** How many pieces can the specified region be split? A given region
* cannot always be divided into the requested number of pieces. For
* instance, if the numberOfPieces exceeds the number of pixels along
......@@ -87,12 +89,42 @@ public:
itkSetMacro(ShrinkFactor, unsigned int);
itkGetMacro(ShrinkFactor, unsigned int);
/** Set the TileHint parameter */
itkSetMacro(TileHint, SizeType);
/** Get the TileHint parameter */
itkGetConstReferenceMacro(TileHint, SizeType);
/** Set the ImageRegion parameter */
itkSetMacro(ImageRegion, RegionType);
/** Get the ImageRegion parameter */
itkGetConstReferenceMacro(ImageRegion, RegionType);
/** Set the requested number of splits parameter */
itkSetMacro(RequestedNumberOfSplits, unsigned int);
/** Get the requested number of splits parameter */
itkGetConstReferenceMacro(RequestedNumberOfSplits, unsigned int);
protected:
StreamingShrinkImageRegionSplitter() : m_SplitsPerDimension(0U), m_ShrinkFactor(10) {}
StreamingShrinkImageRegionSplitter() : m_SplitsPerDimension(0U),
m_ShrinkFactor(10),
m_TileHint(),
m_ImageRegion(),
m_RequestedNumberOfSplits(0),
m_StreamVector(),
m_IsUpToDate(false)
{}
virtual ~StreamingShrinkImageRegionSplitter() {}
void PrintSelf(std::ostream& os, itk::Indent indent) const;
private:
/** This methods actually estimate the split map using the
ImageRegionAdaptativeSplitter and stores it in a
vector */
void EstimateSplitMap(unsigned int numberOfPieces);
StreamingShrinkImageRegionSplitter(const StreamingShrinkImageRegionSplitter &); //purposely not implemented
void operator =(const StreamingShrinkImageRegionSplitter&); //purposely not implemented
......@@ -100,6 +132,24 @@ private:
unsigned int m_TileDimension;
unsigned int m_TileSizeAlignment;
unsigned int m_ShrinkFactor;
// This reflects the input image tiling
SizeType m_TileHint;
// This contains the ImageRegion that is currently beeing split
RegionType m_ImageRegion;
// This contains the requested number of splits
unsigned int m_RequestedNumberOfSplits;
// This is a vector of all regions which will be split
StreamVectorType m_StreamVector;
// Is the splitter up-to-date ?
mutable bool m_IsUpToDate;
// Lock to ensure thread-safety
itk::SimpleFastMutexLock m_Lock;
};
......
......@@ -40,9 +40,33 @@ template <class TImage>
void
StreamingShrinkStreamingManager<TImage>::PrepareStreaming( itk::DataObject * input, const RegionType &region )
{
typedef otb::StreamingShrinkImageRegionSplitter TileSplitterType;
TileSplitterType::Pointer splitter = TileSplitterType::New();
splitter->SetTileSizeAlignment(m_ShrinkFactor);
//Uses the TileHint from the MetaDataDictionnary to find out
//the tiling sheme of the input file if available.
typename otb::StreamingShrinkStreamingManager<TImage>::SizeType tileHint;
unsigned int tileHintX(0), tileHintY(0);
itk::ExposeMetaData<unsigned int>(input->GetMetaDataDictionary(),
MetaDataKey::TileHintX,
tileHintX);
itk::ExposeMetaData<unsigned int>(input->GetMetaDataDictionary(),
MetaDataKey::TileHintY,
tileHintY);
tileHint[0] = tileHintX;
tileHint[1] = tileHintY;
splitter->SetTileHint(tileHint);
this->m_Splitter = splitter;
unsigned long nbDivisions = this->EstimateOptimalNumberOfDivisions(input, region, 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment