Beginner in ITK, Averaging Image

Hello all,
I am new in ITK and using it with CMAKE, GCC compiler. As a python/Matlab programmer, I am finding ITK a bit confusing. But I am trying to do a project that will help me to learn ITK in general. I find the project interesting.
I have a public dataset of 21 3D MR images. I want to average those images and form a single one for registration purposes.
How do I do that?
And also would be helpful if anyone shares how to load class and header files for my purpose/need.

If you want to use your average image for registration purposes, then you have a chicken and egg problem. To get a good average image, you first need to register images together.

You could use ordinary registration techniques to register all images to one which is most average-looking to you. Let’s call that image atlas master. Then you could resample the images onto the pixel grid of the atlas master. Then you could finally make pixel-wise averages.

But before starting it, maybe you should read some groupwise registration papers. This one is freely accessible.

As for the ITK code, you could look at the examples and pick one to start from.

Thanks for your reply.
I wanted to add the images and divide it by the number of images added. Though I mentioned registration but in the second step I will use registration for comparison.
How do I add the 21 images from my local directory?

I am trying the following codes to add the images…let me know but ending up with some errors

<

int
main (int argc, char *argv[])
{
// Setup types
const unsigned int nDims = 3;
typedef itk::Image<int, nDims> ImageType;

// Create and setup a reader from argv[1]
typedef itk::ImageFileReader ImageReaderType;

ImageReaderType::Pointer readers[21];
for (size_t i = 0; i < 21; i++)
{
readers[i] = ImageReaderType::New ();
readers[i]->SetFileName (“KKI2009-” + std::to_string (files[i])
+ “-MPRAGE.nii”);
readers[i]->Update ();
}

Welcome to ITK, Rana! :sunny:

A good resource to be aware of is The ITK Software Guide.

Also, note that ITK also has a Python interface.

To achieve your goal in C++, one possible approach is to:

  1. Create an itk::ImageFileReader, set the filename for the first file, then call Update(). Get the output image SmartPointer, e.g. outputImage, with reader->GetOutput(), then call DisconnectPipeline() on the image. Call FillBuffer(0) on the image to start with an image of 0’s.
  2. Create an itk::AddImageFilter. The inputs are the outputImage and the ImageFileReader.
  3. Looping over the filenames, call SetFileName() on the ImageFileReader. Then call Update() on the AddImageFilter. Then assign the outputImage SmartPointer to addImageFilter->GetOutput(). Then, call outputImage->DisconnectPipeline();.
  4. Use itk::MultipleImageFilter, which also works with scalars to divide by the number of images.
1 Like

Hello Matt,
Thanks for the suggestion. Unfortunately, I ran some codes myself and it worked pretty much as I expected so I couldn’t see your suggestion otherwise I would’ve tried yours. Could you please take a look at the following code:

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkDivideImageFilter.h"
#include "itkNaryAddImageFilter.h"
#include  <string< //double bracket does not print here

int
main(int argc, char * argv[])
{
  // Setup types
  const unsigned int nDims = 3 ;
  typedef itk::Image< double, nDims > ImageType;


  // Create and setup readers for images:
  typedef itk::ImageFileReader< ImageType >  readerType;
  readerType::Pointer readers[21];

  for (int i = 1; i<=21; i = i+1)
    {
      std::string  digit="";
      if(i<10)
      {
       digit = "0";
      }
      readers[i-1] = readerType::New();
      readers[i-1]-> SetFileName("../MPRAGE21_copy/KKI2009-"+digit + std::to_string(i)+"-MPRAGE.nii");
      readers[i-1]->Update();
    }

  typedef itk::NaryAddImageFilter<ImageType, ImageType>NAddImageFilterType;
  NAddImageFilterType::Pointer nAddImage = NAddImageFilterType::New();
  for (int i =0;i<=20;i++)
    {
      nAddImage->SetInput(i, readers[i]->GetOutput());
    }
  nAddImage->Update();


  typedef itk::DivideImageFilter<ImageType, ImageType, ImageType>DivideImageFilterType;
  DivideImageFilterType::Pointer divider = DivideImageFilterType::New();
  divider->SetInput (nAddImage->GetOutput());
  divider-> SetConstant(21.0);
  divider->Update();


  // write out the result to:
  typedef itk::ImageFileWriter < ImageType > writerType;
  writerType::Pointer writer = writerType::New();
  //writer->SetInput ( divider->GetOutput());
  writer->SetFileName ("Sum21.nii" );
  writer->SetInput(divider->GetOutput());
  writer->Update();


  // Done.
  return 0 ;
}

What I want to do is now choose one image as a fixed image and affinely register other 20 ones to the fixed image and average all 21 again.
Which will give me affine template.

How do I perform affine registration in my case?

Thanks in advance.

@banikr looks great :clap:

The choice of similarity metric, optimization strategy, etc. depends on your data. A good general starting place is the ITK-based elastix.

Hello Matt,

Thanks for the reply. I have tried writing some codes and shared for help in another post.

Could you take a look and may be suggest ?

Thanks