[ITK-users] Loading a specifing region of an image from disk
Pol Monsó Purtí
lluna.nova at gmail.com
Tue Nov 4 12:34:37 EST 2014
2014-11-04 15:31 GMT+01:00 Bradley Lowekamp <blowekamp at mail.nih.gov>:
> Discussion inline below:
>
> On Nov 3, 2014, at 5:58 PM, Pol Monsó Purtí <lluna.nova at gmail.com> wrote:
>
> I've read the article early this afternoon and I found it very good and
> encouraging. Specially *"The other difference is that the reader fully
> supports streaming and only reads the required region from the file."*
>
> That is exactly what we need. I was just wondering wether it splitted the
> volume and took the chunks that intersected with the requested one or if it
> really just loaded the requested one. I replicated that code taking out the
> processing and just having a reader and a writer, but I didn't know how to
> test that indeed it was just loading that requested piece.
>
>
> For the ImageIO file formats I wrote which are just headers with binary
> data, they can read an arbitrary ImageIORegion and don't read any more.
> Practically however, its extremely in efficient to not read complete
> contiguous scanlines as there is to much random access and it slows down.
> For Tiff ( similar to some JPEG2000 formats), the image is encoded as
> strips or tiles. The underlying libtiff library can only easily decode
> these entire chunks, so the plan is that the requested region will be
> expanded by the image io to the union of the strips/tiles needed to read
> the requested region.
>
>
>
>> > 2.- Will the pipeline only load the requested region, including the
>> reader?
>>
>> The pipeline has a series of steps which include propagating a requested
>> region, and giving each filter the opportunity to enlarge this region. I
>> have frequently assemble pipelines which perform out-of-core processing as
>> you desire. However all filters in the pipeline must support streaming, and
>> not enlarging the requested region to the largest possible region.
>>
>>
> Yes, I've seen that not many support streaming. But in our case we would
> just need a reader that can read a specific region.
>
>
>> Additionally the ImageIO for the reader and writer must also support
>> streaming. There are several ImageIO's which support streaming reading
>> (MRC,MetaIO, VTK, Nift, JPEG2000, etc), I believe that only MRC, VTK and
>> MetaIO fully support it for writing. So TIFF is currently not there.
>>
>
> Yeah, we were thinking on using HDF5, but maybe you have some idea on what
> would be best. That's another topic thought.
>
>
> I find the the header + raw image data are rather efficient for random
> access of the whole image. These files are archived with compression, and
> decompressed when needed.
>
Yes indeed.
>
>
>> Recently I have been working on improving the itkTIFFImageIO [2], and
>> have performance gains of upto 3-5X from the prior version. However, I
>> haven't gotten to adding streaming yet. It's is a back burner project for
>> me to add support for stream reading to it, so that may be coming shortly (
>> this poking helps ). However, adding stream and paste writing is not
>> planned.
>>
>>
> Good work! 3-5x! That might be of interest actually for something else we
> have. Can we pull your code?
>
>
> Its in ITK master please test :)
>
Will do.
>
>> For this case you should add in an ExtractImageFilter, or a
>> CropImageFilter.
>>
>>
> But if I use Extract or Crop, the reader is still loading the full image
> to disk, isn't it?
>
>
> Nope. The only the sub-region is requested to the reader, and if the
> reader supports streaming that region will be read.
>
> I'd suggest reading section 13.3 of the ITK Software guide a couple times.
> And then assemble the pipeline Reader->Extract, and printing the output of
> each filter for each step in Extract->UpdateOutputInformation(),
> Extract->PropagateRequestedRegion() and then Extract->UpdateOutputData().
> This will help you to under stand the step in the pipeline execution.
>
>
So do readers (hdf5 for example) transparently do streaming? Or do I have
to set the reader imageIO so that it know that it has to stream?
Section 13.3? There are 9 sections, which one do you refer to? I think I
get what you mean and I'll split up the process to undrstand it better as
you suggest.
Meanwhile, below I paste a piece of code more close to what we would like
to do. The code results in exception because the ImageIO starts at index
[0,0,0] while piece1 starts at 51,80,5 and therefore the Extract fails. I
didn't understand how to set the index on a ImageIO. Then I saw that in
your article you put the whole ImageIO and then you just select one slice
with coronalSlice (which would be my piece1/2). I tried that too, although
I wonder what's the difference with not specifying ImageIO and read
normally. setting imageio1/2 to the full image failes on the reader, saying
that it expected 24300094 bytes (that's the size of the image, so it's
trying to load all I guess), but read 411866 bytes.
How can I do this right? And how would the code change if I were to use
HDF5?
the code:
int main( int argc, char* argv[] )
{
const unsigned int Dimension = 3;
typedef unsigned char PixelType;
typedef itk::Image< PixelType, Dimension > ImageType;
typedef itk::ImageFileReader< ImageType > ReaderFilterType;
ReaderFilterType::Pointer reader1 = ReaderFilterType::New();
reader1->SetFileName("../data/image.raw");
//size is not known until we load the image
// ImageType::RegionType largest =
reader1->GetOutput()->GetLargestPossibleRegion();
// ImageType::SizeType size = largest.GetSize();
// ImageType::IndexType index = largest.GetIndex();
ImageType::IndexType start;
start.Fill(0);
ImageType::SizeType size;
size[0] = 511;
size[1] = 806;
size[2] = 59;
ImageType::RegionType largest(start,size);
ReaderFilterType::Pointer reader2 = ReaderFilterType::New();
reader2->SetFileName("../data/image.raw");
ImageType::RegionType piece1;
piece1.SetIndex(0,start[0] + 0.1*size[0]);
piece1.SetIndex(1,start[1] + 0.1*size[1]);
piece1.SetIndex(2,start[2] + 0.1*size[2]);
piece1.SetSize(0,0.1*size[0]);
piece1.SetSize(1,0.1*size[1]);
piece1.SetSize(2,0.1*size[2]);
ImageType::RegionType piece2;
piece2.SetIndex(0,start[0] + 0.5*size[0]);
piece2.SetIndex(1,start[1] + 0.5*size[1]);
piece2.SetIndex(2,start[2] + 0.5*size[2]);
piece2.SetSize(piece1.GetSize());
std::cout << "largest: " << largest << std::endl;
std::cout << "piece1: " << piece1 << std::endl;
std::cout << "piece2: " << piece2 << std::endl;
typedef itk::RawImageIO <PixelType, Dimension> ImageIOType;
ImageIOType::Pointer imageio1 = ImageIOType::New();
ImageIOType::Pointer imageio2 = ImageIOType::New();
imageio1->SetDimensions(0,piece1.GetSize()[0]);
imageio1->SetDimensions(1,piece1.GetSize()[1]);
imageio1->SetDimensions(2,piece1.GetSize()[2]);
imageio1->SetHeaderSize(piece1.GetSize()[0]*piece1.GetSize()[1]*piece1.GetSize()[2]);
imageio2->SetDimensions(0,piece2.GetSize()[0]);
imageio2->SetDimensions(1,piece2.GetSize()[1]);
imageio2->SetDimensions(2,piece2.GetSize()[2]);
imageio2->SetHeaderSize(piece2.GetSize()[0]*piece2.GetSize()[1]*piece2.GetSize()[2]);
reader1->SetImageIO(imageio1);
reader2->SetImageIO(imageio2);
//this should now work
reader1->UpdateOutputInformation();
reader2->UpdateOutputInformation();
std::cout << "reader largest " <<
reader1->GetOutput()->GetLargestPossibleRegion() << std::endl;
typedef itk::ExtractImageFilter< ImageType, ImageType > ExtractFilterType;
ExtractFilterType::Pointer extract1 = ExtractFilterType::New();
ExtractFilterType::Pointer extract2 = ExtractFilterType::New();
extract1->SetExtractionRegion(piece1);
extract2->SetExtractionRegion(piece2);
extract1->SetInput(reader1->GetOutput());
extract2->SetInput(reader2->GetOutput());
#if ITK_VERSION_MAJOR >= 4
extract1->SetDirectionCollapseToIdentity();
extract2->SetDirectionCollapseToIdentity();
#endif
try
{
extract1->Update();
extract2->Update();
}
catch( itk::ExceptionObject & error )
{
std::cerr << "Extract error: " << error << std::endl;
return EXIT_FAILURE;
}
typedef itk::SubtractImageFilter <ImageType, ImageType >
SubtractImageFilterType;
SubtractImageFilterType::Pointer subtractFilter
= SubtractImageFilterType::New ();
subtractFilter->SetInput1(extract1->GetOutput());
subtractFilter->SetInput2(extract2->GetOutput());
typedef itk::ImageFileWriter< ImageType > WriterFilterType;
WriterFilterType::Pointer writer = WriterFilterType::New();
writer->SetFileName("image_out.raw");
writer->SetInput(subtractFilter->GetOutput());
try
{
writer->Update();
}
catch( itk::ExceptionObject & error )
{
std::cerr << "Error: " << error << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/insight-users/attachments/20141104/7d61f278/attachment.html>
More information about the Insight-users
mailing list