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