Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions Utilities/CookieCutter/{{cookiecutter.example_name}}/Code.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,15 @@
import sys
import itk

if len(sys.argv) != 3:
print("Usage: " + sys.argv[0] + "<InputFileName> "
"<OutputFileName>")
sys.exit(1)

parser = argparse.ArgumentParser(description='{{ cookiecutter.example_title }}.')
parser.add_argument('input_image')
parser.add_argument('output_image')
parser = argparse.ArgumentParser(description="{{ cookiecutter.example_title }}.")
parser.add_argument("input_image")
parser.add_argument("output_image")
args = parser.parse_args()

input_image = itk.imread(args.input_image)

output_image = itk.itkHelpers.camel_to_snake_case({{ cookiecutter.class_name }})(input_image)
output_image = itk.itkHelpers.camel_to_snake_case({{cookiecutter.class_name}})(
input_image
)

itk.imwrite(output_image, args.output_image)
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,20 @@ Results
Code
----

Python
......

.. literalinclude:: Code.py
:language: python
:lines: 1,16-

C++
...

.. literalinclude:: Code.cxx
:language: c++
:lines: 18-

Python
......

.. literalinclude:: Code.py
:language: python
:lines: 1,16-


Classes demonstrated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ main(int argc, char * argv[])
region.SetSize(regionSize);
region.SetIndex(regionIndex);

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

while (!imageIterator.IsAtEnd())
{
Expand Down
2 changes: 2 additions & 0 deletions src/Filtering/ImageStatistics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ add_example(ComputeMinMaxVarianceMeanOfImage)
#compare_to_baseline(EXAMPLE_NAME StatisticalPropertiesOfRegions
# BASELINE_PREFIX OutputBaseline
# )

add_example(CalculateImageMoments)
36 changes: 36 additions & 0 deletions src/Filtering/ImageStatistics/CalculateImageMoments/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 3.10.2)

project( CalculateImageMoments )

find_package( ITK REQUIRED )
include( ${ITK_USE_FILE} )

add_executable( CalculateImageMoments Code.cxx )
target_link_libraries( CalculateImageMoments ${ITK_LIBRARIES} )

install( TARGETS CalculateImageMoments
DESTINATION bin/ITKExamples/Filtering/ImageStatistics
COMPONENT Runtime
)

install( FILES Code.cxx CMakeLists.txt Code.py
DESTINATION share/ITKExamples/Code/Filtering/ImageStatistics/CalculateImageMoments
COMPONENT Code
)

enable_testing()

set(input_image ${CMAKE_CURRENT_BINARY_DIR}/ellipse.mha)

add_test( NAME CalculateImageMomentsTest
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CalculateImageMoments
${input_image}
)

