Example 21e1: Digitising a series of images

Digitising points around images

This document and the digitisation com file have been adapted from CMISS example as

Note: This example is used to digitise the epicardial surface. You can see in the ../cmiss_input directory that there is data from scanning all three surfaces required to create a volume mesh of the heart, ie lv endo and rv inner ring services.

The first step in fitting a surface mesh to a series of MR images is to create a 'data cloud' - a collection of points in 3d space that lie on the epicardial surface of the heart that has been scanned. This is done by loading each image slice into cmgui, calculating where the image lies in 3d space and then 'clicking' points around the edge of each image, thus building up a 3d data set.

Setting up the image in 3d space in cmgui

The first step in digitising an image in cmgui is to relate the image to it's actual size and location in 3d space. We will assume that we have a bunch of images in a directory somewhere, lets call it images, and they are numbered sequentially from 001.rgb to 128.rgb. Each of these images are going down through the heart, starting at approximately the top of the ventricles. Some data about the size of the images:

Start up cmgui by typing cmgui at the prompt:

cmgui &
We will start by setting a perl variable for the slice we are up to:
$slice_num = "001"
Now set up pertinent information about the slices (note that a # symbol denotes that everything after it is a comment:
$height = 76.8
$width = 76.8
$xpixel = 512
$ypixel = 512
$xscale = $xpixel/$width 
$yscale = $ypixel/$height
$zdist = 0.6 # Each image is 0.6 mm apart
We will now create a cmgui texture of the image, giving it the same name as $slice_num:
gfx create texture $slice_num image "../../images/$slice_num.rgb" height $height width $width
We will now calculate where the image is in 3d space:
$xorigin = 0.0 # We will set the image up so that it is  
$yorigin = 0.0 # based around an origin of 0,0,0
$zorigin = 0.0

$xbottom = $xorigin - $width/2.0  # The x,y positions
$ybottom = $yorigin - $height/2.0 # of the bottom left hand corner
$xtop = $xorigin + $width/2.0     # and the top right hand corner
$ytop = $yorigin + $height/2.0    

$z = $zorigin - $zdist*($slice_num - 1); # The z position taking into
                                         # account what slice we are
                                         # up to
Now calculate the near and far clipping planes that the image is to lie within, and also where the 'eye' point is (ie where you are looking from):
$cp_dist = 500 # The distance between $z and the viewer eye_point
$cp_near = $cp_dist - 300
$cp_far = $cp_dist + 300

$zeyepoint = $z + $cp_dist
Now calculate the viewing angle (in degrees). This is the angle between the point at which you are looking from (ie, $zeyepoint) and the diagonal span of the image:
# Calculate the diagonal length of the image
$diag_dist = sqrt($height*$height + $width*$width)

# Calculate the viewing angle (need perl libraries for these functions)
$view_angle = 2.0*(rad2deg(atan2($diag_dist/2,$cp_dist)))
We will now set the texture in the graphics window. This has several parts: The cmgui command to do all this is, using the variables we have set up before:
# First create the graphics window
gfx create window 1

gfx modify window 1 view eye_point $xorigin $yorigin $zeyepoint interest_point $xorigin $yorigin $z  up_vector 0 1 0 near_clipping_plane $cp_near far_clipping_plane $cp_far parallel view_angle $view_angle viewport_coordinates $xbottom $ytop $xscale $yscale  absolute_viewport ndc_placement $xbottom $ytop $width $height

Now draw the slice texture. This texture can be moved around and zoomed upon using the middle and right mouse buttons and dragging the mouse. Doing this will not affect where the points you digitise are located in space.
gfx modify window 1 background texture $slice_num tex_placement $xbottom $ybottom $width -$height

Creating the tools to digitise the points

Having set up the image in 3d space, we now have to create the tools to 'click points' on the image and record these points in cmgui. This is done by using the following commands:

# Create a node group for the digitised points
gfx create ngroup $slice_num 

# Create a material for the 'points' to be displayed in the 3d window
gfx create material gold amb 1 0.4 0 diff 1 0.7 0 spec 0.5 0.5 0.5 shininess 0.8

# Create how the points will look when created in the 3d window
gfx modify g_element $slice_num node_points glyph cross size 1 material gold label cmiss_number select_on

# Create a field to store the coordinates that are created when you create the points
gfx define field coordinates finite_element number_of_components 3 real coordinate component_names x y z

# Bind the node tool to the coordinate group 
gfx node_tool group $slice_num coordinate_field coordinates edit create

# Set the node_tool as the current tool in the graphics window. This
# can also be done by clicking on the node icon in the 3d window
gfx modify window 1 set node_tool

Digitising the points

You can now start clicking points. After clicking on a few, you should get something like this in the 3d window:

Repeating the process

The above process is good for one MR image, but what happens when you've got 128 of them. What should happen to do the whole process is to put a few of the commands into a com file, and then call this comfile from cmgui, changing the variable $slice_num before it is called so it sets up all the parameters correctly. Fortunately, some com files have been already written for you ! These can be seen in:

Creating a data file for input into cm

Once you have created all the nodes that you require you must then write out a .exnode file of all the data points. Do this by doing the following:

gfx write node epi
Having created a .exnode file you must then convert it to a .ipdata file for input into cm. You can do this by using an awk script written for this purpose. The script is installed in CMISS_ROOT/cmiss_utils/data_utils/exnode_to_ipdata.sh


The comfile run by this example is as follows:

#Example 21e1

# This example borrows heavily from example as, but does
# include more set up variables to make it more useful.

$\ = "\n"; # Setting the record separator so that 
           # any prints are echoed straight to the screen.

# Create some materials to be used for display
gfx create material gold amb 1 0.4 0 diff 1 0.7 0 spec 0.5 0.5 0.5 shininess 0.8

# Create a coordinate field to store the data points in
gfx define field coordinates finite_element number_of_components 3 real coordinate component_names x y z

$height = 76.8; # Height of image = 76.8 mm
$width = 76.8; # Same as height

$xpixel = 512; # Each image will be 512 x 512 pixels
$ypixel = 512;
$xscale = $xpixel/$width;
$yscale = $ypixel/$height;
$zdist = 0.6; # Each image is 1.2mm apart in the z direction

# The top image will have it's centre located at (0,0,0), with
# each subsequent image $zdist further down on the xy plane
$xorigin = 0.0;
$yorigin = 0.0;
$zorigin = 0.0;
$xbottom = $xorigin - $height/2.0;
$ybottom = $yorigin - $width/2.0;
$xtop = $xorigin + $height/2.0;
$ytop = $yorigin + $height/2.0;

# Set up the distances for the near and far clipping planes
$cp_dist = 500;
$cp_near = $cp_dist - 300;
$cp_far = $cp_dist + 300;

# Create the 3d window
gfx create window 1

# We will construct the slice numbers
# Note that we miss out every second one, ie we have:
# 001 003 005 ...
for $i ("001".."128") {
    if(($i % 2) == 1) {
        push(@slice_numbers,$i)
    }
} 

# Get what slice we are after
$slice_count = 0
$slice_num = $slice_numbers[$slice_count]

# Run the comfile foreach sub image
open com execute 1 digitise

Files used by this example are:

Name                  Modified     Size

example_21e1.com 09-Feb-2001 1.6k digitise.com 09-Feb-2001 3.4k epi-sample.exdata 09-Feb-2001 218k epi-sample.exnode 09-Feb-2001 226k epi-sample.ipdata 09-Feb-2001 293k epi.exnode 09-Feb-2001 226k epi.ipnode 09-Feb-2001 14k inner-ring-rv.exdata 09-Feb-2001 36k inner-ring-rv.exnode 09-Feb-2001 40k inner-ring-rv.ipdata 09-Feb-2001 49k inner-sample.exnode 09-Feb-2001 30k inner-sample.ipdata 09-Feb-2001 34k lv-sample.exdata 09-Feb-2001 46k lv-sample.exnode 09-Feb-2001 51k lv-sample.ipdata 09-Feb-2001 62k rv-sample.exdata 09-Feb-2001 32k rv-sample.exnode 09-Feb-2001 35k rv-sample.ipdata 09-Feb-2001 43k

Download the entire example:

Name                           Modified     Size

examples_2_21_21e_21e1.tar.gz 19-Aug-2006 350k

Html last generated: Sun Mar 6 05:50:10 2016

Input last modified: Fri Feb 9 14:01:11 2001


CMISS Help / Examples / 2 / 21 / 21e / 21e1