Here is a simple demo project which draws an ITK RGBA image and show it in vtkRenderer. We will read DICOM data and put the ITK image above vtkImageData.
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(testITK)
# Find ITK.
find_package( ITK REQUIRED )
include( ${ITK_USE_FILE} )
# Find VTK.
find_package( VTK REQUIRED )
include( ${VTK_USE_FILE} )
add_executable(${PROJECT_NAME} "main.cpp" "ULabelImage.h" "ULabelImage.cpp" "point.hpp")
target_link_libraries( ${PROJECT_NAME} ${VTK_LIBRARIES} ${ITK_LIBRARIES} )
ULabelImage.h
#pragma once
#include <itkRGBAPixel.h>
#include <itkImageIOBase.h>
#include <itkImage.h>
#define CPP_GET_MACRO(name,type) \
type Get##name() \
{ \
return this->name; \
}
class ULabelImage
{
public:
using PixelType = itk::RGBAPixel<unsigned char>;
using ImageType = itk::Image<PixelType, 2>;
ULabelImage(ImageType::IndexType imgStart, ImageType::SizeType imgSize);
CPP_GET_MACRO(m_Image, ImageType::Pointer);
CPP_GET_MACRO(m_ImgSize, ImageType::SizeType);
protected:
ImageType::Pointer m_Image;
ImageType::SizeType m_ImgSize;
};
ULabelImage.cpp
#include "ULabelImage.h"
#include <itkImageRegionIterator.h>
ULabelImage::ULabelImage(ImageType::IndexType imgStart, ImageType::SizeType imgSize)
: m_Image( ImageType::New() )
{
ImageType::RegionType region;
ImageType::IndexType start = { imgStart[0], imgStart[1] };
m_ImgSize = { imgSize[0], imgSize[1] };
region.SetSize(m_ImgSize);
region.SetIndex(start);
m_Image->SetRegions( region );
m_Image->Allocate();
itk::ImageRegionIterator<ImageType> imageIterator(m_Image, region);
while (!imageIterator.IsAtEnd())
{
ImageType::PixelType pixel = imageIterator.Get();
pixel.SetRed(255);
pixel.SetGreen(0);
pixel.SetBlue(0);
pixel.SetAlpha(100);
imageIterator.Set(pixel);
++imageIterator;
}
}
main.cpp
#include <iostream>
#include <itkImage.h>
#include <itkGDCMImageIO.h>
#include <itkGDCMSeriesFileNames.h>
#include <itkImageSeriesReader.h>
#include <itkImageToVTKImageFilter.h>
#include <itkPointSet.h>
#include <itkObject.h>
#include <vtkImageActor.h>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <string>
#include <vtkImageMapToWindowLevelColors.h>
#include <vtkInformation.h>
#include <vtkStreamingDemandDrivenPipeline.h>
#include <vtkLookupTable.h>
#include <vtkImageMapper.h>
#include <vtkActor2D.h>
#include "point.hpp"
#include "ULabelImage.h"
using namespace std;
using PixelType = signed short;
using ImageType3D = itk::Image<PixelType, 3>;
using ImageType2D = itk::Image<PixelType, 2>;
using ImageIoType = itk::GDCMImageIO;
using NamesGeneratorType = itk::GDCMSeriesFileNames;
using ReaderType3D = itk::ImageSeriesReader<ImageType3D>;
using ConnectorType3D = itk::ImageToVTKImageFilter<ImageType3D>;
using ConnectorType2D = itk::ImageToVTKImageFilter<ImageType2D>;
using MetaDataStringType = itk::MetaDataObject<std::string>;
int main( int argc, char *argv[] )
{
ReaderType3D::Pointer ImageReader3D = ReaderType3D::New();
ImageIoType::Pointer dicomIO = ImageIoType::New();
ImageReader3D->SetImageIO(dicomIO);
std::string folder = argv[1];
NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New();
nameGenerator->SetDirectory(folder);
using FilenamesContainer = std::vector<std::string>;
FilenamesContainer fileNames = nameGenerator->GetInputFileNames();
ImageReader3D->SetFileNames(fileNames);
try
{
ImageReader3D->Update();
}
catch (itk::ExceptionObject &ex)
{
std::cout << ex << std::endl;
return -2;
}
ConnectorType3D::Pointer ImageConnector3D = ConnectorType3D::New();
ImageConnector3D->SetInput(ImageReader3D->GetOutput());
try
{
ImageConnector3D->Update();
}
catch (itk::ExceptionObject & ex)
{
std::cout << ex << std::endl;
return -3;
}
double ColorLevel;
double ColorWindow;
const itk::MetaDataDictionary& dictionary = dicomIO->GetMetaDataDictionary();
auto itr = dictionary.Begin();
auto end = dictionary.End();
std::string entryId = "0028|1050";
auto tagItr = dictionary.Find(entryId);
if (tagItr != end)
{
MetaDataStringType::ConstPointer entryvalue =
dynamic_cast<const MetaDataStringType*> (tagItr->second.GetPointer());
if (entryvalue)
{
std::string tagvalue = entryvalue->GetMetaDataObjectValue();
ColorLevel = stod(tagvalue);
}
}
entryId = "0028|1051";
tagItr = dictionary.Find(entryId);
if (tagItr != end)
{
MetaDataStringType::ConstPointer entryvalue =
dynamic_cast<const MetaDataStringType*> (tagItr->second.GetPointer());
if (entryvalue)
{
std::string tagvalue = entryvalue->GetMetaDataObjectValue();
ColorWindow = stod(tagvalue);
}
}
vtkSmartPointer<vtkImageMapToWindowLevelColors> imgToColors = vtkSmartPointer<vtkImageMapToWindowLevelColors>::New();
imgToColors->SetInputData( ImageConnector3D->GetOutput() );
imgToColors->SetLevel( ColorLevel );
imgToColors->SetWindow( ColorWindow );
imgToColors->Update();
vtkImageData *data = imgToColors->GetOutput();
vtkAlgorithm *alg = imgToColors->GetInputAlgorithm();
vtkInformation* outInfo = alg->GetOutputInformation(0);
int *w_ext = outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT());
vtkSmartPointer<vtkImageActor> actor = vtkSmartPointer<vtkImageActor>::New();
actor->SetInputData( data );
int slice = (w_ext[4] + w_ext[5])/2;
actor->SetDisplayExtent( w_ext[0], w_ext[1], w_ext[2], w_ext[3], slice, slice );
vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
ren->AddActor( actor );
vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
renWin->AddRenderer( ren );
vtkSmartPointer<vtkRenderWindowInteractor> iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();
iren->SetRenderWindow( renWin );
iren->Initialize();
vtkSmartPointer<vtkInteractorStyleImage> iStyle = vtkSmartPointer<vtkInteractorStyleImage>::New();
iren->SetInteractorStyle( iStyle );
ren->AddActor( actor );
renWin->SetSize( 800, 800 );
renWin->Render();
ren->ResetCamera();
renWin->Render();
// -------------- show image --------------
double *bds = data->GetBounds();
Point origin;
ren->SetWorldPoint( bds[0], bds[2], bds[4], 0 );
ren->WorldToDisplay();
ren->GetDisplayPoint( origin.point );
double size[3];
Point axis1Vec;
ren->SetWorldPoint( bds[1], bds[2], bds[4], 0 );
ren->WorldToDisplay();
ren->GetDisplayPoint( axis1Vec.point );
Point axis2Vec;
ren->SetWorldPoint( bds[0], bds[3], bds[4], 0 );
ren->WorldToDisplay();
ren->GetDisplayPoint( axis2Vec.point );
Point axis3Vec;
ren->SetWorldPoint( bds[0], bds[2], bds[5], 0 );
ren->WorldToDisplay();
ren->GetDisplayPoint( axis3Vec.point );
size[0] = (axis1Vec - origin).Length();
size[1] = (axis2Vec - origin).Length();
size[2] = (axis3Vec - origin).Length();
std::cout << "size: " << size[0] << ", " << size[1] << ", " << size[2] << std::endl;
ULabelImage::ImageType::SizeType imgSize = { int(size[0]+0.5), int(size[1]+0.5) };
ULabelImage::ImageType::IndexType imgStart = { int(origin[0]+0.5), int(origin[1]+0.5) };
ULabelImage *image = new ULabelImage( imgStart, imgSize );
using ConnectorType = itk::ImageToVTKImageFilter<ULabelImage::ImageType>;
auto connector = ConnectorType::New();
connector->SetInput(image->Getm_Image());
connector->Update();
std::cout << "cells: " << connector->GetOutput()->GetNumberOfCells() << std::endl;
vtkSmartPointer<vtkActor2D> actor2D = vtkSmartPointer<vtkActor2D>::New();
vtkSmartPointer<vtkImageMapper> imgMapper = vtkSmartPointer<vtkImageMapper>::New();
imgMapper->SetColorWindow( 256 );
imgMapper->SetColorLevel( 128 );
imgMapper->SetInputData( connector->GetOutput() );
actor2D->SetMapper( imgMapper );
ren->AddActor( actor2D );
// -------------- finish: show image --------------
iren->Start();
return 0;
}