Project 2, CS 526: Allan Spale (aspale@evl.uic.edu)
Background
This program was written
using Python 2.1, VTK 4.2, and Tkinter (a Python module that supports GUI
widgets) and allows a user to visualize predefined datasets of the Visible
Woman. The files for the project are
simply project2.py. To run the program, type the following: python project2.py. Since Python is an interpreted language,
there is no need to compile; although there is an ability to compile a Python
script to decrease the startup time. The
program meets most of the basic requirements for displaying the requested
visualizations. Some additional
functionality was provided which will be described in the next section.
Sources
The sources of information
used to create this code include the following:
·
Python in a Nutshell, ISBN 0596001886 (used source as guideline to
construct GUI classes)
·
VTK Book,
ISBN 1930934076
·
Websites
o An
Introduction to Tkinter
o VTK Docs
o Python Docs
·
VTK Tk/Tcl
example code
·
Recommendations and
suggestions of other classmates
Usage
The GUI for this program is
a bit better than the first project.
However, there were some difficulties with getting stuff to appear as it
should. To simplify storing properties
for the VTK actors, the data was stored in the class used to create the dialog
windows. Because it was not as
straightforward as it seemed to make a fully functional modal dialog window and to keep the data persistent, the
dialog windows appear as soon as the program begins. They are accessible via the menu or the task
bar, but they may not be closed at any
time lest that dialog box not appear again.
An improvement over the last project was to increase the font size of
the widget objects in order to make them more readable. Unfortunately, this is counterbalanced with
some odd alignment with the label value that describes the value of the slider. Also related to the slider is that
fine-grained control regardless of the range of values is too-fined
grained. That is, each mouse click in
the non-button area of the slider click moves the slider a value of 1. However, moving the slider varies depending
on the range of values for that particular slider.
Generally, the program still
generally functions as one would expect without too many surprises. Using some combination of dataset and
visualization selections, it may be possible for the opacity function to stop
working and/or contours get a bit “noisy”.
For this reason, the author recommends going in menu order (head:
isosurface, raycast-composite, raycast-mip, feet: isosurface,
raycast-composite, raycast-MIP). This
may have been an anomaly that cannot be repeated, but for effective evaluation
of the visualizations, it is recommended that the user follows the above order.
To simplify matters, the
Female.raw file’s location was hard-coded to appear in the current directory
where the Python program resides. In
order to update the visualization, it is necessary to click in the rendering
window. It seemed fairly certain that a
recommendation from my classmate would have fixed the problem on how to code
this properly; unfortunately, this was not the case.
One other glaring problem
occurs with visualizing the feet dataset with raycasting. There is some odd clipping that occurs such
that the feet cannot be “zoomed into” directly.
For this reason, it is best to first visualize the feet using the
isosurface visualization, and then change to one of the raycast visualizations
of the feet. If the feet remain along
the edges when zooming in, this dataset will be better controlled. It seems that when a sampling rate is used
other than 1 (worked in the author’s test for 3, 3, 1), the clipping problem
seemed to subside somewhat.
By default, the joystick
control style (‘j’) is used to control the visualization. It can be turned off by pressing the ‘t’ key for
the trackball style of control.
There is no serious error
checking, but, fortunately, the GUI is presented in such a way as to strongly
eliminate any potential “syntax errors” but not logic errors (i.e. forgetting
that a surface was set to 0% opacity).
The menus are used in the
following manner:
Menus
·
Since the file
is “hard coded”, the only option here is to quit the program. To quit the program, either close the “main
window” (i.e. the one with the menu) or select Exit.
·
To visualize the
data, select two items from the two sections in the Visualization menu. The
available options for the first section are the visualization types which
include: Isosurface, Raycast-Composite, and Raycast-MIP (i.e. Maximum Instensity
Projection). The second section selecting
the dataset to view— Head or Feet.
Both of these also include a bit more of the body than there names would
literally imply. These menu selections
directly control what appears in the visualization, so no dialog window appears
for any of these menu selections. When
the program begins, isosurface is the default visualization and head is the
default dataset. More details about the
menu are as follows:
o Isosurfaces uses a marching cubes visualization to display predefined
single isovalue. In this case, bone is
determined to be a value of 860. Skin is
determined to be a value of 1250. This
visualization is the easiest to use to experiment with viewing the dataset.
o Raycast-Composite uses a raycast composite function to visualize the
data. Because of poor performance by
selecting a single isovalue, ranges of isovalues are displayed for the skin and
bone isosurfaces. The actual range of
isosurfacfes displayed are very counterintuitive and were determined very much
by accident. Nonetheless, they seem to
present the best visualization that the author of the program could come up
with. The VTK Piecewise function used
for opacity displays a range of values 1250-5000 at increments of 10 for the
bone, and range of 860-1060 at increments of 5.
As determined by the author of this program, it is recommended to use an
opacity value of 100% for the bone and 5% for the skin. The VTK Color Transfer function was used for
the coloring of the isosurfaces. The
skin used a range of 860-960 at increments of 1, while the bone used a range of
1250-1509 at increments of 1. The bone
appears best when set to RGB value (255,255,255), while skin looks best as an
orange flesh-tone (in this author’s simple opinion and considering the fact no one
looks orange unless the individual has liver problems) with RGB value (255,140,81).
o Raycast-MIP uses a raycast maximum intensity projection function
to visualize the data. Again, because of
poor performance by selecting a single isovalue, ranges of isovalues are displayed
for the skin and bone isosurfaces. The
author was unable to get a suitable visualization for the bone that allows the
features of the bone to appear. Rather,
it appears more as a “solid silhouette” from all angles. The VTK Piecewise function used for opacity displays
a range of values 1250-5000 at increments of 1 for the bone, and range of 860-870
at increments of 1. As determined by the
author of this program, it is recommended to use an opacity value of 70% for
the bone and 50% for the skin. The VTK
Color Transfer function was used for the coloring of the isosurfaces. The skin used a range of 860-870 at
increments of 1, while the bone used a range of 1250-5000 at increments of 100. To keep colors similar to the other raycasting
visualization, the author recommends using an RGB value (255,255,255) for the
bone and an RGB value (255,140,81) for the skin.
o Head will display slices 0-100 from the entire dataset.
o Feet will display slices 500-576 from the entire
dataset.
·
To change some
of the options of how the dataset, select an item from the Options menu.
o Dataset
Properties allows the user to change
the RGB and opacity values a selected isosurface/tissue— bone or skin. As a benefit for the user, the current values
selected for red, green, and blue are blended together for the user to
see. Please note, when the user is done using this dialog box, it should be minimized and
not closed in order to avoid losing
the dialog window completely. Also
it is important to know that changes are
updated when the user clicks in the visualization portion of the main
window.
o Global Level
of Detail, allows the user to change
the sampling rate of the length (x-axis) and width (y-axis) of the slice in
addition to the number of slices (z-axis) used to define the model. The values for setting each of the axes range
from 1-8. Since the dimensions of the
entire dataset is 256x256x577, selecting a value results in dividing the
resolution for that axis by the value for the slider. These values can be set independently of one
another. To somewhat reduce the
unpleasantness of sampling, a polygon smoothing function is used by the render
to smooth the surfaces, regardless of what sampling values are used.
Design
There is a class that takes
care of all of the rendering. In the
constructor part of this class, all of the visualization pipeline parts are
created. Objects mapped to the renderer
are usually done in a way appropriate for the visualization. Below is the contruction of the pipelines:
readerVolume
[vtkImageReader]
|
+-- voiFeet [vtkExtractVOI]
| |
| +--
mapperCompFeet [vtkVolumeRayCastMapper]
| | |
| | +-- SetVolumeRayCastFunction
| | |
| | +-- compositeFunction [vtkVolumeRayCastCompositeFunction]
| |
| +--
mapperMIPFeet [vtkVolumeRayCastMapper]
| | |
| | +-- SetVolumeRayCastFunction
| | |
| | +-- compositeFunctionMIP [vtkVolumeRayCastCompositeFunction]
| |
| +-- contourBoneFeet
[vtkMarchingCubes]
| | |
| | +-- geoVolumeBone [vtkPVGeometryFilter]
| | |
| | +-- geoBoneMapper
[vtkPolyDataMapper]
| | |
| | +-- actorBone [vtkLODActor]
| |
| +-- contourSkinFeet
[vtkMarchingCubes]
| |
| +-- geoVolumeSkin [vtkPVGeometryFilter]
| |
| +-- geoSkinMapper
[vtkPolyDataMapper]
| |
| +-- actorSkin [vtkLODActor]
|
|
+-- voiHead [vtkExtractVOI]
| |
| +--
mapperCompHead [vtkVolumeRayCastMapper]
| | |
| | +-- SetVolumeRayCastFunction
| | |
| | +-- compositeFunction [vtkVolumeRayCastCompositeFunction]
| |
| +--
mapperMIPHead [vtkVolumeRayCastMapper]
| | |
| | +-- SetVolumeRayCastFunction
| | |
| | +-- compositeFunctionMIP [vtkVolumeRayCastCompositeFunction]
| |
| +-- contourBoneHead
[vtkMarchingCubes]
| | |
| | +-- geoVolumeBone [vtkPVGeometryFilter]
| | |
| | +-- geoBoneMapper
[vtkPolyDataMapper]
| | |
| | +-- actorBone [vtkLODActor]
| |
| +-- contourSkinTop
[vtkMarchingCubes]
| |
| +-- geoVolumeSkin [vtkPVGeometryFilter]
| |
| +-- geoSkinMapper
[vtkPolyDataMapper]
| |
| +-- actorSkin [vtkLODActor]
volumePropertyComp
[vtkVolumeProperty]
|
+-- SetScalarOpacity
| |
| +--
opacityFunctionComp [vtkPiecewiseFunction]
|
+-- SetColor
|
+-- colorTransferFunctionComp [vtkColorTransferFunction]
volumeComp
[vtkVolume]
|
+-- SetMapper
| |
| +--
mapperCompHead [vtkVolumeRayCastMapper]
| |
| +-- mapperCompFeet [vtkVolumeRayCastMapper]
|
+-- SetProperty
|
+-- volumePropertyComp [vtkVolumeProperty]
volumePropertyMIP
[vtkVolumeProperty]
|
+-- SetScalarOpacity
| |
| +--
opacityFunctionMIP [vtkPiecewiseFunction]
|
+-- SetColor
|
+-- colorTransferFunctionMIP [vtkColorTransferFunction]
volumeMIP
[vtkVolume]
|
+-- SetMapper
| |
| +--
mapperMIPHead [vtkVolumeRayCastMapper]
| |
| +-- mapperMIPFeet [vtkVolumeRayCastMapper]
|
+-- SetProperty
|
+-- volumePropertyMIP [vtkVolumeProperty]
Images
Please note,
the images taken here were before polygon smoothing was added to the program.
Opening
screenshot
Surface
properties dialog
Sampling
sizes dialog
All
images, unless otherwise noted, were taken at the original dataset resolution.
Isosurface
of head dataset
Raycasting
using a composite function on the head dataset
Raycasting
using a maximum intensity projection function on the head dataset
Isosurface
of feet dataset
Raycasting
using a composite function on the feet dataset
Because
of the clipping problem with the feet, here is an enlarged, somewhat
out-of-proportion enlargement of the same visualization.
Raycasting
using a maximum intensity projection function on the feet dataset (enlarged and
not proportionate)
Sampling
of the dataset resolution is also possible.
In addition to dividing the resolution by the specified resolutions,
here is a ~ 85x85x1 of the head and feet: