I am trying to create an 3D volume (dimenstions are 4000 x 4000 x 1600) from separate images. I have a for loop, where I first create an std::vector and then use ImportImageFilter to create an image with dimensions 4000 x 4000 x 1. After that I use PasteImageFilter to insert the created image to the volume. So every image is like a layer in the big volume.
The code below works but it takes 20-25 seconds to import the image with the PasteImageFilter.
Is there anything i can do to make it run faster?
Important is that i can't have multiple volume copies at the same time, because i would ran out of memory.
sitk::PixelIDValueEnum pixelTypeM1 = sitk::sitkUInt8;
sitk::PixelIDValueEnum pixelTypeM2 = sitk::sitkFloat32;
std::vector<unsigned int> sitkVolumeSize{4000,4000,1600};
sitk::Image sitk_m1_volume( sitkVolumeSize, pixelTypeM1 );
sitk::Image sitk_m2_volume( sitkVolumeSize, pixelTypeM2 );
sitk::PasteImageFilter pasteFilter;
for(int idx = 0; idx < 1600; idx++){
std::vector<measurement> s1, s2;
std::tie (s1, s2) = load_data();
std::vector<float> m1_vec(4000*4000);
std::vector<uint8_t> m2_vec(4000*4000);
//some computations here to fill the m1_vec and m2_vec
std::vector<unsigned int> imageDims{4000, 4000, 1};
sitk::ImportImageFilter importer;
importer.SetSize( imageDims );
importer.SetBufferAsUInt8(m1_vec.data());
sitk::Image m1_image = importer.Execute();
importer.SetBufferAsFloat( m2_vec.data() );
sitk::Image m2_image = importer.Execute();
pasteFilter.SetDestinationIndex({0,0,idx});
pasteFilter.SetSourceSize(m2_image.GetSize());
sitk_m2_volume = pasteFilter.Execute(sitk_m2_volume, m2_image);
sitk_m1_volume = pasteFilter.Execute(sitk_m1_volume, m1_image);
}
Please ensure that you are compiling in Release mode and not debug this is the most common reason for slow performance using ITK and SimpleITK in C++.
sitk_m2_volume = pasteFilter.Execute(sitk_m2_volume, m2_image);
sitk_m1_volume = pasteFilter.Execute(sitk_m1_volume, m1_image);
With the above calls to execute it will create a copy of the sitk_m{2,1}_volumes. This can be expensive with large images. The sitk::PasteImageFilter also supports move symatics with the first argument:
Image itk::simple::PasteImageFilter::Execute(Image && destinationImage, const Image & sourceImage
)
If you are not familiar with C++ move semantics and rvalue references please find a good modern C++ reference to learn. This signature can be used like this:
sitk_m2_volume = pasteFilter.Execute(std::move(sitk_m2_volume), m2_image);
sitk_m1_volume = pasteFilter.Execute(std::move(sitk_m1_volume), m1_image);
With this call the Image buffer will be moved from the input argument to the output and will not copy the whole buffer thus improving performance.