1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
/*=========================================================================
*
* Copyright Insight Software Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
// Software Guide : BeginLatex
//
// Surface extraction has attracted continuous interest since the early days
// of image analysis, especially in the context of medical applications.
// Although it is commonly associated with image segmentation, surface
// extraction is not in itself a segmentation technique, instead it is a
// transformation that changes the way a segmentation is represented. In its
// most common form, isosurface extraction is the equivalent of image
// thresholding followed by surface extraction.
//
// Probably the most widely known method of surface extraction is the
// \emph{Marching Cubes} algorithm~\cite{MarchingCubes}. Although it has been
// followed by a number of variants~\cite{VTKBook}, Marching Cubes has become
// an icon in medical image processing. The following example illustrates how
// to perform surface extraction in ITK using an algorithm similar to Marching
// Cubes~\footnote{Note that the Marching Cubes algorithm is covered by a
// patent that expired on June 5th 2005.}.
//
// Software Guide : EndLatex
#include "itkImageFileReader.h"
// Software Guide : BeginLatex
//
// The representation of unstructured data in ITK is done with
// the \doxygen{Mesh}. This class enables us to represent $N$-Dimensional grids of
// varied topology. It is natural for the filter that extracts surfaces from an
// image to produce a mesh as its output.
//
// We initiate our example by including the header files of the surface
// extraction filter, the image and the mesh.
//
// \index{Marching Cubes}
// \index{Isosurface extraction!Mesh}
// \index{BinaryMask3DMeshSource!Header}
// \index{Mesh!Isosurface extraction}
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
#include "itkBinaryMask3DMeshSource.h"
#include "itkImage.h"
// Software Guide : EndCodeSnippet
int main(int argc, char * argv[] )
{
if( argc < 3 )
{
std::cerr << "Usage: IsoSurfaceExtraction inputImageFile objectValue " << std::endl;
return EXIT_FAILURE;
}
// Software Guide : BeginLatex
//
// We define then the pixel type and dimension of the image from which we are
// going to extract the surface.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
const unsigned int Dimension = 3;
typedef unsigned char PixelType;
typedef itk::Image< PixelType, Dimension > ImageType;
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// With the same image type we instantiate the type of an ImageFileReader and
// construct one with the purpose of reading in the input image.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef itk::ImageFileReader< ImageType > ReaderType;
ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName( argv[1] );
// Software Guide : EndCodeSnippet
try
{
reader->Update();
}
catch( itk::ExceptionObject & exp )
{
std::cerr << "Exception thrown while reading the input file " << std::endl;
std::cerr << exp << std::endl;
return EXIT_FAILURE;
}
// Software Guide : BeginLatex
//
// The type of the \doxygen{Mesh} is instantiated by specifying the type to be
// associated with the pixel value of the Mesh nodes. This particular pixel
// type happens to be irrelevant for the purpose of extracting the surface.
//
// \index{BinaryMask3DMeshSource!Instantiation}
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef itk::Mesh<double> MeshType;
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Having declared the Image and Mesh types we can now instantiate the
// surface extraction filter, and construct one by invoking its \code{New()}
// method.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef itk::BinaryMask3DMeshSource< ImageType, MeshType > MeshSourceType;
MeshSourceType::Pointer meshSource = MeshSourceType::New();
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// In this example, the pixel value associated with the object
// to be extracted is read from the command line arguments and it is passed to
// the filter by using the \code{SetObjectValue()} method. Note that this is
// different from the traditional isovalue used in the Marching Cubes
// algorithm. In the case of the \code{BinaryMask3DMeshSource} filter, the
// object values define the membership of pixels to the object from which the
// surface will be extracted. In other words, the surface will be surrounding
// all pixels with value equal to the ObjectValue parameter.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
const PixelType objectValue = static_cast<PixelType>( atof( argv[2] ) );
meshSource->SetObjectValue( objectValue );
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// The input to the surface extraction filter is taken from the output of
// the image reader.
//
// \index{BinaryMask3DMeshSource!SetInput}
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
meshSource->SetInput( reader->GetOutput() );
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Finally we trigger the execution of the pipeline by invoking the
// \code{Update()} method. Given that the pipeline may throw an exception this
// call must be place inside a \code{try/catch} block.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
try
{
meshSource->Update();
}
catch( itk::ExceptionObject & exp )
{
std::cerr << "Exception thrown during Update() " << std::endl;
std::cerr << exp << std::endl;
return EXIT_FAILURE;
}
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// We print out the number of nodes and cells in order to inspect the
// output mesh.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
std::cout << "Nodes = " << meshSource->GetNumberOfNodes() << std::endl;
std::cout << "Cells = " << meshSource->GetNumberOfCells() << std::endl;
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// This resulting Mesh could be used as input for a deformable model
// segmentation algorithm, or it could be converted to a format suitable for
// visualization in an interactive application.
//
// Software Guide : EndLatex
return EXIT_SUCCESS;
}
|