I been trying to fix this very weird problem since 1 or 2 weeks ago.
I am trying to read DICOM images using ITK and afterwards do some processing.
Problem is, i want to read the images independently of the pixel type. For this, i have to find out the pixel type and instantiate the itkImage on runtime.
Therefore, when i read the image file, i have to convert it from itkImage to itkImageBase (in the itkImage.h it is declared as class itkImage : public itkImageBase).
Unfortunately, after i cast it from one type to another inside an if block, i cannot access the value stored on this variable anywhere outside this if block. Here is the code:
*Sorry about the variables and method names in portuguese. Here is a little help:
leitor means reader
tipoPixel means pixelType
abreImagem(templated method) means openImage
iniciaAbrirImagem means initiateOpenImage
//here is io.h
#ifndef IO_H
#define IO_H
#include "itkImageSeriesReader.h"
#include "itkImageFileWriter.h"
#include "itkGDCMSeriesFileNames.h"
#include "itkGDCMImageIO.h"
#include "itkMetaDataDictionary.h"
#include "itkImageBase.h"
#include "iobase.h"
typedef itk::GDCMImageIO GDCM;
typedef itk::Image<float, 3> TipoImagemIO;
typedef itk::MetaDataDictionary TipoDicionario;
typedef itk::MetaDataObject<std::string> MetaDataString;
typedef itk::ImageBase<3> ImageBase; //Typedef for the imagebase
class IO : public IOBase
{
private:
ImageBase* imagemB; //This is the variable giving me some trouble
ImageBase* imagemB2;
GDCM::Pointer gdcm;
std::string tipoPixel;
public:
IO();
template<typename TLeitor>void abreImagem(std::string s, TLeitor leitor);
void abreDiretorio(std::string s);
void iniciaGravarImagem(std::string s, ImageBase* imgNova);
ImageBase* GetOutput();
void extraiTags();
void iniciaAbrirImagem(std::string s);
template<typename TGravador, typename TImagem>void gravaImagem(TGravador gravador, TImagem img, std::string s);
};
#endif
//here is io.cpp
#include "io.h"
#include "vtkKWImage.h"
#include "vtkKWImageIO.h"
#include "imagem.h"
#include <typeinfo>
IO::IO()
{
imagemB = 0;
imagemB2 = 0;
gdcm = GDCM::New();
}
template<typename TLeitor>
void IO::abreImagem(std::string s, TLeitor leitor)
{
leitor->SetImageIO(gdcm);
leitor->SetFileName(s);
try
{
leitor->Update();
}
catch(itk::ExceptionObject &ex)
{
std::cerr<<ex<<std::endl;
exit(1);
}
try
{
imagemB = static_cast<ImageBase*>(leitor->GetOutput());
}
catch(std::bad_cast &ex)
{
std::cout<<"EXCECAO";
exit(1);
}
std::cout<<imagemB->GetNameOfClass(); //This one is ok
}
void IO::iniciaAbrirImagem(std::string s)
{
extraiTipoDimensoes(s);
tipoPixel = GetTipo();
if(tipoPixel.compare("short") == 0)
{
typedef itk::Image<short, 3> itkImg;
typedef itk::ImageSeriesReader<itkImg> TipoLeitor;
TipoLeitor::Pointer leitor = TipoLeitor::New();
abreImagem<TipoLeitor::Pointer>(s, leitor);
std::cerr<<"Trying to call a method inside IF: "<<imagemB->GetNameOfClass()<<std::endl; //This one is ok too
}
//...doing the same things for unsigned short, int, float, double, etc...
std::cerr<<"trying to call a method outside IF: ";
std::cerr<<imagemB->GetNameOfClass()<<std::endl; //Here i get this weird segmentation fault
}
ImageBase* IO::GetOutput()
{
std::cerr<<"JUST ENTERED GETOUTPUT()";
std::cout<<imagemB->GetNameOfClass()<<std::endl; //If i remove the last method call of this variable, i get a segfault here
std::cerr<<std::endl<<"HOORAY, ITS GETTING OUT OF GETOUPUT"<<std::endl;
return imagemB;
}
As you can see (or atleast i hope the code is clear enough so you can see it), i declared a pointer to itk::ImageBase<3> and initiated it with value 0 on the class constructor (already tried without initializing, initializing with null, nothing works...).
Afterwards, i call some methods from other class to find out the pixel type of the input image. Then, i enter and if block where i instantiate a itk::ImageFileReader and an itkImage with the same pixel type as the input image.
Then, i send the variable of the type TipoLeitor (or ReaderType, as you wish) to the templated function, where i actually read the image file inside the try/catch block. Then, on the next try i cast the output of the reader (an itkImage) to itkImageBase and put it in the imagemB variable.
If i try to call some random method of that class, like GetNameOfClass inside the templated method, thats ok, everything goes as expected. If i do the same inside the if block where the templated method was called, thats ok too. But it doesn't work if i try to do the same inside the function, after the if block. The same happens if i try to do this on GetOutput() method.
It is like the variable imagemB is initialized inside the if block, the, when it exits the block it is set to uninitialized (does this word even exists).
There's no detailed error message, just a "Segmentation fault".
Thanks for the help and sorry about the poor english and the long text.
leitor
a smart pointer ? – MaheshTipoLeitor::Pointer
falls under this type is what I meant ? – Mahesh