if( ITK_WRAP_PYTHON )
find_package(PythonInterp REQUIRED)
add_test( NAME CalculateImageMomentsTestPython
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Code.py
${input_image}
)
endif()
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "revolutionary-headquarters",
"metadata": {},
"source": [
"# Calculate Image Moments of an Ellipse\n",
"\n",
"Image moments can be used to determine the center of gravity or average pixel location of a binary object as well as the orientation of an object according to its axes of variation.\n",
"\n",
"The interactive plot below demonstrates how to calculate the image moments of an ellipse-defined mask."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "amino-atlantic",
"metadata": {},
"outputs": [],
"source": [
"import itk\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from ipywidgets import interact"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "domestic-jenny",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "9460aeb87fea499c90c4e301da10ddce",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"interactive(children=(IntSlider(value=30, description='tx'), IntSlider(value=50, description='ty'), IntSlider(…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"output_size = [100, 100] # size of binary image containing the ellipse\n",
"\n",
"@interact(tx=(0,output_size[0],1), ty=(0,output_size[1],1), a=(5,50,1), b=(5,50,1), theta=(0,2*np.pi,0.1))\n",
"def foo(tx=30, ty=50, a=5, b=10, theta=np.pi/4.0):\n",
" '''\n",
" Creates a binary image of an ellipse and calculates the image moments. Major (purple) and minor (green)\n",
" principal axes are displayed.\n",
" \n",
" Parameters\n",
" ==========\n",
" tx, ty : translation x and y\n",
" a, b : ellipse horizontal and vertical widths before rotation\n",
" theta : angle of rotation (radians)\n",
" '''\n",
" \n",
" # ellipse starts as unit circle, use world transform to define final ellipse\n",
" ellipse = itk.EllipseSpatialObject[2].New()\n",
" ellipse_transform = itk.AffineTransform[itk.D, 2].New()\n",
" ellipse_transform.Scale([a, b])\n",
" ellipse_transform.Rotate2D(theta)\n",
" ellipse_transform.Translate([tx, ty])\n",
" ellipse.SetObjectToWorldTransform(ellipse_transform)\n",
"\n",
" ellipse_img = itk.spatial_object_to_image_filter(input=ellipse, inside_value=1, outside_value=0, size=output_size)\n",
"\n",
" momentor = itk.ImageMomentsCalculator.New(Image=ellipse_img)\n",
" momentor.Compute()\n",
"\n",
" centroid = momentor.GetCenterOfGravity()\n",
" prin_axes = itk.array_from_matrix(momentor.GetPrincipalAxes())\n",
" minor_axes = prin_axes[0]\n",
" major_axes = prin_axes[1]\n",
"\n",
" fig, ax = plt.subplots(figsize=[8,8])\n",
" plt.imshow(ellipse_img, cmap='gray')\n",
" plt.scatter(centroid[0], centroid[1])\n",
"\n",
" minor_pt = centroid + minor_axes*5\n",
" plt.plot([centroid[0], minor_pt[0]], [centroid[1], minor_pt[1]], color='green')\n",
"\n",
" major_pt = centroid + major_axes*5\n",
" plt.plot([centroid[0], major_pt[0]], [centroid[1], major_pt[1]], color='purple')\n",
"\n",
" print(momentor)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "seasonal-sandwich",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
56 changes: 56 additions & 0 deletions src/Filtering/ImageStatistics/CalculateImageMoments/Code.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*=========================================================================
*
* 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 "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkImageMomentsCalculator.h"

int
main(int argc, char * argv[])
{
if (argc != 2)
{
std::cerr << "Usage: " << std::endl;
std::cerr << argv[0];
std::cerr << " <InputFileName>" << std::endl;
std::cerr << "Prints image moments from unsigned short binary image.";
std::cerr << std::endl;
return EXIT_FAILURE;
}
const char * inputFileName = argv[1];

constexpr unsigned int Dimension = 2;

using PixelType = unsigned short;
using ImageType = itk::Image<PixelType, Dimension>;

using ReaderType = itk::ImageFileReader<ImageType>;
ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName(inputFileName);
reader->Update();

// clang-format off
using FilterType = itk::ImageMomentsCalculator<ImageType>;
// clang-format on
FilterType::Pointer filter = FilterType::New();
filter->SetImage(reader->GetOutput());
filter->Compute();
filter->Print(std::cout, 0);

return EXIT_SUCCESS;
}
28 changes: 28 additions & 0 deletions src/Filtering/ImageStatistics/CalculateImageMoments/Code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/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
import argparse

parser = argparse.ArgumentParser(description="Calculate Image Moments.")
parser.add_argument("input_image")

args = parser.parse_args()
input_image = itk.imread(args.input_image)
momentor = itk.ImageMomentsCalculator.New(Image=input_image)
momentor.Compute()
print(momentor)
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
Calculate Image Moments
================================

.. index::
single: ImageMomentsCalculator

Synopsis
--------


Calculate image moments from binary images and an interactive ellipse.


Results
-------

.. figure:: ellipse.mha
:alt: Input image

Input Image
::
Output
Comment thread
dzenanz marked this conversation as resolved.
ImageMomentsCalculator (000002037138BE90)
RTTI typeinfo: class itk::ImageMomentsCalculator<class itk::Image<unsigned short,2> >
Reference Count: 1
Modified Time: 249
Debug: Off
Object Name:
Observers:
none
Image: 000002037138FDD0
Valid: 1
Zeroth Moment about origin: 153
First Moment about origin: [30, 50]
Second Moment about origin: 15.0458 -8.8366
-8.8366 15.0458

Center of Gravity: [30, 50]
Second central moments: 15.0458 -8.8366
-8.8366 15.0458

Principal Moments: [950, 3654]
Principal axes: 0.707107 0.707107
-0.707107 0.707107


Jupyter Notebook
-----------------

.. image:: https://mybinder.org/badge_logo.svg
:target: https://mybinder.org/v2/gh/InsightSoftwareConsortium/ITKExamples/master?filepath=src%2FFiltering%2FImageStatistics%2FImageMomentsCalculator%2FCalculateEllipseMoments.ipynb

Code
----

Python
......

.. literalinclude:: Code.py
:language: python
:lines: 1,16-

C++
Comment thread
dzenanz marked this conversation as resolved.
...

.. literalinclude:: Code.cxx
:language: c++
:lines: 18-




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

.. breathelink:: itk::ImageMomentsCalculator
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a9dc7abe4d5745de06491d21addb54f561619732d71c98f250447c4fcf2c1444a60badbebaa3d646913e82fff75bfc753e2495c2d672d5bd7f85860fb8f8da0c
Loading