Coder Social home page Coder Social logo

itkthickness3d's Introduction

ITKThickness3D

An ITK module to compute 3D thickness

Build Status

PyPI Version

License

Overview

This is a module for the Insight Toolkit (ITK) that provides filters that compute the skeleton and thickness transforms of a 3D image.

ITK currently comes without a hands-on solution for 3D thickness evaluation. This contribution implements several filters based on the Euclidean distance transform and binary skeleton to fill this blank.

Binary thinning

Provides a 1 pixel-thin wire skeleton using an efficient curve thinning algorithm.

The thinning algorithm used in this module comes from the Insight Journal article:

Homann H.
Implementation of a 3D thinning algorithm
The Insight Journal - 2007 July - December.
https://hdl.handle.net/1926/1292
https://insight-journal.org/browse/publication/181

Medial thickness

The idea behind the medial thickness as implemented in this module is twice the shortest distance to the outter shell along the medial axis of the object (i.e. diameter of the local maximal fitting sphere).

This definition provides an unbiased method for thickness evaluation compared to the local thickness transform since this last one will result in a higher number of points for thick parts. The skeletonization insure a minimal set of measurements to fully describe the object.

Filters

Installation

Python

Binary Python packages are available for Linux, macOS, and Windows. They can be installed with:

python -m pip install --upgrade pip
python -m pip install itk-thickness3d

C++

You need to build ITK from source to use this module.

In the newer versions of ITK, this module is available as a Remote module in the ITK source code. Build it with the CMake option: Module_Thickness3D, this can be switched on with a CMake graphical interface ccmake or directly from the command line with: -DModule_Thickness3D:BOOL=ON

For older ITK versions, add it manually as an External or Remote module to the ITK source code:

External:

cd ${itk_src}/Modules/External
git clone https://github.com/InsightSoftwareConsortium/ITKThickness3D

Remote:

Create a file in ${itk_src}/Modules/Remote called Thickness3D.remote.cmake (see this GitHub gist) with the the following contents:

itk_fetch_module(Thickness3D
  "Tools for 3D thickness measurement"
  GIT_REPOSITORY ${git_protocol}://github.com/InsightSoftwareConsortium/ITKThickness3D.git
  GIT_TAG <replace with the latest stable commit tag>
)

Usage

Python

Once ITK imported, you can use the itk.MedialThicknessImageFilter3D just as any other ITK methods:

skeleton = itk.BinaryThinningImageFilter3D.New(image)

Here is a simple python script that reads an image, applies the medial thickness filter and writes the resulting image in a file:

import itk

input_filename = sys.argv[1]
output_filename = sys.argv[2]

image = itk.imread(input_filename)
thickness_map = itk.MedialThicknessImageFilter3D.New(image)

itk.imwrite(thickness_map, output_filename)

License

This software is distributed under the Apache 2.0 license. Please see the LICENSE file for details.

itkthickness3d's People

Contributors

dzenanz avatar hjmjohnson avatar jhlegarreta avatar mseng10 avatar t4mmi avatar tbirdso avatar thewtex avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

itkthickness3d's Issues

Medial thickness values

Hi! As I understood, MedialThicknessImageFilter3D counts diameter of the local maximal fitting sphere, but returns only the skeleton, based on these calculations. Is there a possibility to get these values of diameters for further analysis of thickness?

No module named 'itkHelpers'

Description

With the latest release of itk (version 5.2.0) the BinaryThinningImageFilter3D does not work anymore and fails with a ModuleNotFoundError.

Steps to reproduce

Package versions:

itk==5.2.0
itk-core==5.2.0
itk-filtering==5.2.0
itk-io==5.2.0
itk-numerics==5.2.0
itk-registration==5.2.0
itk-segmentation==5.2.0
itk-thickness3d==5.1.1 

Minimal example:

import itk 

image = itk.imread(<PATH TO A NIFTI FILE>)
skeleton = itk.BinaryThinningImageFilter3D.New(image)

fails with the following error message:

ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-4-78328829eebf> in <module>
----> 1 skeleton = itk.BinaryThinningImageFilter3D.New(image)

~/opt/anaconda3/envs/yuri/lib/python3.6/site-packages/itk/support/lazy.py in __getattribute__(self, attr)
     74                     module = self.__belong_lazy_attributes[attr]
     75                     namespace = {}
---> 76                     base.itk_load_swig_module(module, namespace)
     77                     self.loaded_lazy_modules.add(module)
     78                     for k, v in namespace.items():

