1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 
19 //  Software Guide : BeginLatex
20 //
21 //  This example illustrates the use of Mathematical Morphology filters for
22 //  image enhancement. One of the difficulties of image enhancement is that it
23 //  is defined based on human visual perception and it is related to a
24 //  particular set of features that are of interest in the image. In this
25 //  context, what is considered enhancement for one person, may be seen as
26 //  image degradation by another person.
27 //
28 //  \index{itk::AntiAliasBinaryImageFilter|textbf}
29 //
30 //  Software Guide : EndLatex
31 
32 
33 // Software Guide : BeginCodeSnippet
34 #include "itkImage.h"
35 #include "itkPNGImageIO.h"
36 #include "itkImageFileReader.h"
37 #include "itkImageFileWriter.h"
38 
39 #include "itkGrayscaleMorphologicalOpeningImageFilter.h"
40 #include "itkGrayscaleMorphologicalClosingImageFilter.h"
41 #include "itkBinaryBallStructuringElement.h"
42 
43 #include "itkConstrainedValueAdditionImageFilter.h"
44 #include "itkConstrainedValueDifferenceImageFilter.h"
45 
46 #include "itkRescaleIntensityImageFilter.h"
47 
main(int argc,char * argv[])48 int main( int argc, char * argv[] )
49 {
50   if( argc < 4 )
51     {
52     std::cerr << "Usage: " << std::endl;
53     std::cerr << argv[0] << "  inputImageFile  ";
54     std::cerr << " outputImageFile radius " << std::endl;
55     return EXIT_FAILURE;
56   }
57 
58   //
59   //  The following code defines the input and output pixel types and their
60   //  associated image types.
61   //
62   constexpr unsigned int Dimension = 2;
63 
64   using PixelType = unsigned char;
65   using WritePixelType = unsigned char;
66 
67   using ImageType = itk::Image< PixelType,  Dimension >;
68     using WriteImageType = itk::Image< WritePixelType, Dimension >;
69   // readers/writers
70   using ReaderType = itk::ImageFileReader< ImageType  >;
71   using WriterType = itk::ImageFileWriter< WriteImageType >;
72 
73   // structuring element
74   using StructuringElementType = itk::BinaryBallStructuringElement<
75             PixelType, Dimension  >;
76   // define the opening and closing types
77   using OpeningFilterType = itk::GrayscaleMorphologicalOpeningImageFilter<
78             ImageType, ImageType, StructuringElementType >;
79   using ClosingFilterType = itk::GrayscaleMorphologicalClosingImageFilter<
80             ImageType, ImageType, StructuringElementType >;
81   // define arithmetic operation filters
82   using AdditionFilterType = itk::ConstrainedValueAdditionImageFilter<
83             ImageType, ImageType, ImageType >;
84   using SubtractionFilterType = itk::ConstrainedValueDifferenceImageFilter<
85             ImageType, ImageType, ImageType >;
86   // define rescaling filter
87   using RescaleFilterType = itk::RescaleIntensityImageFilter<
88             ImageType, WriteImageType>;
89 
90   // Create structuring element
91   StructuringElementType  structuringElement;
92   // (argv[3]+1) x (argv[3]+1) structuring element
93   structuringElement.SetRadius( std::stoi(argv[3]) );
94   structuringElement.CreateStructuringElement();
95 
96   // Setup the input and output files
97   ReaderType::Pointer reader = ReaderType::New();
98   reader->SetFileName( argv[1] );
99   WriterType::Pointer writer  = WriterType::New();
100   writer->SetFileName( argv[2] );
101 
102   // reading input image
103   try
104     {
105     reader->Update();
106     }
107   catch ( itk::ExceptionObject &err)
108     {
109     std::cout << "Problems reading input image" << std::endl;
110     std::cerr << "ExceptionObject caught !" << std::endl;
111     std::cerr << err << std::endl;
112     return EXIT_FAILURE;
113     }
114 
115   // Create the opening closing filters
116   OpeningFilterType::Pointer  opening  = OpeningFilterType::New();
117   ClosingFilterType::Pointer  closing  = ClosingFilterType::New();
118   // Setup the opening and closing methods
119   opening->SetKernel(  structuringElement );
120   closing->SetKernel(  structuringElement );
121   // Setup minnimum and maximum of rescale filter
122   RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New();
123   rescaleFilter->SetOutputMinimum( 0 );
124   rescaleFilter->SetOutputMaximum( 255 );
125   // creation of the pipeline. The enhancement operation is given by:
126   // Original Image + Top Hat Image - Bottom Hat Image
127   opening->SetInput(           reader->GetOutput()           );
128   closing->SetInput(           reader->GetOutput()           );
129   SubtractionFilterType::Pointer topHat    = SubtractionFilterType::New();
130   topHat->SetInput1(           reader->GetOutput()           );
131   topHat->SetInput2(           opening->GetOutput()          );
132   SubtractionFilterType::Pointer bottomHat = SubtractionFilterType::New();
133   bottomHat->SetInput1(        closing->GetOutput()          );
134   bottomHat->SetInput2(        reader->GetOutput()           );
135   AdditionFilterType::Pointer    internalAddition = AdditionFilterType::New();
136   internalAddition->SetInput1( reader->GetOutput()           );
137   internalAddition->SetInput2( topHat->GetOutput()           );
138 
139   SubtractionFilterType::Pointer imageEnhancement =
140                                                  SubtractionFilterType::New();
141   imageEnhancement->SetInput1( internalAddition->GetOutput() );
142   imageEnhancement->SetInput2( bottomHat->GetOutput()        );
143   rescaleFilter->SetInput(     imageEnhancement->GetOutput() );
144   writer->SetInput(            rescaleFilter->GetOutput()    );
145   try
146     {
147     writer->Update();
148     }
149   catch( itk::ExceptionObject & err )
150     {
151     std::cout << "ExceptionObject caught !" << std::endl;
152     std::cout << err <<std::endl;
153     return EXIT_FAILURE;
154     }
155   return EXIT_SUCCESS;
156 }
157