Assignment 5: Segmentation
Methods In Medical Image Analysis (BioE 2630 : 16-725 : 18-791 : 42-735) - Spring 2011
John Galeotti

70 points total

Responsible TA: Vikas

Due Date: You have almost 2 weeks to do this assignment. Your code must be checked into the svn repository by 5 PM Monday night, March 28. Always, try to finish early! E-mail your TA or instructor with questions or problems.

This is your segmentation assignment. It includes:

  1. Region-growing Threshold
  2. Level Set Threshold
  3. On-Your-Own Competition

For further guidance you should consult the ITK software guide and the lecture slides, especially those from lectures 13&14, 15, and 17.

0. SVN Setup & Dataset Acquisition (0 points, apx. 5-30 minutes)

Create a new svn directory structure for this assignment, following the pattern below exactly. Assuming you previously checked out your svn module to c:\MIIA\, this would look like:

cd c:\MIIA\{Your_SVN_User_Name}    <-- This is the only line you might need to change.
mkdir hw5
mkdir hw5\Part1
mkdir hw5\Part2
mkdir hw5\Part3
svn add hw5
svn ci hw5 -m "Setting up module for hw5"

Now, download the image data set you will be using for this assignment, and unzip the archive somewhere convenient, but NOT in your SVN directory. (Please do NOT upload your copy of these downloaded images to SVN.)

Inside the resulting HW5_Images directory, you will find IM.mha, which is a small (64x64x64) piece of a much larger volumetric CT data. IM.mha has been cropped to include the ascending aorta, which will be your primary segmentation task for this assignment. In the same directory you will also find SegIM.mha, which is a coresponding expert segmentation for the ascending aorta, as visible in IM.mha. As noted in the included seed_data.txt, your automatic segmentations of this piece of the aorta should be initialized using the seed point (x=35,y=17,z=28).

Run the ITK-SNAP program (which you installed in HW2, Part 1). Go to "File" -> "Open Greyscale Image". Browse to the HW5_Images directory, and choose the file IM.mha. Choose the defaults through the rest of the file-opening dialogs. (If an "Insufficient Precision Warning" dialog appears, just ignore it and click "Ok" to make it go away.) Now go to "Segmentation" -> "Load From Image". Browse to the HW5_Images directory again, but this time choose the file SegIM.mha. Choose the defaults through the rest of the dialogs. Now click the "update mesh" button at the bottom of the main window. A screen-shot of what this should look like after you update SNAP's mesh is included in the file HW5-SNAP.jpg. Spend a little time using SNAP to look through the volumetric data, to get a feel for it.

Finally, inside the HW5_Images directory you will also find a subdirectory named LargeSet, which contains a much larger CT volume from which our small subset was taken, with coresponding expertly-automated segmentation and seed point. Use SNAP to look at this larger data set and segmentation as well. Please note that this expert segmentation is not perfect. It was created for a particular purpose, and there is some vasculature that it completely misses! You are not necessarily expected to do better than the expert segmentation, but you should be happy if you do.

Unless specifically told otherwise, you should use the small (64x64x64) data set for each part of this assignment.

1. Region-Growing Threshold Segmentation (20 points, apx. 3-6 hours)

Begin by copying Examples/Segmentation/ConnectedThresholdImageFilter.cxx from your InsightToolkit directory to Part1\threshold.cxx. Copy and update your CMakeLists.txt file from HW3-part2 as well. When updating your CMakeLists.txt file, the compiled program should be named threshold and your TARGET_LINK_LIBRARIES line should include ITKNumerics and ITKIO (this is discernable by looking at the CMakeLists.txt file in the Examples/Segmentation directory). Add and commit your code (CMakeLists.txt is part of your code) to SVN.

Now, make the following changes to threshold.cxx, being sure to commit your changes to svn after you complete each step:

  1. Make it operate on 3-dimensional images. Be sure to make it read in and use the Z-coordinate of the seed point, and change as necessary all references to argc and argv. I strongly recommend testing to make sure this works before continuing.
  2. Instead of smoothing with CurvatureFlowImageFilter, use one of the other Edge-Preserving Smoothing filters discussed in section 6.7.3 of the ITK Software Guide. (As a technical note, to keep the rest of the example code working, you will probably want to keep using the name smoothing for the smart-pointer to your smoothing filter.) Include a comment at the top of threshold.cxx indicating which smoothing filter you used, and why you set its parameters the way you did. You need to do some experimentation (preferably on the file below) to earn full credit. I encourage you to spend some time here, since you will be using this smoothing filter for the rest of the assignment.
  3. Test your code using IM.mha, with the provided seed point, and compare your results with SegIM.mha. Experiment with different values for the upper and lower threshold. You can visualize your resulting segmentations using ITK Snap. Include a comment at the top of threshold.cxx indicating your best choice of upper and lower thresholds, as well as how you derived your answers. In the same comment, rate (on a scale of 1=bad to 10=perfect) how well you think this segmentation worked.

Big Hint: Be aware that CT images have 12-bit data stored in 16-bit pixels, and so their intensities can be negative or exceed 1000 (unlike standard jpegs or pngs that have a maximum intensity of 255).

2. Level Set Threshold Segmentation (20 points, apx. 3-6 hours)

Begin by copying Examples/Segmentation/ThresholdSegmentationLevelSetImageFilter.cxx from your InsightToolkit directory to Part2\thresholdLevelSet.cxx. Copy and update your CMakeLists.txt file from Part1 as well; the compiled program should be named thresholdLS. Add and commit your code to SVN.