~/opt/anaconda3/envs/yuri/lib/python3.6/site-packages/itk/support/base.py in itk_load_swig_module(name, namespace)
    108     # if we haven't already.
    109     loader = LibraryLoader()
--> 110     l_module = loader.load(swig_module_name)
    111 
    112     # OK, now the modules on which this one depends are loaded and

~/opt/anaconda3/envs/yuri/lib/python3.6/site-packages/itk/support/base.py in load(self, name)
    257             # since version 3.4: Use importlib.util.find_spec() instead.
    258             l_spec = importlib.util.find_spec(name)
--> 259             l_spec.loader.exec_module(l_module)  # pytype: disable=attribute-error
    260             return l_module
    261         finally:

~/opt/anaconda3/envs/yuri/lib/python3.6/importlib/_bootstrap_external.py in exec_module(self, module)

~/opt/anaconda3/envs/yuri/lib/python3.6/importlib/_bootstrap.py in _call_with_frames_removed(f, *args, **kwds)

~/opt/anaconda3/envs/yuri/lib/python3.6/site-packages/itk/support/../Thickness3DPython.py in <module>
     73 import itk.ITKDistanceMapPython
     74 import itk.ITKCommonPython
---> 75 from itk.itkThickness3DPython import *
     76 
     77 

~/opt/anaconda3/envs/yuri/lib/python3.6/site-packages/itk/itkThickness3DPython.py in <module>
    913 
    914 
--> 915 import itkHelpers
    916 @itkHelpers.accept_numpy_array_like_xarray
    917 def binary_thinning_image_filter3_d(*args, **kwargs):

ModuleNotFoundError: No module named 'itkHelpers'

Environment

MacOS, Python 3.6

Question regarding spurious branches in computed centerline

Hi @T4mmi,
I've been using your ITKThickness3D filter to compute the centerlines of airway segmentations.
For the most part, it works like charm. However, I've noticed that the centerline computed with ITKThickness3D sometimes contain what I would refer to as "short spurious branches".
I am not sure whether this is a bug in the implementation or an undesirable but sometimes to be expected behavior of the algorithm. As it's difficult to explain this, I've created a short example showing this phenomenon. Using the code below I create the skeleton of the airway segmentation:

import itk

airway_img_path = "airways.mhd"
centerline_path = "centerline_test.mhd"

airway_img = itk.imread(airway_img_path)

skeleton = itk.BinaryThinningImageFilter3D.New(airway_img)
pipeline_endpoint = skeleton

pipeline_endpoint.Update()


itk.imwrite(pipeline_endpoint, centerline_path)

I've upload the input file as well as the result I get here

If you open the centerline_test.mhd file, could you have a look at the two branches below the first bifurcation? In the middle of the left one of those two branches there is a small (2-points) branch sticking out to the side. Looking at the "airways.mhd" images I do not understand where these two points come from. Is this an expected behavior of the algorithm? Or am I overlooking something?
BTW, I've observed similar results for other airway geometries as well.

Input 3D image format support

I tried to read .obj file both as mesh and voxels. but the code image = itk.imread(input) is unable to read the file.
It throws an error :
reader = TemplateReaderType.New(**kwargs)
File "/home/anaconda3/envs/Pose/lib/python3.6/site-packages/itkTemplate.py", line 471, in New
return self._NewImageReader(itk.ImageFileReader, False, 'FileName', *args, **kwargs)
File "/home/anaconda3/envs/Pose/lib/python3.6/site-packages/itkTemplate.py", line 538, in _NewImageReader
raise RuntimeError("Could not create IO object for reading file %s" % inputFileName + msg)
RuntimeError: Could not create IO object for reading file 01.obj

what exactly should be the input and output so as to convert mesh or voxel 3D object to skeleton.

Problem with ITK 5.1.0

Hi there,
after updating to itk 5.1.0 I am experiencing an issue with the BinaryThinningImageFilter3D which did not occur with previous versions. Below is a minimal example to reproduce this:

import itk
import numpy as np
array = np.zeros((6, 5, 5), np.uint8)
array[:, 1:4, 1:4] = 1
origin = [0.0, 0.0, 0.0]
spacing = [0.5, 0.5, 0.7]
   
image_itk = itk.GetImageFromArray(array)
image_itk.SetOrigin(origin)
image_itk.SetSpacing(spacing)
 
skeleton = itk.BinaryThinningImageFilter3D.New(image_itk)
skeleton.Update()

When running this in cobination with the latest itk5.1.0, I get the following error:

