Problem with displaying cross-hairs on 2D views when using vtkImageResliceMapper -> vtkImageSlice -> vtkImageStack pipeline

ochampao <[email protected]>
Newsgroups gmane.comp.lib.vtk.user
Message-ID <[email protected]>
Hi vtkUsers, 

I am developing a four-pane viewer for displaying medical images. The 3
views display slices of the volumes in the 3 standard anatomical views
(axial, coronal, sagittal) whereas the 4th one displays some 3D surface
rendering of the volume. For now, I will only focus on the 2D views.

The 2D views use the following pipeline: vtkImageResliceMapper ->
vtkImageSlice -> vtkImageStack. This allows the application to overlay
slices from multiple volumes simultaneously. The attached code is a minimal
example of the 2D pipeline I use in my application. The slices displayed are
determined by the focal point of the camera in each 2D view.

What I would like to do is display a set of cross-hairs on each of the 2D
views, but I don't know how to achieve this using the pipeline I am
currently using.

I am aware of the classes: 
vtkResliceCursorWidget, 
vtkResliceCursor, 
vtkResliceCursorLineRepresentation, 
vtkImagePlaneWidget, 
vtkResliceImageViewer

I have tried using these classes (see commented code in attached source
code), but they don't seem compatible with my current pipeline. For example,
when using vtkResliceCursorWidget the cross-hairs are visible and I can
interact with them but slicing stops working. I also see some weird
artefacts around the border of the slice. Also, to use these classes I need
to specify the volume which the reslice cursor will be slicing
(vtkResliceCursor->SetImage(imageData)), but in my case I have multiple
volumes.

I am also aware of and tried using vtkCursor2D/vtkCursor3D. Although they
are close to what I have in mind, they allow very limited customization of
their look.

Essentially what I would like to implement is something that looks like the
cursor of vtkResliceCursorWidget/vtkImagePlaneWidget/vtkResliceImageViewer
but does not handle slicing.

Can someone recommend how can I achieve this, or point me to some
classes/examples? Is their a way of using
vtkResliceCursorWidget/vtkImagePlaneWidget/vtkResliceImageViewer with my
current pipeline, or would I need to change it?

Thanks a lot for your help.
Panos

========================================================
Basic Pipeline Minimal Example
========================================================
#include <vtkCamera.h>
#include <vtkDICOMImageReader.h>
#include <vtkImageChangeInformation.h>
#include <vtkImageData.h>
#include <vtkImageProperty.h>
#include <vtkImageResliceMapper.h>
#include <vtkImageSlice.h>
#include <vtkImageStack.h>
#include <vtkInteractorStyleImage.h>
#include <vtkMath.h>
#include <vtkNIFTIImageReader.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>

#include <vtkResliceCursor.h>
#include <vtkResliceCursorActor.h>
#include <vtkResliceCursorLineRepresentation.h>
#include <vtkResliceCursorPolyDataAlgorithm.h>
#include <vtkResliceCursorWidget.h>

void setupCamera(vtkCamera* camera);
vtkSmartPointer<vtkImageData> loadDicom(const char* filename);
vtkSmartPointer<vtkImageData> loadNifti(const char* filename);

