Creating a composite Image from multiple blocks


#1

I am trying to create a composite image from a number of blocks arranged in a grid. When pasting new block into this composite Image the composite is getting overwritten in the location of first block so I end up with the mostly empty composite image with last block written in the first position. I am not sure why this is happening. Code of relavant function is attached below

void fuseImages(ImageType* compositeImage, ImageType* block, CompositeTransformType* transform,  double alpha){
    
    TransformType::Pointer combinedTransform = TransformType::New();
    combinedTransform->SetIdentity();
    std::size_t nTform = transform->GetNumberOfTransforms();
    for (std::size_t i = nTform; i-- > 0 ; ) {
	combinedTransform->Compose(static_cast< const TransformType* >( transform->GetNthTransformConstPointer(i) ) );
    }
    
    auto finalParameters    = combinedTransform->GetParameters();
    auto translationAlongX  = std::ceil(finalParameters[0]);
    auto translationAlongY  = std::ceil(finalParameters[1]);
    auto translationAlongZ  = std::ceil(finalParameters[2]);
    
    auto compositeImageSize = compositeImage->GetLargestPossibleRegion().GetSize();
    auto blockImageSize = block->GetLargestPossibleRegion().GetSize();
    std::cout<<"Size of Composite image"<<compositeImageSize<<std::endl;
    std::cout<<"Size of block image"<<blockImageSize<<std::endl;

    ImageType::IndexType finalShift = {{std::abs(translationAlongX),
	std::abs(translationAlongY),
	std::abs(translationAlongZ)}};
    std::cout<<"Location for destination:"<<finalShift<<std::endl;    
    ImageType::IndexType start;
    start.Fill(0);
    ImageType::RegionType blockRegion;
    blockRegion.SetSize( blockImageSize );
    blockRegion.SetIndex( start );

    ImageType::RegionType outputMovingRegion;
    outputMovingRegion.SetSize( blockImageSize );
    outputMovingRegion.SetIndex( finalShift );

    //added to prevent region outside buffered region 
    auto fixedROIFilter = ROIFilterType::New();
    fixedROIFilter->SetInput( compositeImage );    
    fixedROIFilter->SetRegionOfInterest( outputMovingRegion );
    fixedROIFilter->Update();
    

    itk::ImageRegionIterator< ImageType > compositeIterator(compositeImage, outputMovingRegion);
    itk::ImageRegionConstIterator< ImageType > blockIterator(block, blockRegion);
    
    OutputPixelType value, oldValue;
    while(!blockIterator.IsAtEnd()) {//!compositeIterator.IsAtEnd()){
        if(compositeIterator.Get() == 0){
            value = blockIterator.Get();
    	}else{
            oldValue = compositeIterator.Get();
    	    value = ( (1- alpha)*blockIterator.Get() ) + ( alpha * oldValue );
    	}
    	compositeIterator.Set(100);
        ++compositeIterator;
        ++blockIterator;
     }
 
    using WriterType = itk::ImageFileWriter< ImageType >;
    WriterType::Pointer writer = WriterType::New();
    writer->SetFileName( outFolder +  "test.mha" );
    writer->SetInput( compositeImage );
    try{
        writer->Update();
    	std::cout<<"WROTE FILE"<<writer->GetFileName()<<std::endl;
    }catch( itk::ExceptionObject & error ){
        #if DEBUG >= DEBUG_INFO
    	std::cerr << "Error: " << error << std::endl;
        #endif
    	return;// EXIT_FAILURE;
    }
}

(Dženan Zukić) #2

I guess this is debugging leftover.

Your entire composite image should be in memory, so there should be no need for fixedROIFilter. If compositeImage is not completely in memory, I don’t see how this could work at all.


(Dave Chen) #3

Way back when I wrote a SimpleITK Python script to do exactly what you want to do.

I’ve put it up on GitHub in case it might be of use to you.


#4

@dzenanz yes the line is leftover debugging. Thanks for your input, fixedROIFilter is indeed not required.
For future reference the problem was with the ‘block’ image. I was reusing the same reader in a loop which led to erratic behaviour. Creating a new instance of reader of each block got rid of the problem. I am not sure why this is the case, but clearly I don’t understand ITK well enough.


(Dženan Zukić) #5

If you intend to reuse the reader, e.g. declare it before the loop then use it in a loop, you need to disconnect pipeline from the resulting image:

reader=...
for (i=...)
{
  reader->SetFilename("blah"+std::to_string(i)+".png");
  reader->Update();
  images[i]=reader->GetOutput();
  images[i]->DisconnectPipeline(); // updating reader for i+1 will not affect i
}