From 06cc158ec7ed53203ed131d1a543dae4aab5e5b9 Mon Sep 17 00:00:00 2001 From: Niels Dekker Date: Thu, 26 May 2022 13:21:56 +0200 Subject: [PATCH] ENH: Add example, "Generate the Offsets of a Shaped Image Neighborhood" --- src/Core/Common/CMakeLists.txt | 1 + .../CMakeLists.txt | 23 ++++ .../Code.cxx | 109 ++++++++++++++++++ .../Documentation.rst | 81 +++++++++++++ src/Core/Common/index.rst | 1 + 5 files changed, 215 insertions(+) create mode 100644 src/Core/Common/GenerateOffsetsShapedImageNeighborhood/CMakeLists.txt create mode 100644 src/Core/Common/GenerateOffsetsShapedImageNeighborhood/Code.cxx create mode 100644 src/Core/Common/GenerateOffsetsShapedImageNeighborhood/Documentation.rst diff --git a/src/Core/Common/CMakeLists.txt b/src/Core/Common/CMakeLists.txt index 541e114c2..5e2a0279a 100644 --- a/src/Core/Common/CMakeLists.txt +++ b/src/Core/Common/CMakeLists.txt @@ -46,6 +46,7 @@ add_example(DuplicateAnImage) add_example(ApplyAFilterOnlyToASpecifiedRegionOfAnImage) add_example(IterateOverARegionWithAShapedNeighborhoodIterator) add_example(IterateOverARegionWithAShapedNeighborhoodIteratorManual) +add_example(GenerateOffsetsShapedImageNeighborhood) add_example(CreateABackwardDifferenceOperator) add_example(BuildAHelloWorldProgram) add_example(TraceMemoryBetweenPoints) diff --git a/src/Core/Common/GenerateOffsetsShapedImageNeighborhood/CMakeLists.txt b/src/Core/Common/GenerateOffsetsShapedImageNeighborhood/CMakeLists.txt new file mode 100644 index 000000000..3c4f501c5 --- /dev/null +++ b/src/Core/Common/GenerateOffsetsShapedImageNeighborhood/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.16.3) + +project(Shapes) + +find_package(ITK REQUIRED) +include(${ITK_USE_FILE}) + +add_executable(${PROJECT_NAME} Code.cxx) +target_link_libraries(${PROJECT_NAME} ${ITK_LIBRARIES}) + +install(TARGETS ${PROJECT_NAME} + DESTINATION bin/ITKSphinxExamples/Core/Common + COMPONENT Runtime +) + +install(FILES Code.cxx CMakeLists.txt + DESTINATION share/ITKSphinxExamples/Code/Core/Common/${PROJECT_NAME} + COMPONENT Code +) + +enable_testing() +add_test(NAME ${PROJECT_NAME}Test + COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}) diff --git a/src/Core/Common/GenerateOffsetsShapedImageNeighborhood/Code.cxx b/src/Core/Common/GenerateOffsetsShapedImageNeighborhood/Code.cxx new file mode 100644 index 000000000..4ee39aed9 --- /dev/null +++ b/src/Core/Common/GenerateOffsetsShapedImageNeighborhood/Code.cxx @@ -0,0 +1,109 @@ +/*========================================================================= + * + * 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. + * + *=========================================================================*/ + +#include "itkConnectedImageNeighborhoodShape.h" +#include "itkImage.h" +#include "itkImageBufferRange.h" +#include "itkImageNeighborhoodOffsets.h" +#include "itkRectangularImageNeighborhoodShape.h" +#include "itkShapedImageNeighborhoodRange.h" + +#include +#include +#include // For iota +#include // For hex + +namespace +{ +constexpr unsigned int Dimension{ 2 }; +using OffsetType = itk::Offset; + +// Print the specified offsets of a neighborhood shape. Also prints the pixel values of a small image for which such a +// shaped neigborhood located at the image center is filled with consecutive values, 1, 2, 3, ..., N. +template +void +PrintImageNeighborhoodShape(const TOffsets & offsets) +{ + std::cout << " "; + + for (const OffsetType & offset : offsets) + { + std::cout << offset << ' '; + } + + using ImageType = itk::Image; + const auto image = ImageType::New(); + constexpr unsigned int imageSize{ 7 }; + image->SetRegions(ImageType::SizeType::Filled(imageSize)); + image->Allocate(true); + + const auto centerIndex = ImageType::IndexType::Filled(imageSize / 2); + const itk::ShapedImageNeighborhoodRange shapedImageNeighborhoodRange(*image, centerIndex, offsets); + + // Set the values of the pixels in the "shaped neighborhood" of the image center to 1, 2, 3, ..., N, consecutively. + std::iota(shapedImageNeighborhoodRange.begin(), shapedImageNeighborhoodRange.end(), 1); + + std::cout << "\n\n"; + const std::ios_base::fmtflags flags(std::cout.flags()); + std::cout << std::hex << std::uppercase; + + const itk::ImageBufferRange imageBufferRange(*image); + auto imageBufferIterator = imageBufferRange.cbegin(); + + for (int y{ 0 }; y < imageSize; ++y) + { + std::cout << " "; + + for (int x{ 0 }; x < imageSize; ++x) + { + std::cout << *imageBufferIterator << ' '; + ++imageBufferIterator; + } + std::cout << '\n'; + } + std::cout.flags(flags); + std::cout << '\n'; +} + +} // namespace + + +int +main() +{ + const std::array offsets = { { { { 0, -1 } }, { { 0, 1 } }, { { 1, 1 } } } }; + std::cout << "Shape of some arbitrary offsets:\n\n"; + PrintImageNeighborhoodShape(offsets); + + const bool includeCenterPixel = false; + const size_t maximumCityblockDistance = 1; + std::cout << "4-connected neighborhood shape (excluding the center pixel) with maximumCityblockDistance = " + << maximumCityblockDistance << ":\n\n"; + + // GenerateConnectedImageNeighborhoodShapeOffsets returns an std::array of offsets. + const auto connectedImageNeighborhoodShapeOffsets = + itk::GenerateConnectedImageNeighborhoodShapeOffsets(); + PrintImageNeighborhoodShape(connectedImageNeighborhoodShapeOffsets); + + const itk::Size radius = { { 1, 2 } }; + std::cout << "Rectangular shape of radius " << radius << ":\n\n"; + + // GenerateRectangularImageNeighborhoodOffsets returns an std::vector of offsets. + const auto rectangularImageNeighborhoodOffsets = itk::GenerateRectangularImageNeighborhoodOffsets(radius); + PrintImageNeighborhoodShape(rectangularImageNeighborhoodOffsets); +} diff --git a/src/Core/Common/GenerateOffsetsShapedImageNeighborhood/Documentation.rst b/src/Core/Common/GenerateOffsetsShapedImageNeighborhood/Documentation.rst new file mode 100644 index 000000000..d398dcf26 --- /dev/null +++ b/src/Core/Common/GenerateOffsetsShapedImageNeighborhood/Documentation.rst @@ -0,0 +1,81 @@ +:name: GenerateOffsetsShapedImageNeighborhood + +Generate the Offsets of a Shaped Image Neighborhood +=================================================== + +.. index:: + single: ConnectedImageNeighborhoodShape + single: RectangularImageNeighborhoodShape + single: ShapedImageNeighborhoodRange + + +Synopsis +-------- + + +This example demonstrates various ways to create a container of offsets, to +specify the shape of a neighborhood of pixels: + + - An arbitrary shape + - A 4-connected neighborhood shape + - A rectangular neighborhood shape + +These offsets may be used to specify the shape of a ShapedImageNeighborhoodRange +(as included with this code example), or a ShapedNeighborhoodIterator. + +Results +------- + +Output:: + + Shape of some arbitrary offsets: + + [0, -1] [0, 1] [1, 1] + + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 1 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 2 3 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + + 4-connected neighborhood shape (excluding the center pixel) with maximumCityblockDistance = 1: + + [0, -1] [-1, 0] [1, 0] [0, 1] + + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 1 0 0 0 + 0 0 2 0 3 0 0 + 0 0 0 4 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + + Rectangular shape of radius [1, 2]: + + [-1, -2] [0, -2] [1, -2] [-1, -1] [0, -1] [1, -1] [-1, 0] [0, 0] [1, 0] [-1, 1] [0, 1] [1, 1] [-1, 2] [0, 2] [1, 2] + + 0 0 0 0 0 0 0 + 0 0 1 2 3 0 0 + 0 0 4 5 6 0 0 + 0 0 7 8 9 0 0 + 0 0 A B C 0 0 + 0 0 D E F 0 0 + 0 0 0 0 0 0 0 + + +Code +---- + +C++ +... + +.. literalinclude:: Code.cxx + :lines: 18- + + +Classes demonstrated +-------------------- + +.. breathelink:: itk::ConnectedImageNeighborhoodShape itk::RectangularImageNeighborhoodShape diff --git a/src/Core/Common/index.rst b/src/Core/Common/index.rst index bf0273293..e59196012 100644 --- a/src/Core/Common/index.rst +++ b/src/Core/Common/index.rst @@ -55,6 +55,7 @@ Common FilterImageUsingMultipleThreads/Documentation.rst FilterImageWithoutCopying/Documentation.rst FindMaxAndMinInImage/Documentation.rst + GenerateOffsetsShapedImageNeighborhood/Documentation.rst GetImageSize/Documentation.rst GetNameOfClass/Documentation.rst GetOrSetMemberVariableOfITKClass/Documentation.rst