Skip to content

Commit

Permalink
DOC: Expanded Canny Edge Detection Example
Browse files Browse the repository at this point in the history
The code for the Canny Edge Detection example in the software guide
was complete and instructive.  However, the example lacked textual
explanation.  This commit begins to bring the example more in line
with other examples in the software guide.

Change-Id: Ia6a9768a0ccde466f1996dc81978f94ab46f835c
  • Loading branch information
sudomakeinstall committed Jul 9, 2015
1 parent 88f45f6 commit 7799106
Showing 1 changed file with 76 additions and 54 deletions.
130 changes: 76 additions & 54 deletions Examples/Filtering/CannyEdgeDetectionImageFilter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,46 +19,50 @@
// Software Guide : BeginLatex
//
// This example introduces the use of the
// \doxygen{CannyEdgeDetectionImageFilter}. This filter is widely used for
// \doxygen{CannyEdgeDetectionImageFilter}. Canny edge detection is widely used for
// edge detection since it is the optimal solution satisfying the constraints
// of good sensitivity, localization and noise robustness.
// of good sensitivity, localization and noise robustness. To achieve this
// end, Canny edge detection is implemented internally as a multi-stage
// algorithm, which involves Gaussian smoothing to remove noise, calculation
// of gradient magnitudes to localize edge features, non-maximum suppression
// to remove suprious features, and finally thresholding to yield a binary image.
// Though the specifics of this internal pipeline are largely abstracted from
// the user of the class, it is nonetheless beneficial to have a general
// understanding of these components so that parameters can be appropriately
// adjusted.
//
// \index{itk::CannyEdgeDetectionImageFilter|textbf}
//
// Software Guide : EndLatex


#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkCastImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"


// Software Guide : BeginLatex
//
// The first step required for using this filter is to include its header file.
//
// \index{itk::CannyEdgeDetectionImageFilter!header}
//
// Software Guide : EndLatex

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkCastImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"

// Software Guide : BeginCodeSnippet
#include "itkCannyEdgeDetectionImageFilter.h"
// Software Guide : EndCodeSnippet


