IN4086P Volume Visualisation
Welcome to the Wonderful World of Wolume Wisualisation! In this exercise, you will learn how to apply the three basic volume visualisation techniques (MPR, surface extraction and DVR) to a medical dataset. All three of these techniques originated from visualization research and are now a valued tool in clinical practice.
IMPORTANT NOTE: For the shading part of this exercise, you need a specially modified ParaView. The Linux installation at the Drebbelweg has already been modified. If you want to make use of your own build, please use the patch appropriate for your version: ParaView 3.2 / ParaView 3.4 This patch is only relevant if you want to compile your own ParaView and you want to activate shading during direct volume rendering. In this case you'll also want to activate Python support in the CMake configuration.
Loading the data
Especially for you, we have prepared a DICOM dataset containing an abdominal angiogram acquired on a 16 detector CT scanner of a patient with an abdominal aortic aneurysm (AAA). DICOM, or Digital Imaging and Communications in Medicine, is a specification for file formats and communication protocols that are used by most medical imaging equipment. Because ParaView can't read DICOM directly, we've pre-converted the data to the VTI format. Whilst we were at it, we image processed away certain external structures (for example the table that the patient was lying on) and downsampled the data with a cubic interpolation filter in order to facilitate this exercise. The dataset filename is panoramix_m_voi_0.8.vti. Download and unpack the zip archive containing this file from the in4086p dataset page.
|
Load the dataset. What are the dimensions (X x Y x Z) of the data? What is the range of the associated scalars? (minimum value, maximum value) Why are there negative values? |
MPR visualisation
MPR, or multi-planar reconstruction / reformatting, is the most basic and probably most popular volume visualisation technique, and refers to the interpolation of an arbitrary slice of data from a volume. The scanner usually has a primary slicing direction, often axial. With MPR, coronal or saggital slices, or even oblique slices, can also be extracted from the data.
|
Use a Slice filter to slice through the data. Load a greyscale colour map so that your visualisation looks like the image below. |
|
Use Slice filters to slice through the data axially, coronally and saggitally as well as obliquely. Demonstrate this to your assistant. Find out what an abdominal aortic aneurysm is and then try to locate it using your MPRs. |
Extracting surfaces
The well-known Marching Cubes algorithm can be used to extract triangulated iso-surfaces directly from volume data.
|
Explain to the assistant what an iso-surface is. Also explain how the Marching Cubes algorithm works. |
To be able to extract meaningful iso-surfaces from medical data, one needs to derive suitable iso-values first. There are several ways to do this. One could make use of a histogram to get an idea of the distribution of scalar values in the data.
|
Create a histogram of the complete loaded CT dataset. Increase the number of bins so that you can get a good idea of the distribution. |
One can also probe (sample) the data more directly. In ParaView, this is done by making use of the selection interface. Activate View | Selection Inspector, and in the window that appears make sure that your slice is the Current Object, that Selection Type is set to IDs and Field Type to POINT. Now click on the Create Selection button. On the Point Label tab at the bottom, set Visible to on and Label Mode to Scalars_. Now deselect everything in the Pipeline Browser.
Now you can select the Point Selection tool (icon in the bar at the top with a triangle with 3 red corners) and then click on the slice to see the intensity at that position.
Continue using the point selection tool, and then clicking somewhere on one of your slices. It should show the scalar value at that point.
|
Setup and demonstrate the point selection interface. What are the scalar values of bone, of air and of muscle? Do these correlate with the published standard CT values that you find on-line? |
Based on the histogram and direct probing, one can experiment with thresholding to determine which threshold values reveal interesting structures in the data. ParaView Linked Views, explained in the first question along with histograms, are useful when doing this type of exploration. We will now see how.
|
Create a new 3D View and link it to your existing view with the slices. Connect a Threshold filter to the output of one of your Slice filters and show its output in the new linked view you have created. Experiment with the threshold value to find interesting stuctures (bone, air, vessels) in the data. Demonstrate to your assistant. |
You should now have a good idea of the scalar makeup of the CT dataset that you are working with.
|
Make use of different Contour filters, together with a Clip filter, to create a visualisation similar to the one below. Use your imagination. You can demonstrate any other visualisation of this data that includes at least two structures of interest and a Clip filter to your assistant. |
Direct volume rendering
Now the fun really starts! Direct Volume Rendering (DVR) is a technique for the direct visualisation of volume data. Please study the linked wikipedia article. What's not explicitly mentioned in the article, is that there are two main types of DVR, image-order, for example raycasting, and object-order, for example splatting.
|
Study the two linked articles, and pay special attention to raycasting and splatting. Explain both of these techniques to your assistant. Based on your understanding of these techniques, explain the difference between image-order and object-order DVR techniques. |
ParaView supports the raycasting type of DVR. Recall that in raycasting, there is a strong relation between the size of the rendered image and the speed at which it can be rendered. Practically, this means that if you zoom out far enough, you will get high interactivity in return. This is useful when you are tuning raycasting parameters for example. Zoom out, tune, zoom in for a final high quality view.
|
Make your first simple volume rendering: change the representation of of the loaded dataset to "Volume" by selecting the dataset, going to the "Display" tab of the Object Inspector and changing the "Representation" drop-down list to "Volume". Marvel at the prettiness you see before you. |
An important element of DVR is the transfer function. This function maps data values to optical characteristics, such as colour and opacity. In raycasting, it is applied at every step of the integration, usually after the sampled data value has been interpolated. This was also discussed in the wikipedia page on Volume Rendering, which you studied a few paragraphs ago.
|
Make a volume rendering of the skeleton by modifying the transfer function. The transfer function can be accessed by going to the "Display" tab of the Object Inspector whilst the input dataset is selected in the Pipeline Browser. Of course ParaView could use another name for this. Your volume rendering should be similar to the one below. |
Up to now, you have been using a straight-forward raycasting implementation without shading. Each interpolated volume sample is transformed to a colour and opacity via the transfer function and then accumulated with other values along its ray using the volume rendering integral. However, in most modern volume rendering implementations, lighting (shading) is also integrated. This entails that the effect of light (under the Phong model ambient, diffusive and specular light) is simulated, based on the image gradient and the looked-up colour and opacity.
You are now going to activate shading in ParaView! The ParaView GUI does not yet support this, so we have hacked the source to make it possible via the Python scripting interface. Activate this interface by selecting "Tools | Python Shell" from the main menu. Cut and paste the following script into the scripting interface, line by line using Ctrl-C Ctrl-V (middle button paste will NOT work, due to Qt). If you have multiple views, the index to GetRenderView should correspond to the view containing the volume rendering.
1 from paraview import servermanager
2 view = servermanager.GetRenderView(0)
3 names = [i.__class__.__name__ for i in view.Representations]
4 r_idx = names.index('UniformGridRepresentation')
5 r = view.Representations[r_idx]
6 r.Shade = 1
7
|
Make the same skeleton volume rendering as above, but with shading activated. It should look (more or less) like the image below. Try to explain the differences in appearance based on what you know about the lighting model. |
There are some beautiful examples of direct volume rendering on the web. See for example the Voreen image gallery, or do a Google Image Search for "direct volume rendering". One of the most important factors in creating good volume renderings is a suitable transfer function. In ParaView, you can zoom out to get faster updates as you finetune the transfer function (as explained above). You could also consider using the "Extract Subset" filter to extract an interesting sub-volume of the dataset and focus on that.
|
Spend some time on creating the best transfer function you can. Try to make more structures visible (and give them unique colours) than just the skeleton. Show your rendering and transfer function to the assistant. Below is a simple example showing the transfer function and the resultant rendering. |
|
|