int main(int, char*[])
{
	// Setup renderer
	vtkNew<vtkRenderer> renderer;
	renderer->SetBackground(0.0, 0.0, 0.0);	
	renderer->GetActiveCamera()->ParallelProjectionOn();
	renderer->ResetCameraClippingRange();
	renderer->ResetCamera();

	// Setup renderWindow
	vtkNew<vtkRenderWindow> renderWindow;
	renderWindow->AddRenderer(renderer);

	// Setup interaction style
	vtkNew<vtkInteractorStyleImage> interactorStyle;
	interactorStyle->SetInteractionModeToImageSlicing();

	// Setup window interactor
	vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
	renderWindowInteractor->SetRenderWindow(renderWindow);
	renderWindowInteractor->SetInteractorStyle(interactorStyle);

	// Setup camera
	setupCamera(renderer->GetActiveCamera());

	// Load data from DICOM series
//	vtkSmartPointer<vtkImageData> imageData = 
//		loadDicom("<path_to_DICOM_series>"");

	// Load data from Nifti file
	vtkSmartPointer<vtkImageData> imageData =
		loadNifti("<path_to_nii_file>");

	// setup slice mapper
	vtkNew<vtkImageResliceMapper> resliceMapper;
	resliceMapper->SetInputData(imageData);
	resliceMapper->SliceFacesCameraOn();
	resliceMapper->SliceAtFocalPointOn();
	resliceMapper->JumpToNearestSliceOn();
	resliceMapper->BorderOff();

	// Set to full window and centered level:
	double window = imageData->GetScalarRange()[1] -
imageData->GetScalarRange()[0];
	double level = imageData->GetScalarRange()[0] + window / 2.0;

	// Setup prop holding the slice
	vtkNew<vtkImageSlice> imageSlice;
	imageSlice->SetMapper(resliceMapper);
	imageSlice->GetProperty()->SetColorWindow(window);
	imageSlice->GetProperty()->SetColorLevel(level);
	imageSlice->GetProperty()->SetLayerNumber(0);
	imageSlice->GetProperty()->SetInterpolationTypeToNearest();
	
	// Setup prop holding the multiple slices
	vtkNew<vtkImageStack> imageStack;
	imageStack->SetActiveLayer(imageSlice->GetProperty()->GetLayerNumber());
	imageStack->AddImage(imageSlice); // add slice

	vtkNew<vtkResliceCursor> resliceCursor;
	resliceCursor->SetCenter(imageData->GetCenter());
	resliceCursor->SetThickMode(0);
	resliceCursor->SetImage(imageData);

	vtkNew<vtkResliceCursorLineRepresentation> cursorRepresentation;
	cursorRepresentation->GetResliceCursorActor()->
           GetCursorAlgorithm()->SetResliceCursor(resliceCursor);
	cursorRepresentation->GetResliceCursorActor()->
            BasicPipeline.cxx
<http://vtk.1045678.n5.nabble.com/file/t341857/BasicPipeline.cxx> 
GetCursorAlgorithm()->SetReslicePlaneNormal(2);

	vtkNew<vtkResliceCursorWidget> resliceCursorWidget;
	resliceCursorWidget->SetInteractor(renderWindowInteractor);
	resliceCursorWidget->SetDefaultRenderer(renderer);
	resliceCursorWidget->SetRepresentation(cursorRepresentation);
	resliceCursorWidget->SetManageWindowLevel(false);
	resliceCursorWidget->EnabledOn();
	//resliceCursorWidget->ProcessEventsOff();

	// Add actors to renderer
	renderer->AddViewProp(imageStack);
	renderer->ResetCamera(); 

	// Start interaction
	renderWindowInteractor->Initialize();
	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

void setupCamera(vtkCamera* camera)
{
	double viewUp[3] = { 0, 1, 0 };
	double leftToRight[3] = { 1, 0, 0 };

	// compute the view plane normal
	double normal[3];
	vtkMath::Cross(leftToRight, viewUp, normal);

	// get the camera focus
	double focus[3];
	camera->GetFocalPoint(focus);

	// get the camera distance from the focus
	double d = camera->GetDistance();

	// position the camera on view plane normal keeping the focus and the
distance from it fixed
	camera->SetPosition(
		focus[0] + d*normal[0],
		focus[1] + d*normal[1],
		focus[2] + d*normal[2]);

	// make sure focus is the same
	camera->SetFocalPoint(focus);

	// setup view up vector
	camera->SetViewUp(viewUp);
	camera->OrthogonalizeViewUp();
}

vtkSmartPointer<vtkImageData> loadDicom(const char* filename)
{
	vtkNew<vtkDICOMImageReader> reader;
	reader->FileLowerLeftOn();
	reader->SetDirectoryName(filename);
	reader->UpdateInformation();

	vtkNew<vtkImageChangeInformation> imageInfo;
	imageInfo->SetOutputOrigin(0.0, 0.0, 0.0);
	imageInfo->SetOutputSpacing(reader->GetPixelSpacing());
	imageInfo->SetInputConnection(reader->GetOutputPort());
	imageInfo->Update();

	return imageInfo->GetOutput();
}

vtkSmartPointer<vtkImageData> loadNifti(const char* filename)
{
	vtkNew<vtkNIFTIImageReader> niftiiReader;
	niftiiReader->SetFileName(filename);

	vtkNew<vtkImageChangeInformation> imageInfo;
	imageInfo->SetOutputOrigin(0.0, 0.0, 0.0);
	imageInfo->SetInputConnection(niftiiReader->GetOutputPort());
	imageInfo->Update();

	return imageInfo->GetOutput();//data;
}





--
Sent from: http://vtk.1045678.n5.nabble.com/VTK-Users-f1224199.html
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ

Search the list archives at: http://markmail.org/search/?q=vtkusers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtkusers
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.