diff --git a/src/Filtering/MathematicalMorphology/CMakeLists.txt b/src/Filtering/MathematicalMorphology/CMakeLists.txt index c94c748fa..195fdfe41 100644 --- a/src/Filtering/MathematicalMorphology/CMakeLists.txt +++ b/src/Filtering/MathematicalMorphology/CMakeLists.txt @@ -32,3 +32,8 @@ add_example(ErodeBinaryImageUsingFlatStruct) compare_to_baseline(EXAMPLE_NAME ErodeBinaryImageUsingFlatStruct BASELINE_PREFIX ErodeBinaryImageUsingFlatStruct ) + +add_example(DilateUsingFunctionalGrayscale) +compare_to_baseline(EXAMPLE_NAME DilateUsingFunctionalGrayscale + BASELINE_PREFIX OutputBaseline + ) diff --git a/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/CMakeLists.txt b/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/CMakeLists.txt new file mode 100644 index 000000000..549603929 --- /dev/null +++ b/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 3.16.3) + +project( DilateUsingFunctionalGrayscale ) + +find_package( ITK REQUIRED + COMPONENTS + ITKCommon + ITKIOImageBase + ITKMathematicalMorphology + ITKIOPNG + ) +include( ${ITK_USE_FILE} ) + +add_executable( DilateUsingFunctionalGrayscale Code.cxx ) +target_link_libraries( DilateUsingFunctionalGrayscale ${ITK_LIBRARIES} ) + +install( TARGETS DilateUsingFunctionalGrayscale + DESTINATION bin/ITKSphinxExamples/Filtering/MathematicalMorphology + COMPONENT Runtime +) + +install( FILES Code.cxx CMakeLists.txt + DESTINATION share/ITKSphinxExamples/Code/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale + COMPONENT Code +) + +enable_testing() +add_test( NAME DilateUsingFunctionalGrayscaleTest + COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DilateUsingFunctionalGrayscale + ${CMAKE_CURRENT_BINARY_DIR}/cthead1.png + Output.png + 5 + ) + +if( ITK_WRAP_PYTHON ) + add_test( NAME DilateUsingFunctionalGrayscaleTestPython + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Code.py + ${CMAKE_CURRENT_BINARY_DIR}/cthead1.png + OutputPython.png + 5 + ) +endif() diff --git a/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/Code.cxx b/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/Code.cxx new file mode 100644 index 000000000..9986928b4 --- /dev/null +++ b/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/Code.cxx @@ -0,0 +1,79 @@ +/*========================================================================= + * + * 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. + * + *=========================================================================*/ + +#include "itkFlatStructuringElement.h" +#include "itkGrayscaleFunctionDilateImageFilter.h" +#include "itkImage.h" +#include "itkImageFileReader.h" +#include "itkImageFileWriter.h" + +int +main(int argc, char * argv[]) +{ + if (argc < 4) + { + std::cerr << "Usage: " << std::endl; + std::cerr << argv[0] << " "; + std::cerr << std::endl; + return EXIT_FAILURE; + } + + constexpr unsigned int Dimension = 2; + using PixelType = unsigned char; + + using ImageType = itk::Image; + + using ReaderType = itk::ImageFileReader; + using WriterType = itk::ImageFileWriter; + + auto reader = ReaderType::New(); + auto writer = WriterType::New(); + + const char * inputImage = argv[1]; + const char * outputImage = argv[2]; + const unsigned int radiusValue = std::stoi(argv[3]); + + reader->SetFileName(inputImage); + writer->SetFileName(outputImage); + + using StructuringElementType = itk::FlatStructuringElement; + StructuringElementType::RadiusType radius; + radius.Fill(radiusValue); + StructuringElementType structuringElement = StructuringElementType::Ball(radius); + + using FilterType = itk::GrayscaleFunctionDilateImageFilter; + + auto filter = FilterType::New(); + + filter->SetKernel(structuringElement); + + filter->SetInput(reader->GetOutput()); + writer->SetInput(filter->GetOutput()); + + try + { + writer->Update(); + } + catch (const itk::ExceptionObject & excp) + { + std::cerr << excp << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/Code.py b/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/Code.py new file mode 100644 index 000000000..02d6879bb --- /dev/null +++ b/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/Code.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +# 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 +# +# 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. + +import itk +import argparse + +itk.auto_progress(2) + +parser = argparse.ArgumentParser( + description="Dilate an image using functional grayscale morphology." +) +parser.add_argument("input_image") +parser.add_argument("output_image") +parser.add_argument("radius", type=int) +args = parser.parse_args() + +PixelType = itk.UC +Dimension = 2 + +ImageType = itk.Image[PixelType, Dimension] + +reader = itk.ImageFileReader[ImageType].New() +reader.SetFileName(args.input_image) + +StructuringElementType = itk.FlatStructuringElement[Dimension] +structuringElement = StructuringElementType.Ball(args.radius) + +grayscaleFilter = itk.GrayscaleFunctionDilateImageFilter[ + ImageType, ImageType, structuringElement +].New() +grayscaleFilter.SetInput(reader.GetOutput()) +grayscaleFilter.SetKernel(structuringElement) + +writer = itk.ImageFileWriter[ImageType].New() +writer.SetFileName(args.output_image) +writer.SetInput(grayscaleFilter.GetOutput()) + +writer.Update() diff --git a/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/Documentation.rst b/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/Documentation.rst new file mode 100644 index 000000000..1e0dc0112 --- /dev/null +++ b/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/Documentation.rst @@ -0,0 +1,60 @@ +:name: DilateUsingFunctionalGrayscale + +Dilate a grayscale image using a functional kernel +=================================================== + +.. index:: + single: BinaryBallStructuringElement + single: GrayscaleFunctionDilateImageFilter + pair: mathematical morphology; dilation + +.. seealso:: dilation; erosion + + +Synopsis +-------- + +Dilate an image using functional grayscale morphology. +Function dilation takes the maximum of all the pixels identified by the structuring element plus the structuring element value. +In this example, the white regions are enlarged. + + + +Results +------- + +.. figure:: cthead1.png + :scale: 50% + :alt: Input ct head image. + + Input grayscale image. + +.. figure:: OutputBaseline.png + :scale: 50% + :alt: Dilated output. + + Dilated output. + + +Code +---- + +Python +...... + +.. literalinclude:: Code.py + :language: python + :lines: 1, 16- + + +C++ +... + +.. literalinclude:: Code.cxx + :lines: 18- + + +Classes demonstrated +-------------------- + +.. breathelink:: itk::GrayscaleFunctionDilateImageFilter itk::BinaryBallStructuringElement diff --git a/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/OutputBaseline.png.cid b/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/OutputBaseline.png.cid new file mode 100644 index 000000000..3ccba8846 --- /dev/null +++ b/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/OutputBaseline.png.cid @@ -0,0 +1 @@ +bafkreiaqbnt5phaiaiohrwjfis2bwmqinj5eu4jgnumpfsmviy27nsduoe diff --git a/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/cthead1.png.cid b/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/cthead1.png.cid new file mode 100644 index 000000000..fed459e53 --- /dev/null +++ b/src/Filtering/MathematicalMorphology/DilateUsingFunctionalGrayscale/cthead1.png.cid @@ -0,0 +1 @@ +bafkreieilrgrns7xcna5yle2yw3q2wxkl3wn7lp22k4d4pwjhlhwc3ed4u diff --git a/src/Filtering/MathematicalMorphology/index.rst b/src/Filtering/MathematicalMorphology/index.rst index 3c0eb0b6d..8792e9d3b 100644 --- a/src/Filtering/MathematicalMorphology/index.rst +++ b/src/Filtering/MathematicalMorphology/index.rst @@ -6,6 +6,7 @@ MathematicalMorphology CreateABinaryBallStructuringElement/Documentation.rst DilateAGrayscaleImage/Documentation.rst + DilateUsingFunctionalGrayscale/Documentation.rst ErodeAGrayscaleImage/Documentation.rst ErodeBinaryImageUsingFlatStruct/Documentation.rst GenerateStructureElementsWithAccurateArea/Documentation.rst