RuntimeError: /Users/kitware/Dashboards/ITK/ITKPythonPackage/standalone-build/ITKs/Modules/Core/Common/src/itkProcessObject.cxx:1403:
itk::ERROR: BinaryThinningImageFilter3D(0x7fc108b065e0): Input Primary is required but not set.

When I downgrade to itk5.0.1 the same code runs just fine. Do you have any suggestions?

Restrict wrapping to 3D

The itk::MedialThicknessImageFilter is dependent on the itk::BinaryThinningImageFilter3D, which is only defined for 3D images. ITK compile time concept checks may stop compilation for 2D images, since it would not be valid.

In the Python wrapping add a third parameter, 3 to restrict wrapping for that dimension, i.e.

  itk_wrap_image_filter("${WRAP_ITK_SCALAR}" 2 3)

More details can be found in the wrapping macro documentation.

Import error with new itk version 5.3.0

Description

With the latest release of itk (version 5.3.0) the BinaryThinningImageFilter3D does not work anymore, and the import fails with an AttributeError.

Steps to reproduce

Package versions:

itk==5.3.0
itk-core==5.3.0
itk-filtering==5.3.0
itk-io==5.3.0
itk-numerics==5.3.0
itk-registration==5.3.0
itk-segmentation==5.3.0
itk-thickness3d==5.2.0

Minimal example:

import itk
    
PixelType = itk.ctype("unsigned char")
ImageType = itk.Image[PixelType, 3]
image = ImageType.New()

skeleton = itk.binary_thinning_image_filter3_d(image)

fails with the following error message:

Traceback (most recent call last):
    skeleton = itk.binary_thinning_image_filter3_d(image)
  File "/Users/mariebrei/opt/anaconda3/envs/test_env/lib/python3.9/site-packages/itk/support/lazy.py", line 138, in __getattribute__
    base.itk_load_swig_module(module, namespace)
  File "/Users/mariebrei/opt/anaconda3/envs/test_env/lib/python3.9/site-packages/itk/support/base.py", line 132, in itk_load_swig_module
    l_module = loader.load(swig_module_name)
  File "/Users/mariebrei/opt/anaconda3/envs/test_env/lib/python3.9/site-packages/itk/support/base.py", line 291, in load
    l_spec.loader.exec_module(l_module)  # pytype: disable=attribute-error
  File "<frozen importlib._bootstrap_external>", line 850, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "/Users/mariebrei/opt/anaconda3/envs/test_env/lib/python3.9/site-packages/itk/support/../Thickness3DPython.py", line 13, in <module>
    from . import _Thickness3DPython
AttributeError: PyCapsule_Import "_ITKCommonPython._C_API" is not valid

With itk==5.2.1.post1 everything works as expected.

Data/medial_thickness.tif is missing

The test/Data/medial_thickness.tif file is missing, referenced here:

https://github.com/T4mmi/ITKThickness3D/blob/1f638feff017e95fa86e1f53b7077dbd0c006eac/test/CMakeLists.txt#L15

and creating the error on CircleCI:

CMake Warning (dev) at /usr/share/cmake-3.11/Modules/ExternalData.cmake:690 (message):
  Data file referenced by argument

    DATA{Data/medial_thickness.tif}

  corresponds to source tree path

    test/Data/medial_thickness.tif

  that does not exist as a file (with or without an extension)!
Call Stack (most recent call first):
  /usr/share/cmake-3.11/Modules/ExternalData.cmake:494 (_ExternalData_arg)
  /usr/share/cmake-3.11/Modules/ExternalData.cmake:333 (ExternalData_expand_arguments)
  /ITK/CMake/ITKModuleTest.cmake:127 (ExternalData_add_test)
  test/CMakeLists.txt:12 (itk_add_test)
This warning is for project developers.  Use -Wno-dev to suppress it.

Is this a seperate module? Or is this a sub-module of ITK?

python -m pip install itk-thickness3d could install this module, right? However, the implementation is:

import itk

input_filename = sys.argv[1]
output_filename = sys.argv[2]

image = itk.imread(input_filename)
thickness_map = itk.MedialThicknessImageFilter3D.New(image)

itk.imwrite(thickness_map, output_filename)

The above script only import itk, instead of itk-thickness3d. So I have two questions:

  1. Can I use the function itk.MedialThicknessImageFilter3D if I only import itk?
  2. Why I installed itk-thickness3d but I do not need to use it?

Segmentation fault when calling MedialThicknessImageFilter3D on Linux

