Skip to content

Commit

Permalink
ENH: ScaleAnImage Python example and baseline image update
Browse files Browse the repository at this point in the history
Added `cthead1` input data for example to replace contrived square
image.
  • Loading branch information
tbirdso committed May 22, 2022
1 parent 1284f09 commit bed0f6b
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 69 deletions.
2 changes: 1 addition & 1 deletion src/Core/Transform/CMakeLists.txt
Expand Up @@ -15,7 +15,7 @@ compare_to_baseline(

add_example(ScaleAnImage)
compare_to_baseline(EXAMPLE_NAME ScaleAnImage
BASELINE_PREFIX ScaleAnImageOutput
BASELINE_PREFIX ScaleAnImageOutputBaseline
)

add_example(TranslateAVectorImage)
Expand Down
19 changes: 11 additions & 8 deletions src/Core/Transform/ScaleAnImage/CMakeLists.txt
Expand Up @@ -13,21 +13,24 @@ install(TARGETS ScaleAnImage
DESTINATION bin/ITKSphinxExamples/Core/Transform
COMPONENT Runtime
)

install(FILES Code.cxx CMakeLists.txt
install(FILES Code.cxx Code.py CMakeLists.txt
DESTINATION share/ITKSphinxExamples/Code/Core/Transform/ScaleAnImage/
COMPONENT Code
)


enable_testing()
set(input_image ${CMAKE_CURRENT_BINARY_DIR}/input.png)
set(output_image Output.png)
set(test_options)

add_test(NAME ScaleAnImageTest
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ScaleAnImage
${input_image}
${output_image}
${test_options}
${CMAKE_CURRENT_BINARY_DIR}/ScaleAnImageInput.png
${CMAKE_CURRENT_BINARY_DIR}/ScaleAnImageOutput.png
)

if(ITK_WRAP_PYTHON)
add_test(NAME ScaleAnImageTestPython
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Code.py
${CMAKE_CURRENT_BINARY_DIR}/ScaleAnImageInput.png
${CMAKE_CURRENT_BINARY_DIR}/ScaleAnImageOutputPython.png)
endif()
71 changes: 14 additions & 57 deletions src/Core/Transform/ScaleAnImage/Code.cxx
Expand Up @@ -17,25 +17,25 @@
*=========================================================================*/
#include "itkImage.h"
#include "itkScaleTransform.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkResampleImageFilter.h"

using ImageType = itk::Image<unsigned char, 2>;

static void
CreateImage(ImageType::Pointer image);

int
main()
main(int argc, char * argv[])
{
auto image = ImageType::New();
CreateImage(image);
if (argc < 3)
{
std::cerr << "Usage: " << argv[0] << " inputFile outputFile" << std::endl;
}

itk::WriteImage(image, "input.png");
using PixelType = unsigned char;
constexpr unsigned int ImageDimension = 2;
using ImageType = itk::Image<PixelType, ImageDimension>;
auto image = itk::ReadImage<ImageType>(argv[1]);

// using TransformType = itk::ScaleTransform<float, 2>; // If you want to use float here, you must use:
// using ResampleImageFilterType = itk::ResampleImageFilter<ImageType, ImageType, float>; later.
using TransformType = itk::ScaleTransform<double, 2>;
using MetricValueType = double;
using TransformType = itk::ScaleTransform<MetricValueType, 2>;
auto scaleTransform = TransformType::New();
itk::FixedArray<float, 2> scale;
scale[0] = 1.5; // newWidth/oldWidth
Expand All @@ -48,57 +48,14 @@ main()

scaleTransform->SetCenter(center);

using ResampleImageFilterType = itk::ResampleImageFilter<ImageType, ImageType>;
using ResampleImageFilterType = itk::ResampleImageFilter<ImageType, ImageType, MetricValueType>;
auto resampleFilter = ResampleImageFilterType::New();
resampleFilter->SetTransform(scaleTransform);
resampleFilter->SetInput(image);
resampleFilter->SetSize(image->GetLargestPossibleRegion().GetSize());
resampleFilter->Update();

itk::WriteImage(resampleFilter->GetOutput(), "output.png");
itk::WriteImage(resampleFilter->GetOutput(), argv[2]);

return EXIT_SUCCESS;
}

void
CreateImage(ImageType::Pointer image)
{
itk::Index<2> start;
start.Fill(0);

itk::Size<2> size;
size.Fill(101);

ImageType::RegionType region(start, size);
image->SetRegions(region);
image->Allocate();
image->FillBuffer(0);

// Make a white square
for (unsigned int r = 40; r < 60; ++r)
{
for (unsigned int c = 40; c < 60; ++c)
{
ImageType::IndexType pixelIndex;
pixelIndex[0] = r;
pixelIndex[1] = c;

image->SetPixel(pixelIndex, 255);
}
}

itk::ImageRegionIterator<ImageType> imageIterator(image, image->GetLargestPossibleRegion());

// Draw a white border
while (!imageIterator.IsAtEnd())
{
if (imageIterator.GetIndex()[0] == 0 ||
imageIterator.GetIndex()[0] == static_cast<int>(image->GetLargestPossibleRegion().GetSize()[0]) - 1 ||
imageIterator.GetIndex()[1] == 0 ||
imageIterator.GetIndex()[1] == static_cast<int>(image->GetLargestPossibleRegion().GetSize()[1]) - 1)
{
imageIterator.Set(255);
}
++imageIterator;
}
}
40 changes: 40 additions & 0 deletions src/Core/Transform/ScaleAnImage/Code.py
@@ -0,0 +1,40 @@
#!/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 sys

import itk

if len(sys.argv) < 3:
raise Exception(f"Usage: {sys.argv[0]} inputFile outputFile")

image = itk.imread(sys.argv[1], itk.UC)

image_dimension = image.GetImageDimension()

transform = itk.ScaleTransform[itk.D, 2].New(
scale=[1.5] * image_dimension, center=[x / 2 for x in itk.size(image)]
)

scaled_image = itk.resample_image_filter(
image, transform=transform, size=itk.size(image)
)

itk.imwrite(scaled_image, sys.argv[2])
8 changes: 7 additions & 1 deletion src/Core/Transform/ScaleAnImage/Documentation.rst
Expand Up @@ -20,7 +20,7 @@ Results

Input Image

.. figure:: ScaleAnImageOutput.png
.. figure:: ScaleAnImageOutputBaseline.png
:scale: 70%
:alt: Generated Output Image

Expand All @@ -36,6 +36,12 @@ C++
.. literalinclude:: Code.cxx
:lines: 18-

Python
...

.. literalinclude:: Code.py
:lines: 21-

Classes demonstrated
--------------------

Expand Down
@@ -1 +1 @@
a2af37927b6e67dd7a1eceaa8b2b15837a872a91d04ad7df15d59e57c61d5ac1ce4ff11409de048c9d7a066adbbe4225af38d156e586dfead3c49059f1f2e581
3751db8b668657ed157daa5f7472ba2775feefbed331d8cd45c867089c5b5a535a10d55ec02cbf7c6cf73309f06636bc4001080b8bbc4f53dec205addd0ee41f

This file was deleted.

@@ -0,0 +1 @@
7ec9d81518d26754151a112affbe24a0f206b307aaa8c8bf8241a954e0974b6ea31a8b2982ce26d9de8eb4eeacba4003e16badfc9dd39aa7cd8827080360eb39

0 comments on commit bed0f6b

Please sign in to comment.