Now, make the following changes to thresholdLevelSet.cxx, being sure to commit your changes to svn after you complete each step:

  1. To help with item 3, below, begin by experimenting with different values for SetCurvatureScaling() using ITK's 2D image Examples/Data/BrainProtonDensitySlice256x256.png (this is the image used in the Software Guide example). Take note that you do not need to repeatedly recompile your code to experiment with SetCurvatureScaling(), because thresholdLevelSet.cxx already uses a command-line argument to your executable to read this value.
  2. Make thresholdLevelSet.cxx operate on 3-dimensional images. Be sure to make it read in and use the Z-coordinate of the seed point, and change as necessary all references to argc and argv. I strongly recommend testing to make sure this works before continuing.
  3. Test your code on the same (64x64x64) file as above, using the same seed point, but this time you must pick an appropriate initial radius. Experiment with different values for the upper and lower threshold, and for SetCurvatureScaling(), all of which can already be set using command-line arguments to your executable. You can visualize your result using ITK Snap. Include a comment at the top of thresholdLevelSet.cxx indicating your best choice of upper and lower thresholds and for SetCurvatureScaling(), as well as how you derived your answers. In the same comment, rate (on a scale of 1=bad to 10=perfect) how well you think this segmentation worked.
  4. Try to improve your result by pre-processing your original input image using the smoothing filter from Part1. Re-adjust your thresholds and curvature scaling as necessary. Include your results in a comment at the top of thresholdLevelSet.cxx.

Big Hint: Here are timings for using the provided seed, an initial distance (radius) of 2.0, LT of 300, UT of 700, and curvature of 1.0. With Debug mode this process took 30 minutes; with Release mode (see the entire Major Hint section, below) this process took under 5 minutes!

(30 points, apx. 4-10 hours)

Find and use another ITK segmentation algorithm to process the image from the LargeSet subdirectory, using the (new) appropriate included seedpoint. To find appropriate algorithms for vasculature segmentation, as well as example code to use, I highly recommend using the ITK Software Guide, Google, and/or the ITK mailing list archives (please do not ask the mailing list how to do this--search the list archives instead; if you still have questions, then it is appropriate to ask the list). I also highly recommend starting with the small (64x64x64) volume for initial experimentation, and then only trying things that seem promising on the larger data set.

In addition to the seedpoint provided, you may optionally choose up to 4 additional seedpoints for the large volume (5 seedpoints total). Carefully distributing your seed points can substantially speed up your segmentation, and potentially increase its accuracy as well.

Scoring for this part is as follows:

Since this part is a competition to see who can get the best segmentation, you are on your own. Neither the TA nor myself will help you choose or implement your segmentation algorithm (but feel free to ask your TA for help with compiler problems, etc.). Feel free to use all other sources of help at your disposal, including internet mailing lists (but please be polite and only ask specific questions on the itk mailing list). Place your well-commented code in Part3\best_segmentation.cxx; include an appropriate CMakeLists.txt file.

Be sure to comment in your code about any areas where you believe your segmentation does a better job than the expert segmentation. (If you're not sure about a piece of vasculature that you believe should be segmented, but was not in the expert segmentation, then feel free to ask your TA for clarificaiton.)

*** Also, be sure to include a comment at the top of best_segmentation.cxx indicating how long it takes your code to run on your machine, so that the TA has some idea how long he should wait for your code to finish executing.

Please note that I strongly discourage trying to use really complex segmention methods for this part. On such a large, branching data set they almost certainly will not work. If, contrary to my advice and in the spirit of competition, you feel compelled to try anyway, then I would suggest (1) lots of cafine, and (2) a 2-stage segmentation, where you only use an advanced segmentation method to refine the output of some other simpler and more robust method.

Major Hint

You can drastically speed up the execution of your well-debugged code by recompiling it without debugging support. This requires that you previously compiled ITK both with and without debugging support (as instructed in Assignment 2). More details:

Debug mode is great if your code/input parameters may have errors because the errors will be flagged as the program is running and tell you (sometimes less descriptive than others) what went wrong. If, on the other hand, you build your program in "Release" mode, you don't have all of the 'watchers' keeping track of all the variables and error messages, if thrown. Thus, your program runs MUCH faster in Release mode than in Debug. However, you do not get error checking on input parameters. So, if you are careful and particular about the details, build your project in Release mode (make sure that it builds in Debug first, so that you know there are no obvious errors in your work).

BEWARE: Building your programs in Release mode will inherently look for the Release mode versions of all the libraries that your program looks for. Therefore, if your program uses ITK libraries, which all of yours should at least use for this assignment, you should have ITK built for Release mode.

On Windows to build a second copy of your code in Release Mode in Visual Studio:

  1. Open your HW5/Part# project
  2. In top center of Visual Studio there is a drop-down menu that currently will state "Debug" mode
  3. Change drop-down menu to "Release"
  4. (Re)Build HW5/Part#

Now, instead of the executable for your program being located in the Debug folder, it will be located in the Release folder of your Binary directory.

IN SUMMARY: Use Debug mode first to error check your code, including running the program with some parameters from the command-line first, verifying that everything is working as planned (even if it takes 45-60 minutes for your code to run). Once everything is working, and ITK has also been built for Release mode, then build your program for Release mode and be amazed at how much faster it runs.