itkImageToVtkImageFilter returns ObjectBase

Hi,

I’m using ITK5 and VTK9, and I’m very confusing about itkImageToVtkImageFilter returns.

This is my code

class Window {
public:
    Window();
    explicit Window(const ImageType::Pointer image);
    virtual ~Window();
    Window(const Window& other);
    Window& operator=(const Window& other);

    vtkImageData* ConvertItkToVtk();

private:
    ImageType::Pointer _image;
};

vtkImageData* Window::ConvertItkToVtk()
{
    constexpr unsigned int Dimension = 2;
    using PixelType = unsigned char;
    using ImageType = itk::Image< PixelType, Dimension >;
    using ReaderType = itk::ImageFileReader< ImageType >;
    using itkVtkFilterType = itk::ImageToVTKImageFilter< ImageType >;

    itkVtkFilterType::Pointer filter = itkVtkFilterType::New();
    filter->SetInput(this->_image);
    try {
        filter->Update();
    } catch (itk::ExceptionObject & error) {
        std::cerr << "Error: " << error << std::endl;
        return nullptr;
    }
    filter->GetOutput()->Print(std::cout) // 1
    return filter->GetOutput();
}

int main(int argc, char *argv[])
{

    if (argc < 2) {
        std::cerr << "Invalid Usage!" << std::endl;
        std::cerr << "Usage: " << argv[0] << ", {filename}.dcm" << std::endl;
        return EXIT_FAILURE;
    }

    Program program(argv[1]);
    Window w(program.ReadImage());

    w.ConvertItkToVtk()->Print(std::cout); // 2

    return EXIT_SUCCESS;
}

In the place of 1, itkImageToVtkFilter returns vtkImageData object correctly like this

vtkImageData (0x7f93899b68a0)
  Debug: Off
  Modified Time: 230
  Reference Count: 1
  Registered Events: (none)
  Information: 0x7f93899b6a40
  Data Released: False
  Global Release Data: Off
  UpdateTime: 231
  Field Data:
    Debug: Off
    Modified Time: 150
    .....

But in the 2, It becomes vtkObjectBase like this

vtkObjectBase (0x7f93899b68a0)
  Reference Count: 0

Why this problem occurs?
I’m sorry I’m a beginner of itk and vtk.
please help me.

Hi,

It’s because the image is discarded because the only registered reference that linked it was the filter which created it. When the function end, the filter is discarded, thus also the image. Try returning a vtkSmartPointer< vtkImageData > rather than vtkImageData*.

HTH,

Tim

@tim-evain
Thank you for your reply!

I tried it, but it doesn’t work…
this is my updated code

vtkImageData* Window::ConvertItkToVtk()
{
    itkVtkFilterType::Pointer filter = itkVtkFilterType::New();
    filter->SetInput(this->_image);
    try {
        filter->Update();
    } catch (itk::ExceptionObject & error) {
        std::cerr << "Error: " << error << std::endl;
        return nullptr;
    }
    vtkSmartPointer<vtkImageData> image = filter->GetOutput();

    return image;
}

Is it impossible to return vtkImageData object?

It’s possible, no worries :slight_smile:.

You haven’t changed the return type of your function, so you are not returning the smart pointer. Change for :

vtkSmartPointer<vtkImageData> Window::ConvertItkToVtk()

If it still fails, add a vtkSmartPointer<vtkImageData> member to your class, and assign the filter output to it, then return the member to keep a reference.

@tim-evain

Awesome!!!
It work!!!
Thank you very much!

If i try to convert from vtkImageData to itkImage and want to return that,
do i need to use itk::SmartPointer?

@arwtyxouymz

If you want to keep the same logic, yes.

Just keep in mind that ITK/VTK use their smartpointers and reference counts to keep a track when a object is used or become useless. That doesn’t formally prevent you from using raw pointers, but the reference tracking will be blind to them, eventually leading to issues like yours.

@tim-evain

Thank you for your teaching!

1 Like

@tim-evain

I’m sorry that i ask you the same type question again…

Based on your explanation, I tried to use itk::Image as a member of class, but it cannot be displayed by QuickView.
This is my code:

constexpr unsigned int Dimension = 2;
using PixelType = unsigned char;
using ImageType = itk::Image< PixelType, Dimension >;

class Program {
public:
    Program();
    explicit Program(const std::string& filename);

    virtual ~Program();

    Program(const Program& other);
    Program& operator=(const Program& other);

    void ReadImage();
    itk::SmartPointer<ImageType> GetImage();

private:
    const std::string _filename;
    itk::SmartPointer<ImageType> _image;
};
void Program::ReadImage()
{
    ReaderType::Pointer reader = ReaderType::New();
    reader->SetFileName(this->_filename);

    this->_image = reader->GetOutput();
}

itk::SmartPointer<ImageType> Program::GetImage()
{
    return this->_image;
}

int main(int argc, char *argv[])
{

    if (argc < 2) {
        std::cerr << "Invalid Usage!" << std::endl;
        std::cerr << "Usage: " << argv[0] << ", {filename}.dcm" << std::endl;
        return EXIT_FAILURE;
    }

    Program program(argv[1]);
    program.ReadImage();
    QuickView q;
    q.AddImage(program.GetImage().GetPointer());
    q.Visualize();
    return EXIT_SUCCESS;
}

I tried

private:
    ImageType::Pointer _image;

But this also doesn’t work.

I’m so sorry to ask about same question, but i wanna your help
please help me

I think it because you forgot the Update() call on the reader in your ReadImage function (before the assign to the member).

On side notes:

  • The smartpointers decay into raw pointers, so you can call directly “q.AddImage(program.GetImage())”
  • Smartpointers in ITK can also be obtained like “ImageType::Pointer” rather than “itk::SmartPointer<ImageType>”. Just mentioning since this way is used in the ITK code/examples

@tim-evain

Thank you! It worked!