diff --git a/src/Filtering/ImageFeature/CMakeLists.txt b/src/Filtering/ImageFeature/CMakeLists.txt index a921b8211..e17fc6691 100644 --- a/src/Filtering/ImageFeature/CMakeLists.txt +++ b/src/Filtering/ImageFeature/CMakeLists.txt @@ -33,3 +33,6 @@ add_example(FindZeroCrossingsInSignedImage) #=================================== add_example(AdditiveGaussianNoiseImageFilter) + +add_example(DerivativeImage) +compare_to_baseline(EXAMPLE_NAME DerivativeImage BASELINE_PREFIX Output) diff --git a/src/Filtering/ImageFeature/DerivativeImage/BrainProtonDensitySlice.png.sha512 b/src/Filtering/ImageFeature/DerivativeImage/BrainProtonDensitySlice.png.sha512 new file mode 100644 index 000000000..55092eda5 --- /dev/null +++ b/src/Filtering/ImageFeature/DerivativeImage/BrainProtonDensitySlice.png.sha512 @@ -0,0 +1 @@ +86cbe2a809e90d72fb464868449477fe6d83809ddd0493cfca92033d7d3dd4bc3e0b831b17735926ed990735234a4eb8034aeaca70a3f5ba18fffe8f3c8e7eaa diff --git a/src/Filtering/ImageFeature/DerivativeImage/CMakeLists.txt b/src/Filtering/ImageFeature/DerivativeImage/CMakeLists.txt new file mode 100644 index 000000000..b183b1d53 --- /dev/null +++ b/src/Filtering/ImageFeature/DerivativeImage/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.16.3) + +project( DerivativeImage ) + +find_package( ITK REQUIRED ) +include( ${ITK_USE_FILE} ) + +add_executable( DerivativeImage Code.cxx ) +target_link_libraries( DerivativeImage ${ITK_LIBRARIES} ) + +install( TARGETS DerivativeImage + DESTINATION bin/ITKSphinxExamples/Filtering/ImageFeature + COMPONENT Runtime + ) + +install( FILES Code.cxx CMakeLists.txt + DESTINATION share/ITKSphinxExamples/Code/Filtering/ImageFeature/DerivativeImage + COMPONENT Code + ) + +enable_testing() +add_test( NAME DerivativeImageTest + COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DerivativeImage + ${CMAKE_CURRENT_BINARY_DIR}/BrainProtonDensitySlice.png + Output.mha Output_normalized.mha 1 1 + ) + +#if( ITK_WRAP_PYTHON ) +# add_test( NAME DerivativeImageTestPython +# COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Code.py +# ${CMAKE_CURRENT_BINARY_DIR}/BrainProtonDensitySlice.png +# OutputPython.png +# ) +#endif() diff --git a/src/Filtering/ImageFeature/DerivativeImage/Code.cxx b/src/Filtering/ImageFeature/DerivativeImage/Code.cxx new file mode 100644 index 000000000..435a332f9 --- /dev/null +++ b/src/Filtering/ImageFeature/DerivativeImage/Code.cxx @@ -0,0 +1,190 @@ +/*========================================================================= + * + * Copyright NumFOCUS + * + * 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 + * + * https://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 : BeginCommandLineArgs +// INPUTS: {BrainProtonDensitySlice.png} +// ARGUMENTS: {DerivativeImageFilterFloatOutput.mhd} +// OUTPUTS: {DerivativeImageFilterOutput.png} +// ARGUMENTS: 1 0 +// Software Guide : EndCommandLineArgs + +// Software Guide : BeginLatex +// +// The \doxygen{DerivativeImageFilter} is used for computing the partial +// derivative of an image, the derivative of an image along a particular +// axial direction. +// +// \index{itk::DerivativeImageFilter} +// +// Software Guide : EndLatex + + +#include "itkImage.h" +#include "itkImageFileReader.h" +#include "itkImageFileWriter.h" +#include "itkRescaleIntensityImageFilter.h" + +// Software Guide : BeginLatex +// +// The header file corresponding to this filter should be included first. +// +// \index{itk::DerivativeImageFilter!header} +// +// Software Guide : EndLatex + + +// Software Guide : BeginCodeSnippet +#include "itkDerivativeImageFilter.h" +// Software Guide : EndCodeSnippet + + +int +main(int argc, char * argv[]) +{ + if (argc < 6) + { + std::cerr << "Usage: " << std::endl; + std::cerr << argv[0] << " inputImageFile outputImageFile normalizedOutputImageFile "; + std::cerr << " derivativeOrder direction" << std::endl; + return EXIT_FAILURE; + } + + + // Software Guide : BeginLatex + // + // Next, the pixel types for the input and output images must be defined + // and, with them, the image types can be instantiated. Note that it is + // important to select a signed type for the image, since the values of the + // derivatives will be positive as well as negative. + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + using InputPixelType = float; + using OutputPixelType = float; + + constexpr unsigned int Dimension = 2; + + using InputImageType = itk::Image; + using OutputImageType = itk::Image; + // Software Guide : EndCodeSnippet + + + using ReaderType = itk::ImageFileReader; + using WriterType = itk::ImageFileWriter; + + auto reader = ReaderType::New(); + auto writer = WriterType::New(); + + reader->SetFileName(argv[1]); + writer->SetFileName(argv[2]); + + // Software Guide : BeginLatex + // + // Using the image types, it is now possible to define the filter type + // and create the filter object. + // + // \index{itk::DerivativeImageFilter!instantiation} + // \index{itk::DerivativeImageFilter!New()} + // \index{itk::DerivativeImageFilter!Pointer} + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + using FilterType = itk::DerivativeImageFilter; + + auto filter = FilterType::New(); + // Software Guide : EndCodeSnippet + + + // Software Guide : BeginLatex + // + // The order of the derivative is selected with the \code{SetOrder()} + // method. The direction along which the derivative will be computed is + // selected with the \code{SetDirection()} method. + // + // \index{itk::DerivativeImageFilter!SetOrder()} + // \index{itk::DerivativeImageFilter!SetDirection()} + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + filter->SetOrder(std::stoi(argv[4])); + filter->SetDirection(std::stoi(argv[5])); + // Software Guide : EndCodeSnippet + + + // Software Guide : BeginLatex + // + // The input to the filter can be taken from any other filter, for example + // a reader. The output can be passed down the pipeline to other filters, + // for example, a writer. An \code{Update()} call on any downstream filter + // will trigger the execution of the derivative filter. + // + // \index{itk::DerivativeImageFilter!SetInput()} + // \index{itk::DerivativeImageFilter!GetOutput()} + // + // Software Guide : EndLatex + + + // Software Guide : BeginCodeSnippet + filter->SetInput(reader->GetOutput()); + writer->SetInput(filter->GetOutput()); + writer->Update(); + // Software Guide : EndCodeSnippet + + + // Software Guide : BeginLatex + // + // \begin{figure} + // \center + // \includegraphics[width=0.44\textwidth]{BrainProtonDensitySlice} + // \includegraphics[width=0.44\textwidth]{DerivativeImageFilterOutput} + // \itkcaption[Effect of the Derivative filter.]{Effect of the Derivative + // filter on a slice from a MRI proton density brain image.} + // \label{fig:DerivativeImageFilterOutput} + // \end{figure} + // + // Figure \ref{fig:DerivativeImageFilterOutput} illustrates the effect of + // the DerivativeImageFilter on a slice of MRI brain image. The derivative + // is taken along the $x$ direction. The sensitivity to noise in the image + // is evident from this result. + // + // Software Guide : EndLatex + + + using WriteImageType = itk::Image; + + using NormalizeFilterType = itk::RescaleIntensityImageFilter; + + using NormalizedWriterType = itk::ImageFileWriter; + + auto normalizer = NormalizeFilterType::New(); + auto normalizedWriter = NormalizedWriterType::New(); + + normalizer->SetInput(filter->GetOutput()); + normalizedWriter->SetInput(normalizer->GetOutput()); + + normalizer->SetOutputMinimum(0); + normalizer->SetOutputMaximum(255); + + normalizedWriter->SetFileName(argv[3]); + normalizedWriter->Update(); + + return EXIT_SUCCESS; +} diff --git a/src/Filtering/ImageFeature/DerivativeImage/Documentation.rst b/src/Filtering/ImageFeature/DerivativeImage/Documentation.rst new file mode 100644 index 000000000..c221389be --- /dev/null +++ b/src/Filtering/ImageFeature/DerivativeImage/Documentation.rst @@ -0,0 +1,49 @@ +:name: DerivativeImage + +Compute Derivative +=================== + +.. index:: + single: DerivativeImageFilter + +Synopsis +-------- + +This filter computes a n-th Derivative of a scalar-valued image in a specified direction. + + +Results +------- + +.. figure:: BrainProtonDensitySlice.png + :scale: 50% + :alt: Input image + + Input image + +.. figure:: Output.png + :scale: 50% + :alt: Output image + + Output image + + +.. figure:: Output_normalized.png + :scale: 50% + :alt: Output normalized image + + Output normalized image + +Code +---- + +C++ +... + +.. literalinclude:: Code.cxx + :lines: 18- + +Classes demonstrated +-------------------- + +.. breathelink:: itk::DerivativeImageFilter diff --git a/src/Filtering/ImageFeature/DerivativeImage/Output.mha.sha512 b/src/Filtering/ImageFeature/DerivativeImage/Output.mha.sha512 new file mode 100644 index 000000000..05066b272 --- /dev/null +++ b/src/Filtering/ImageFeature/DerivativeImage/Output.mha.sha512 @@ -0,0 +1 @@ +1bba1d72a84bf2d171c85834a9e9e7e485b26ef60a05fb0fe93c1103ff920071fc5ccc14b7c27348abf5dcd537825838bdefd7a8b27336c8115677ceb80af227 diff --git a/src/Filtering/ImageFeature/DerivativeImage/Output.png.sha512 b/src/Filtering/ImageFeature/DerivativeImage/Output.png.sha512 new file mode 100644 index 000000000..d32800b87 --- /dev/null +++ b/src/Filtering/ImageFeature/DerivativeImage/Output.png.sha512 @@ -0,0 +1 @@ +29e67a22a4218b780ca75af045544178e193aefce7ceff7923fcd858068918efab6d41c37ea3020fe3747abb35172a67be33ff85c9595ff3a19fffdc37d6a2d1 diff --git a/src/Filtering/ImageFeature/DerivativeImage/Output_normalized.mha.sha512 b/src/Filtering/ImageFeature/DerivativeImage/Output_normalized.mha.sha512 new file mode 100644 index 000000000..6b4582891 --- /dev/null +++ b/src/Filtering/ImageFeature/DerivativeImage/Output_normalized.mha.sha512 @@ -0,0 +1 @@ +346c92583d339826d3ebf9cede566d1d215e50b3cd431fe63e693e97f03f0b9f48c2f461a4dd73218f0e5852f5a12e9d90e8360c522fb8e5752aadc86e6d3362 diff --git a/src/Filtering/ImageFeature/DerivativeImage/Output_normalized.png.sha512 b/src/Filtering/ImageFeature/DerivativeImage/Output_normalized.png.sha512 new file mode 100644 index 000000000..f38f21ea4 --- /dev/null +++ b/src/Filtering/ImageFeature/DerivativeImage/Output_normalized.png.sha512 @@ -0,0 +1 @@ +1cf70adf30331a9c1a084e64f13dc7c263d212ebcad0880048413af3490ee81f5e1f77caf5cd98b52a0181a66ad2ced1c02392dd8c8e2d46f615e93d205df6c4 diff --git a/src/Filtering/ImageFeature/index.rst b/src/Filtering/ImageFeature/index.rst index bdf4f8d14..2a38966dc 100644 --- a/src/Filtering/ImageFeature/index.rst +++ b/src/Filtering/ImageFeature/index.rst @@ -10,6 +10,7 @@ ImageFeature BilateralFilterAnImage/Documentation.rst ComputeLaplacian/Documentation.rst DetectEdgesWithCannyEdgeDetectionFilter/Documentation.rst + DerivativeImage/Documentation.rst ExtractContoursFromImage/Documentation.rst FindZeroCrossingsInSignedImage/Documentation.rst LaplacianRecursiveGaussianImageFilter/Documentation.rst