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.
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 apartWe 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 $widthWe 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 toNow 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_distNow 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:
# 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 $heightNow 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
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
You can now start clicking points. After clicking on a few, you should
get something like this in the 3d window:
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:
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 epiHaving 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