[Insight-users] problem displaying series DICOM with ITK VTK QVTKWidget
Cary lorey
developement.unity at gmail.com
Thu Apr 18 10:52:52 EDT 2013
Hello ,
I saw your video entitled "CT Data visualization", I work in the same
environment (visual studio 9, VTK, ITK and qt for GUI)
I am a beginner in VTK and ITK and Qt, so for the moment I am trying to
read a DICOM series with ITK and display it with VTK into QVTKWidget.
First, I was able to view the DICOM series with ITK and VTK, but without Qt.
Then, when I wanted to view the DICOM series with QVTKWidget, the program
crashes.
Then, I tried to read the DICOM series with VTK without ITK and display it
into QVTKWidget to locate the problem and it works.
so there may be a problem with ITK pointer, sincerely I do not know what
the problem, I tried with all methods but the program still crashes. I took
for your help if you have an idea about this problem.
here is my code:
************************************************************************
#include "essaieappqtvtk.h"
#include <vtkSmartPointer.h>
#include <vtkObjectFactory.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkActor.h>
// headers needed for this example
#include <vtkImageViewer2.h>
#include <vtkDICOMImageReader.h>
#include <vtkInteractorStyleImage.h>
#include <vtkActor2D.h>
#include <vtkTextProperty.h>
#include <vtkTextMapper.h>
#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkCurvatureFlowImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itkGDCMImageIO.h"
#include "itkVTKImageExport.h"
#include "itkVTKImageImport.h"
#include "vtkImageImport.h"
#include "vtkImageExport.h"
#include "vtkRenderWindow.h"
#include "vtkImageActor.h"
#include "vtkImageData.h"
#include "itkGDCMImageIO.h"
#include "itkGDCMSeriesFileNames.h"
#include "itkImageSeriesReader.h"
#include "itkImageFileWriter.h"
#include "vtkImageShiftScale.h"
//#include "vtkKWImageIO.h"
//#include "vtkKWImage.h"
// needed to easily convert int to std::string
#include <sstream>
using namespace std;
#include <QFileDialog>
#include <QString>
#include <QMessageBox>
#include <QFile>
#include "vtkKWImageIO.h"
#include "vtkKWImage.h"
using namespace std;
class StatusMessage {
public:
static std::string Format(int slice, int maxSlice) {
std::stringstream tmp;
tmp << "Slice Number " << slice + 1 << "/" << maxSlice + 1;
return tmp.str();
}
};
// Define own interaction style
class myVtkInteractorStyleImage : public vtkInteractorStyleImage
{
public:
static myVtkInteractorStyleImage* New();
vtkTypeMacro(myVtkInteractorStyleImage, vtkInteractorStyleImage);
protected:
vtkImageViewer2* _ImageViewer;
vtkTextMapper* _StatusMapper;
int _Slice;
int _MinSlice;
int _MaxSlice;
public:
void SetImageViewer(vtkImageViewer2* imageViewer) {
this->_ImageViewer = imageViewer;
_MinSlice = imageViewer->GetSliceMin();
_MaxSlice = imageViewer->GetSliceMax();
_Slice = _MinSlice;
cout << "Slicer: Min = " << _MinSlice << ", Max = " << _MaxSlice <<
std::endl;
}
void SetStatusMapper(vtkTextMapper* statusMapper) {
_StatusMapper = statusMapper;
}
protected:
void MoveSliceForward() {
if(_Slice < _MaxSlice) {
_Slice += 1;
cout << "MoveSliceForward::Slice = " << _Slice << std::endl;
this->_ImageViewer->SetSlice(_Slice);
std::string msg = StatusMessage::Format(_Slice, _MaxSlice);
_StatusMapper->SetInput(msg.c_str());
_ImageViewer->Render();
}
}
void MoveSliceBackward() {
if(_Slice > _MinSlice) {
_Slice -= 1;
cout << "MoveSliceBackward::Slice = " << _Slice << std::endl;
this->_ImageViewer->SetSlice(_Slice);
std::string msg = StatusMessage::Format(_Slice, _MaxSlice);
_StatusMapper->SetInput(msg.c_str());
_ImageViewer->Render();
}
}
virtual void OnKeyDown() {
std::string key = this->GetInteractor()->GetKeySym();
if(key.compare("Up") == 0) {
//cout << "Up arrow key was pressed." << endl;
MoveSliceForward();
}
else if(key.compare("Down") == 0) {
//cout << "Down arrow key was pressed." << endl;
MoveSliceBackward();
}
// forward event
vtkInteractorStyleImage::OnKeyDown();
}
virtual void OnMouseWheelForward() {
//std::cout << "Scrolled mouse wheel forward." << std::endl;
MoveSliceForward();
// don't forward events, otherwise the image will be zoomed
// in case another interactorstyle is used (e.g. trackballstyle, ...)
// vtkInteractorStyleImage::OnMouseWheelForward();
}
virtual void OnMouseWheelBackward() {
//std::cout << "Scrolled mouse wheel backward." << std::endl;
if(_Slice > _MinSlice) {
MoveSliceBackward();
}
// don't forward events, otherwise the image will be zoomed
// in case another interactorstyle is used (e.g. trackballstyle, ...)
// vtkInteractorStyleImage::OnMouseWheelBackward();
}
};
vtkStandardNewMacro(myVtkInteractorStyleImage);
/**
* This will be setup as a callback for a progress event on an ITK
* filter.
*/
struct ProgressDisplay
{
ProgressDisplay(itk::ProcessObject* process): m_Process(process) {}
void Display()
{
float progress = m_Process->GetProgress()*100.0;
std::cout << "Progress " << progress << " percent." << std::endl;
}
itk::ProcessObject::Pointer m_Process;
};
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());
}
essaieAppQtVTK::essaieAppQtVTK(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
connect(this->ui.pushButton, SIGNAL(clicked()), this,
SLOT(slotOpenFolder()));
}
void essaieAppQtVTK::openDCMFolder()
{
QString folderNameDCM = QFileDialog::getExistingDirectory(this,tr("Open DCM
Folder"),QDir::currentPath(),QFileDialog::ShowDirsOnly);
std::string stdstrFolderNameDCM = folderNameDCM.toUtf8().constData();
drawDCMSeries(stdstrFolderNameDCM);
}
void essaieAppQtVTK::slotOpenFolder()
{
openDCMFolder();
}
void essaieAppQtVTK::drawDCMSeries(std::string folderDCM)
{
//typedef unsigned short PixelType;
//const unsigned int Dimension = 3;
// typedef itk::Image< PixelType, Dimension > ImageType;
typedef itk::Image< double, 3 > 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;
}
//*************************************************************//
typedef itk::CurvatureFlowImageFilter<ImageType, ImageType> DenoiserType;
// Create the itk::CurvatureFlowImageFilter and connect it
// to the itk::RandomImageSource.
DenoiserType::Pointer denoiser = DenoiserType::New();
denoiser->SetInput(reader->GetOutput());
//------------------------------------------------------------------------
// ITK to VTK pipeline connection.
//------------------------------------------------------------------------
// Create the itk::VTKImageExport instance and connect it to the
// itk::CurvatureFlowImageFilter.
ImageExportType::Pointer exporter = ImageExportType::New();
exporter->SetInput(denoiser->GetOutput());
// Create the vtkImageImport and connect it to the
// itk::VTKImageExport instance.
vtkImageImport* importer = vtkImageImport::New();
ConnectPipelines(exporter, importer);
//------------------------------------------------------------------------
// VTK pipeline.
//------------------------------------------------------------------------
importer->Update();
this->imageViewer= vtkImageViewer2::New();
imageViewer->SetInput(importer->GetOutput());
//***********************************************************
//it works with VTK reader without ITK:
/*this->reader = vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetDirectoryName(folderDCM.c_str());
reader->Update();
imageViewer->SetInputConnection(reader->GetOutputPort());*/
//******************************************************************
// slice status message
vtkTextProperty *sliceTextProp = vtkTextProperty::New();
// this->sliceTextProp = vtkTextProperty::New();
sliceTextProp->SetFontFamilyToCourier();
sliceTextProp->SetFontSize(20);
sliceTextProp->SetVerticalJustificationToBottom();
sliceTextProp->SetJustificationToLeft();
vtkTextMapper *sliceTextMapper = vtkTextMapper::New();
// this->sliceTextMapper = vtkTextMapper::New();
std::string msg = StatusMessage::Format(imageViewer->GetSliceMin(),
imageViewer->GetSliceMax());
sliceTextMapper->SetInput(msg.c_str());
sliceTextMapper->SetTextProperty(sliceTextProp);
vtkActor2D *sliceTextActor = vtkActor2D::New();
//this->sliceTextActor = vtkActor2D::New();
sliceTextActor->SetMapper(sliceTextMapper);
sliceTextActor->SetPosition(15, 10);
// usage hint message
vtkTextProperty *usageTextProp = vtkTextProperty::New();
// this->usageTextProp = vtkTextProperty::New();
usageTextProp->SetFontFamilyToCourier();
usageTextProp->SetFontSize(14);
usageTextProp->SetVerticalJustificationToTop();
usageTextProp->SetJustificationToLeft();
vtkTextMapper *usageTextMapper = vtkTextMapper::New();
//this->usageTextMapper = vtkTextMapper::New();
usageTextMapper->SetInput("- Slice with mouse wheel\n or Up/Down-Key\n-
Zoom with pressed right\n mouse button while dragging");
usageTextMapper->SetTextProperty(usageTextProp);
vtkActor2D *usageTextActor = vtkActor2D::New();
//this->usageTextActor = vtkActor2D::New();
usageTextActor->SetMapper(usageTextMapper);
usageTextActor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedDisplay();
usageTextActor->GetPositionCoordinate()->SetValue( 0.05, 0.95);
// create an interactor with our own style (inherit from
vtkInteractorStyleImage)
// in order to catch mousewheel and key events
vtkRenderWindowInteractor *renderWindowInteractor =
vtkRenderWindowInteractor::New();
//this->renderWindowInteractor = vtkRenderWindowInteractor::New();
myVtkInteractorStyleImage *myInteractorStyle =
myVtkInteractorStyleImage::New();
// make imageviewer2 and sliceTextMapper visible to our interactorstyle
// to enable slice status message updates when scrolling through the slices
myInteractorStyle->SetImageViewer(imageViewer);
myInteractorStyle->SetStatusMapper(sliceTextMapper);
imageViewer->SetupInteractor(renderWindowInteractor);
// make the interactor use our own interactorstyle
// cause SetupInteractor() is defining it's own default interatorstyle
// this must be called after SetupInteractor()
renderWindowInteractor->SetInteractorStyle(myInteractorStyle);
// add slice status message and usage hint message to the renderer
imageViewer->GetRenderer()->AddActor2D(sliceTextActor);
imageViewer->GetRenderer()->AddActor2D(usageTextActor);
ui.qvtkWidget->SetRenderWindow(imageViewer->GetRenderWindow());
ui.qvtkWidget->GetRenderWindow()->GetInteractor()->SetInteractorStyle(myInteractorStyle);
imageViewer->Render();
ui.qvtkWidget->update();
}
essaieAppQtVTK::~essaieAppQtVTK()
{
}
Please answer me because I already posted the topic for a week but no one
has replied.
Thank you in advance
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.itk.org/pipermail/insight-users/attachments/20130418/b0ddc9de/attachment-0001.htm>
More information about the Insight-users
mailing list