如何使用C++将ITK连接到VTK?

3
我是ITK、VTK和Qt的初学者,我使用Visual Studio 9。我试图用ITK读取DICOM系列,并在QVTKWidget(Qt)中显示它。我基于这个代码http://www.itk.org/Wiki/VTK/Examples/Cxx/IO/ReadDICOMSeries并根据我的需要进行了修改。
当我使用VTK读取DICOM系列并在QVTKWidget中显示时,它可以正常工作。但当我想要用ITK读取这个系列并在QVTKWidget中显示时,程序会显示系列的第一张图片,当我用鼠标滚轮切换到下一张图片时,程序崩溃了。
当我调试时,收到了这个错误:
void VTKImageExportBase::UpdateInformationCallbackFunction(void *userData)
{
static_cast< VTKImageExportBase * >
( userData )->UpdateInformationCallback();//the error is here
}

我尝试使用ausssi的ImageToVTKImageFilter类,但是遇到了同样的问题。

以下是我的代码:

void essaieAppQtVTK::drawDCMSeries(std::string folderDCM)
{
typedef unsigned short    PixelType;
const unsigned int      Dimension = 3;

typedef itk::Image< PixelType, Dimension >         ImageType;

typedef itk::VTKImageExport<ImageType> ImageExportType; 
typedef itk::ImageSeriesReader< ImageType >        ReaderType;
ReaderType::Pointer reader = ReaderType::New();
typedef itk::GDCMImageIO       ImageIOType;
ImageIOType::Pointer dicomIO = ImageIOType::New(); 

reader->SetImageIO( dicomIO );
typedef itk::GDCMSeriesFileNames NamesGeneratorType;
NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New();

nameGenerator->SetUseSeriesDetails( true );
nameGenerator->AddSeriesRestriction("0008|0021" );  
nameGenerator->SetDirectory( folderDCM);

typedef std::vector< std::string >    SeriesIdContainer;    
const SeriesIdContainer & seriesUID = nameGenerator->GetSeriesUIDs();   
std::cout << seriesUID.size() << std::endl;
SeriesIdContainer::const_iterator seriesItr = seriesUID.begin();
SeriesIdContainer::const_iterator seriesEnd = seriesUID.end();
while( seriesItr != seriesEnd )
{
std::cout << seriesItr->c_str() << std::endl;
seriesItr++;
}
std::string seriesIdentifier;
seriesIdentifier = seriesUID.begin()->c_str();
std::cout << seriesIdentifier.c_str() << std::endl;

typedef std::vector< std::string >   FileNamesContainer;
FileNamesContainer fileNames; 
fileNames = nameGenerator->GetFileNames( seriesIdentifier ); 

reader->SetFileNames( fileNames );
try
{
reader->Update();
}
catch (itk::ExceptionObject &ex)
{
std::cout << ex << std::endl;
}

//------------------------------------------------------------------------
// ITK to VTK pipeline connection.
//------------------------------------------------------------------------

// Create the itk::VTKImageExport instance and connect it to the
// itk::CurvatureFlowImageFilter.
ImageExportType::Pointer exporter = ImageExportType::New();
exporter->SetInput(reader->GetOutput());

// Create the vtkImageImport and connect it to the
// itk::VTKImageExport instance.
vtkImageImport* importer = vtkImageImport::New();  
ConnectPipelines(exporter, importer);

//------------------------------------------------------------------------
// VTK pipeline.
//------------------------------------------------------------------------

this->imageViewer= vtkImageViewer2::New();
imageViewer->SetInput(importer->GetOutput());


// slice status message
//******same code *****//

// usage hint message
//******same code *****//

// create an interactor with our own style (inherit from vtkInteractorStyleImage)
// in order to catch mousewheel and key events
//******same code *****//

// add slice status message and usage hint message to the renderer
//******same code *****//

//to display the result: 
ui.qvtkWidget->SetRenderWindow(imageViewer->GetRenderWindow()); 
ui.qvtkWidget->GetRenderWindow()->GetInteractor()-   >SetInteractorStyle(myInteractorStyle); 
imageViewer->Render(); 
ui.qvtkWidget->update();
}

可选:我的导出器和导入器如下:

template <typename ITK_Exporter, typename VTK_Importer>
void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter- >GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
/**
* This function will connect the given vtkImageExport filter to
* the given itk::VTKImageImport filter.
*/
template <typename VTK_Exporter, typename ITK_Importer>
void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}

也许ITK和VTK之间的管道存在故障,请帮助我找到解决这个问题的方法。我已经花了两周时间寻找解决方案,但所有的方法都失败了。也许有另一种方法可以将ITK和VTK绑定在一起,除了ImageToVTKImageFilter类。我期待您的帮助。提前感谢您。

信息:我忘了告诉你,我尝试使用ITK和VTK读取DICOM系列,但没有使用Qt,结果非常好,并且我使用了我发布的相同代码。问题出在当我想在QVTKWidget上显示这个系列时。请帮帮我! - Clara
我可以告诉你,对于我作为医学影像研究员所做的大部分Qt + VTK + ITK应用程序,我使用ItkVTKGlue代码。自2008年以来,这一方法一直适用于ITK、VTK和Qt的许多版本。 - drescherjm
1个回答

1

我在使用 ImageToVTKImageFilter 进行转换时,在 VTKImageExportBase::UpdateInformationCallbackFunction 函数内遇到了与你相同的错误。我所缺少的是在将其连接到 VTK 查看器之前更新 ITK 管道。在 ITK 到 VTK 管道连接 部分,你的代码也缺少同样的步骤。因此,请使用以下代码:

exporter->SetInput(reader->GetOutput());
exporter->Update();

然后继续前进。

谢谢您的回复,我已经找到了解决问题的方法,实际上只需要在代码末尾添加这一行:renderWindowInteractor->Start();但是我想知道,ImageToVTKImageFilter和我使用的方法(ConnectPipelines)之间有什么区别吗?谢谢。 - Clara
根据我检查的ImageToVTKImageFilter代码,它使用了与您导出itk图像相同的方法,因此没有任何区别。 - QT-ITK-VTK-Help

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接