int main(int argc, char* argv[])
{

if( argc < 3 )
{
std::cerr << "Usage: " << std::endl;
std::cerr << argv[0] << " inputImage outputImage [variance upperThreshold lowerThreshold]" << std::endl;
std::cerr << argv[0]
<< " inputImage outputImage"
<< " [variance upperThreshold lowerThreshold]" << std::endl;
return EXIT_FAILURE;
}

const char * inputFilename = argv[1];
const char * outputFilename = argv[2];

float variance = 2.0;
float upperThreshold = 0.0;
float lowerThreshold = 0.0;
Expand All @@ -82,75 +86,92 @@ int main(int argc, char* argv[])
std::cout << "UpperThreshold = " << upperThreshold << std::endl;
std::cout << "LowerThreshold = " << lowerThreshold << std::endl;

typedef unsigned char CharPixelType; // IO
typedef double RealPixelType; // Operations
const unsigned int Dimension = 2;

typedef itk::Image<CharPixelType, Dimension> CharImageType;
typedef itk::Image<RealPixelType, Dimension> RealImageType;

typedef itk::ImageFileReader< CharImageType > ReaderType;
typedef itk::ImageFileWriter< CharImageType > WriterType;

// Software Guide : BeginLatex
//
// This filter operates on images of pixel type \code{float}. It is then
// necessary to cast the type of the input images which are usually of
// integer type. The \doxygen{CastImageFilter} is used here for this purpose.
// Its image template parameters are defined for casting from the input type
// to the \code{float} type used for processing.
// In this example, images are read and written with \code{unsigned char}
// pixel type. However, Canny edge detection requires floating point
// pixel types in order to avoid numerical errors. For this reason,
// a separate internal image type with pixel type \code{double} is defined
// for edge detection.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
typedef itk::CastImageFilter< CharImageType, RealImageType>
CastToRealFilterType;
// Software Guide : EndCodeSnippet
// Software Guide : BeginCodeSnippet
const unsigned int Dimension = 2;
typedef unsigned char CharPixelType; // IO
typedef double RealPixelType; // Operations

typedef itk::Image<CharPixelType, Dimension> CharImageType;
typedef itk::Image<RealPixelType, Dimension> RealImageType;

typedef itk::RescaleIntensityImageFilter<RealImageType, CharImageType > RescaleFilter;
// Software Guide : EndCodeSnippet

typedef itk::ImageFileReader<CharImageType> ReaderType;
typedef itk::ImageFileWriter<CharImageType> WriterType;

// Software Guide : BeginLatex
//
// The \doxygen{CannyEdgeDetectionImageFilter} is instantiated using the
// \code{float} image type.
//
// \index{itk::CannyEdgeDetectionImageFilter|textbf}
// The \code{CharImageType} image is cast to and from \code{RealImageType}
// using \doxygen{CastImageFilter} and \code{RescaleIntensityImageFilter},
// respectively; both the input and output of \code{CannyEdgeDetectionImageFilter}
// are \code{RealImageType}.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
typedef itk::CastImageFilter<CharImageType, RealImageType>
CastToRealFilterType;

typedef itk::CannyEdgeDetectionImageFilter<RealImageType, RealImageType> CannyFilter;

//Setting the IO

ReaderType::Pointer reader = ReaderType::New();
WriterType::Pointer writer = WriterType::New();
typedef itk::RescaleIntensityImageFilter<RealImageType, CharImageType> RescaleFilter;

CastToRealFilterType::Pointer toReal = CastToRealFilterType::New();
RescaleFilter::Pointer rescale = RescaleFilter::New();
// Software Guide : EndCodeSnippet

//Setting the ITK pipeline filter
//Setting the IO

CannyFilter::Pointer cannyFilter = CannyFilter::New();
ReaderType::Pointer reader = ReaderType::New();
CastToRealFilterType::Pointer toReal = CastToRealFilterType::New();
CannyFilter::Pointer cannyFilter = CannyFilter::New();
RescaleFilter::Pointer rescale = RescaleFilter::New();
WriterType::Pointer writer = WriterType::New();

reader->SetFileName( inputFilename );
writer->SetFileName( outputFilename );

//The output of an edge filter is 0 or 1
rescale->SetOutputMinimum( 0 );
rescale->SetOutputMaximum( 255 );

toReal->SetInput( reader->GetOutput() );

cannyFilter->SetInput( toReal->GetOutput() );
rescale->SetInput( cannyFilter->GetOutput() );
writer->SetInput( rescale->GetOutput() );

// Software Guide : BeginLatex
//
// In this example, three parameters of the Canny edge detection
// filter may be set via the \code{SetVariance()}, \code{SetUpperThreshold()},
// and \code{SetLowerThreshold()} methods. Based on the previous discussion
// of the steps in the internal pipeline, we understand that
// \code{variance} adjusts the amount of Gaussian smoothing and
// \code{upperThreshold} and \code{lowerThreshold} control which edges are
// selected in the final step.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
cannyFilter->SetVariance( variance );
cannyFilter->SetUpperThreshold( upperThreshold );
cannyFilter->SetLowerThreshold( lowerThreshold );

rescale->SetInput( cannyFilter->GetOutput() );
writer->SetInput( rescale->GetOutput() );
// Software Guide : EndCodeSnippet

// Software Guide : BeginLatex
//
// Finally, \code{Update()} is called on \code{writer} to trigger excecution
// of the pipeline. As usual, the call is wrapped in a \code{try/catch}
// block.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
try
{
writer->Update();
Expand All @@ -162,6 +183,7 @@ int main(int argc, char* argv[])
return EXIT_FAILURE;
}

// Software Guide : EndCodeSnippet

return EXIT_SUCCESS;

Expand Down

0 comments on commit 7799106

Please sign in to comment.