Hi,
I've been using the BinaryThinningImageFilter3D and the MedialThicknessImageFilter3D on my Mac (OS 10.14.3 with Python 3.6 ) for some time now. However, I keep getting a segmentation fault when calling the MedialThicknessImageFilter3D under Linux, while the same code executes flawlessly under osx. I am a bit out of my depth here and don't know whether the issue lies in the data I pass to the filter of if this is a Bug.

The problem can be reproduced with the attached
code snipped and the docker container by following these steps:

  1. Build the docker image:
    docker build -t test/modgen .
  2. Run docker container:
    docker run -it test/modgen /bin/bash
  3. Install ITKThickness3D:
    pip install itk-thickness3d
  4. Run the code provide in medial_axis_min.py in the container

itk.BinaryThinningImageFilter3D output an empty image

Thank you very much for sharing the code. However, I met an error when using BinaryThinningImageFilter3D, which output an empty image.

My environment is:
win 10
python 3.5.6

My code is:

import itk, os
import SimpleITK as sitk
import numpy as np
import scipy.io as sio
npImg = np.zeros(shape=[256,256,256],dtype=np.int16)
npImg[50:100, :, :] = 1
sitkimg = sitk.GetImageFromArray(npImg, isVector=False)
print('-------------sitk image --------------------')
print(sitkimg)

itkImage = itk.GetImageFromArray(sitk.GetArrayFromImage(sitkimg), is_vector =False)
print('-------------itk image --------------------')
print(itkImage)
skeleton = itk.BinaryThinningImageFilter3D.New(itkImage)
skeletonImg = skeleton.GetOutput()
print('-------------skeleton image --------------------')
print(skeletonImg)

From the result of print, we can find that:
the size of sitk image is 256256256
the size of itk image is: 256256256
the size of skeleton image is: 256256256

Those, I don't know what's the wrong for my code.
Thanks for any suggestion!

Build with older ITK version

I want to build this module in ITK-5.1.2.
I followed the instruction to clone the respoitory under Modules/External,
however, when I configure the source code there is no option "Module_Thickness3D" and after building I can't find the module in ITK-build directory either.
Did I miss any detail?

Consider publishing ARM bdist wheels for MacOS

Hi all,

I'm using this great library, but unfortunately can't pip install it on my newer macbook because only x86_64 wheels are currently published. Would you consider publishing ARM wheels for MacOS also, for python 3.8+?

Thanks!

Running with AttributeError

Hi,
Thanks for your package and I'm trying to use it to get the skeleton of an airway. And I used the example code I found in a former issure

import itk
import numpy as np
import imageio

# create the original test array
array = np.zeros((256,256,256),dtype=np.int16)
array[50:100, :, :] = 1
# cast to itk image
image = itk.GetImageViewFromArray(array)
# extract the skeleton
skeleton = itk.BinaryThinningImageFilter3D(image)
# cast back the skeleton from itk to numpy
output = itk.GetArrayViewFromImage(skeleton)
# simple way to see if output is empty:
print("original object size : {} vx".format(np.sum(array)))
print("skeleton size : {} vx".format(np.sum(output)))
# export as tiff objects fot visualization
imageio.volwrite("in.tif", array)
imageio.volwrite("out.tif", output)```

and it reported an error like this: 
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
d:\personal\find_airway_centerline.py in 
      27 image = itk.GetImageViewFromArray(array)
     28 # extract the skeleton
---> 29 skeleton = itk.BinaryThinningImageFilter3D(image)
     30 # cast back the skeleton from itk to numpy
     31 output = itk.GetArrayViewFromImage(skeleton)

D:\softwares\ANACONDA\envs\torch\lib\site-packages\itkLazy.py in __getattribute__(self, attr)
     50             module = self.__belong_lazy_attributes[attr]
     51             namespace = {}
---> 52             itkBase.LoadModule(module, namespace)
     53             self.loaded_lazy_modules.add(module)
     54             for k, v in namespace.items():

D:\softwares\ANACONDA\envs\torch\lib\site-packages\itkBase.py in LoadModule(name, namespace)
     59         if namespace is not None:
     60             swig = namespace.setdefault('swig', {})
---> 61             swig.update(this_module.swig)
     62 
     63             # don't worry about overwriting the symbols in namespace -- any

AttributeError: module 'itk.Thickness3DPython' has no attribute 'swig'
---------------------------------------------------------------------------
It's strange because I didn't name any files with "itk" inside the name. 
Codes were running on windows, using Python 3.6.10, in VS Code. Do you have any suggestion? 
Thanks! 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.