Skip to content
Snippets Groups Projects
Commit 9edc8378 authored by Andrew Maclean's avatar Andrew Maclean
Browse files

Adding ImageProcessing examples

parent cec004d6
No related branches found
No related tags found
1 merge request!327Add pythonic api examples 1
Showing
with 580 additions and 0 deletions
### Description
This MRI image illustrates attenuation that can occur due to sensor position. The artifact is removed by dividing by the attenuation profile determined manually. This histograms shows how the artifact hides information in the form of scalar value clusters.
!!! info
See [this figure](../../../VTKBook/10Chapter10/#Figure%2010-6) in [Chapter 10](../../../VTKBook/10Chapter10) the [VTK Textbook](../../../VTKBook/01Chapter1).
#!/usr/bin/env python3
from dataclasses import dataclass
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonDataModel import vtkSphere
from vtkmodules.vtkIOImage import vtkImageReader2Factory
from vtkmodules.vtkImagingCore import (
vtkImageCast,
vtkImageShiftScale
)
from vtkmodules.vtkImagingGeneral import vtkImageGaussianSmooth
from vtkmodules.vtkImagingHybrid import vtkSampleFunction
from vtkmodules.vtkImagingMath import vtkImageMathematics
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleImage
from vtkmodules.vtkRenderingCore import (
vtkImageActor,
vtkRenderWindow,
vtkRenderWindowInteractor,
vtkRenderer
)
def get_program_parameters():
import argparse
description = 'This MRI image illustrates attenuation that can occur due to sensor position.'
epilogue = '''
The artifact is removed by dividing by the attenuation profile determined manually.
'''
parser = argparse.ArgumentParser(description=description, epilog=epilogue,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('filename', help='AttenuationArtifact.pgm.')
args = parser.parse_args()
return args.filename
def main():
colors = vtkNamedColors()
file_name = get_program_parameters()
# Read the image.
reader = vtkImageReader2Factory().CreateImageReader2(file_name)
reader.file_name = file_name
cast = vtkImageCast(output_scalar_type=ImageCastOutputScalarType().VTK_DOUBLE)
# Get rid of the discrete scalars.
smooth = vtkImageGaussianSmooth(standard_deviations=(0.8, 0.8, 0))
m1 = vtkSphere(center=(310, 130, 0), radius=0)
m2 = vtkSampleFunction(implicit_function=m1, model_bounds=(0, 264, 0, 264, 0, 1), sample_dimensions=(264, 264, 1))
m3 = vtkImageShiftScale(scale=0.000095)
div = vtkImageMathematics(operation=ImageMathematicsOperation().VTK_MULTIPLY)
# Create the actors.
color_window = 256.0
color_level = 127.5
original_actor = vtkImageActor()
original_actor.property.color_window = color_window
original_actor.property.color_level = color_level
filtered_actor = vtkImageActor()
# Define the viewport ranges.
# (xmin, ymin, xmax, ymax)
original_viewport = [0.0, 0.0, 0.5, 1.0]
filtered_viewport = [0.5, 0.0, 1.0, 1.0]
# Set up the pipelines.
p = reader >> cast
p >> original_actor.mapper
(p >> smooth, m2 >> m3) >> div >> filtered_actor.mapper
# Set up the renderers.
original_renderer = vtkRenderer(background=colors.GetColor3d('SlateGray'), viewport=original_viewport)
filtered_renderer = vtkRenderer(background=colors.GetColor3d('LightSlateGray'), viewport=filtered_viewport)
original_renderer.AddActor(original_actor)
filtered_renderer.AddActor(filtered_actor)
original_renderer.ResetCamera()
filtered_renderer.ResetCamera()
render_window = vtkRenderWindow(size=(600, 300), window_name='Attenuation')
render_window.AddRenderer(original_renderer)
render_window.AddRenderer(filtered_renderer)
render_window_interactor = vtkRenderWindowInteractor()
style = vtkInteractorStyleImage()
render_window_interactor.SetInteractorStyle(style)
render_window_interactor.SetRenderWindow(render_window)
render_window_interactor.Initialize()
render_window_interactor.Start()
@dataclass(frozen=True)
class ImageCastOutputScalarType:
VTK_CHAR: int = 2
VTK_UNSIGNED_CHAR: int = 3
VTK_SHORT: int = 4
VTK_UNSIGNED_SHORT: int = 5
VTK_INT: int = 6
VTK_UNSIGNED_INT: int = 7
VTK_LONG: int = 8
VTK_UNSIGNED_LONG: int = 9
VTK_FLOAT: int = 10
VTK_DOUBLE: int = 11
@dataclass(frozen=True)
class ImageMathematicsOperation:
VTK_ADD: int = 0
VTK_SUBTRACT: int = 1
VTK_MULTIPLY: int = 2
VTK_DIVIDE: int = 3
VTK_INVERT: int = 4
VTK_SIN: int = 5
VTK_COS: int = 6
VTK_EXP: int = 7
VTK_LOG: int = 8
VTK_ABS: int = 9
VTK_SQR: int = 10
VTK_SQRT: int = 11
VTK_MIN: int = 12
VTK_MAX: int = 13
VTK_ATAN: int = 14
VTK_ATAN2: int = 15
VTK_MULTIPLYBYK: int = 16
VTK_ADDC: int = 17
VTK_CONJUGATE: int = 18
VTK_COMPLEX_MULTIPLY: int = 19
VTK_REPLACECBYK: int = 20
if __name__ == '__main__':
main()
### Description
High-pass filters can also be used to compress the range of an image. Since low frequencies account for much of the dynamic range of an image but carry little information, a high-pass filter can significantly decrease an image’s scalar range and emphasize hidden details. The Laplacian filter, which is a second derivative operation, is one implementation of a high-pass filter. It eliminates constant and low frequencies leaving only high-frequency edges. The output of the Laplacian can be subtracted from the original image to produce edge enhancement or sharpening of an image.
This example subtracts the Laplacian (middle) from the original image (left) resulting in edge enhancement or a sharpening operation (right).
!!! info
See [this figure](../../../VTKBook/10Chapter10/#Figure%2010-9) in [Chapter 10](../../../VTKBook/10Chapter10) the [VTK Textbook](../../../VTKBook/01Chapter1).
#!/usr/bin/env python3
from dataclasses import dataclass
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkIOImage import vtkImageReader2Factory
from vtkmodules.vtkImagingColor import vtkImageMapToWindowLevelColors
from vtkmodules.vtkImagingCore import vtkImageCast
from vtkmodules.vtkImagingGeneral import vtkImageLaplacian
from vtkmodules.vtkImagingMath import vtkImageMathematics
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleImage
from vtkmodules.vtkRenderingCore import (
vtkImageActor,
vtkRenderWindow,
vtkRenderWindowInteractor,
vtkRenderer
)
def get_program_parameters():
import argparse
description = 'High-pass filters can extract and enhance edges in an image.'
epilogue = '''
Subtraction of the Laplacian (middle) from the original image (left) results
in edge enhancement or a sharpening operation (right).
'''
parser = argparse.ArgumentParser(description=description, epilog=epilogue,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('filename', help='FullHead.mhd.')
args = parser.parse_args()
return args.filename
def main():
file_name = get_program_parameters()
# Read the image.
reader = vtkImageReader2Factory().CreateImageReader2(file_name)
reader.file_name = file_name
reader.update()
scalar_range = list()
for i in range(0, 2):
scalar_range.append(reader.GetOutput().GetPointData().GetScalars().GetRange()[i])
print("Range:", scalar_range)
middle_slice = 22
# Work with triple images.
cast = vtkImageCast(output_scalar_type=ImageCastOutputScalarType().VTK_DOUBLE)
laplacian = vtkImageLaplacian(dimensionality=3)
enhance = vtkImageMathematics(operation=ImageMathematicsOperation().VTK_SUBTRACT)
color_window = (scalar_range[1] - scalar_range[0])
color_level = color_window / 2
# Map the image through the lookup table.
original_color = vtkImageMapToWindowLevelColors(window=color_window, level=color_level)
display_extent = list()
data_extent = reader.data_extent
for i in range(0, 4):
display_extent.append(data_extent[i])
for i in range(0, 2):
display_extent.append(middle_slice)
original_actor = vtkImageActor(display_extent=display_extent)
original_actor.property.interpolation_type = VolumePropertyInterpolationType().VTK_NEAREST_INTERPOLATION
laplacian_color = vtkImageMapToWindowLevelColors(window=1000, level=0)
laplacian_actor = vtkImageActor(display_extent=original_actor.GetDisplayExtent())
laplacian_actor.property.interpolation_type = VolumePropertyInterpolationType().VTK_NEAREST_INTERPOLATION
enhanced_color = vtkImageMapToWindowLevelColors(window=color_window, level=color_level)
enhanced_actor = vtkImageActor(display_extent=original_actor.GetDisplayExtent())
enhanced_actor.property.interpolation_type = VolumePropertyInterpolationType().VTK_NEAREST_INTERPOLATION
# Set up the pipelines.
reader >> original_color >> original_actor.mapper
p = reader >> cast
q = p >> laplacian
q >> laplacian_color >> laplacian_actor.mapper
(p, q) >> enhance >> enhanced_color >> enhanced_actor.mapper
# Setup the renderers.
original_renderer = vtkRenderer()
laplacian_renderer = vtkRenderer()
enhanced_renderer = vtkRenderer()
original_renderer.AddActor(original_actor)
laplacian_renderer.AddActor(laplacian_actor)
enhanced_renderer.AddActor(enhanced_actor)
renderers = list()
renderers.append(original_renderer)
renderers.append(laplacian_renderer)
renderers.append(enhanced_renderer)
# Setup viewports for the renderers.
renderer_size = 400
x_grid_dimensions = 3
y_grid_dimensions = 1
ren_win_size = (renderer_size * x_grid_dimensions, renderer_size * y_grid_dimensions)
render_window = vtkRenderWindow(size=ren_win_size, window_name='EnhanceEdges')
# render_window.SetSize(renderer_size * x_grid_dimensions, renderer_size * y_grid_dimensions)
for row in range(0, y_grid_dimensions):
for col in range(x_grid_dimensions):
index = row * x_grid_dimensions + col
# (xmin, ymin, xmax, ymax)
viewport = [float(col) / x_grid_dimensions, float(y_grid_dimensions - (row + 1)) / y_grid_dimensions,
float(col + 1) / x_grid_dimensions, float(y_grid_dimensions - row) / y_grid_dimensions]
renderers[index].SetViewport(viewport)
render_window.AddRenderer(renderers[index])
render_window_interactor = vtkRenderWindowInteractor()
style = vtkInteractorStyleImage()
render_window_interactor.SetInteractorStyle(style)
render_window_interactor.SetRenderWindow(render_window)
# Renderers share one camera.
render_window.Render()
renderers[0].GetActiveCamera().Dolly(1.5)
renderers[0].ResetCameraClippingRange()
for r in range(1, len(renderers)):
renderers[r].SetActiveCamera(renderers[0].GetActiveCamera())
render_window_interactor.Initialize()
render_window_interactor.Start()
@dataclass(frozen=True)
class ImageCastOutputScalarType:
VTK_CHAR: int = 2
VTK_UNSIGNED_CHAR: int = 3
VTK_SHORT: int = 4
VTK_UNSIGNED_SHORT: int = 5
VTK_INT: int = 6
VTK_UNSIGNED_INT: int = 7
VTK_LONG: int = 8
VTK_UNSIGNED_LONG: int = 9
VTK_FLOAT: int = 10
VTK_DOUBLE: int = 11
@dataclass(frozen=True)
class ImageMathematicsOperation:
VTK_ADD: int = 0
VTK_SUBTRACT: int = 1
VTK_MULTIPLY: int = 2
VTK_DIVIDE: int = 3
VTK_INVERT: int = 4
VTK_SIN: int = 5
VTK_COS: int = 6
VTK_EXP: int = 7
VTK_LOG: int = 8
VTK_ABS: int = 9
VTK_SQR: int = 10
VTK_SQRT: int = 11
VTK_MIN: int = 12
VTK_MAX: int = 13
VTK_ATAN: int = 14
VTK_ATAN2: int = 15
VTK_MULTIPLYBYK: int = 16
VTK_ADDC: int = 17
VTK_CONJUGATE: int = 18
VTK_COMPLEX_MULTIPLY: int = 19
VTK_REPLACECBYK: int = 20
@dataclass(frozen=True)
class VolumePropertyInterpolationType:
VTK_NEAREST_INTERPOLATION: int = 0
VTK_LINEAR_INTERPOLATION: int = 1
VTK_CUBIC_INTERPOLATION: int = 2
if __name__ == '__main__':
main()
### Description
Low-pass filters can be implemented as convolution with a Gaussian kernel. The Gaussian kernel displayed on top has been magnified for this figure.
!!! info
See [this figure](../../../VTKBook/10Chapter10/#Figure%2010-2) in [Chapter 10](../../../VTKBook/10Chapter10) the [VTK Textbook](../../../VTKBook/01Chapter1).
#!/usr/bin/env python3
from dataclasses import dataclass
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkIOImage import vtkImageReader2Factory
from vtkmodules.vtkImagingCore import vtkImageCast
from vtkmodules.vtkImagingGeneral import vtkImageGaussianSmooth
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleImage
from vtkmodules.vtkRenderingCore import (
vtkImageActor,
vtkRenderWindow,
vtkRenderWindowInteractor,
vtkRenderer
)
def get_program_parameters():
import argparse
description = 'Low-pass filters can be implemented as convolution with a Gaussian kernel.'
epilogue = '''
'''
parser = argparse.ArgumentParser(description=description, epilog=epilogue,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('filename', help='Gourds.png.')
args = parser.parse_args()
return args.filename
def main():
colors = vtkNamedColors()
file_name = get_program_parameters()
# Read the image.
reader = vtkImageReader2Factory().CreateImageReader2(file_name)
reader.file_name = file_name
# Process the image.
cast = vtkImageCast(output_scalar_type=ImageCastOutputScalarType().VTK_FLOAT)
smoothing_filter = vtkImageGaussianSmooth(dimensionality=2, standard_deviations=(4.0, 4.0),
radius_factors=(2.0, 2.0))
# Create the actors.
original_actor = vtkImageActor()
filtered_actor = vtkImageActor()
# Set up the pipelines.
reader >> original_actor.mapper
reader >> cast >> smoothing_filter >> filtered_actor.mapper
# Define the viewport ranges.
# (xmin, ymin, xmax, ymax)
original_viewport = [0.0, 0.0, 0.5, 1.0]
filtered_viewport = [0.5, 0.0, 1.0, 1.0]
# Setup the renderers.
original_renderer = vtkRenderer(background=colors.GetColor3d("SlateGray"), viewport=original_viewport)
filtered_renderer = vtkRenderer(background=colors.GetColor3d("LightSlateGray"), viewport=filtered_viewport)
original_renderer.AddActor(original_actor)
filtered_renderer.AddActor(filtered_actor)
original_renderer.ResetCamera()
filtered_renderer.ResetCamera()
render_window = vtkRenderWindow(size=(600, 300), window_name='GaussianSmooth')
render_window.AddRenderer(original_renderer)
render_window.AddRenderer(filtered_renderer)
render_window_interactor = vtkRenderWindowInteractor()
style = vtkInteractorStyleImage()
render_window_interactor.SetInteractorStyle(style)
render_window_interactor.SetRenderWindow(render_window)
render_window_interactor.Initialize()
render_window_interactor.Start()
@dataclass(frozen=True)
class ImageCastOutputScalarType:
VTK_CHAR: int = 2
VTK_UNSIGNED_CHAR: int = 3
VTK_SHORT: int = 4
VTK_UNSIGNED_SHORT: int = 5
VTK_INT: int = 6
VTK_UNSIGNED_INT: int = 7
VTK_LONG: int = 8
VTK_UNSIGNED_LONG: int = 9
VTK_FLOAT: int = 10
VTK_DOUBLE: int = 11
if __name__ == '__main__':
main()
### Description
The discrete Fourier transform changes an image from the spatial domain into the frequency domain, where each pixel represents a sinusoidal function. This example shows an image and its power spectrum displayed using a logarithmic transfer function.
!!! info
See [Figure 10-10](../../../VTKBook/10Chapter10/#Figure%2010-10) in [Chapter 10](../../../VTKBook/10Chapter10) the [VTK Textbook](../../../VTKBook/01Chapter1).
#!/usr/bin/env python3
from dataclasses import dataclass
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkIOImage import vtkImageReader2Factory
from vtkmodules.vtkImagingCore import vtkImageMapToColors
from vtkmodules.vtkImagingFourier import (
vtkImageFFT,
vtkImageFourierCenter
)
from vtkmodules.vtkImagingMath import (
vtkImageLogarithmicScale,
vtkImageMagnitude
)
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleImage
from vtkmodules.vtkRenderingCore import (
vtkImageActor,
vtkRenderWindow,
vtkRenderWindowInteractor,
vtkRenderer,
vtkWindowLevelLookupTable
)
def get_program_parameters():
import argparse
description = 'The discrete Fourier transform.'
epilogue = '''
This changes an image from the spatial domain into the frequency domain,
where each pixel represents a sinusoidal function.
This figure shows an image and its power spectrum displayed using a logarithmic transfer function.
'''
parser = argparse.ArgumentParser(description=description, epilog=epilogue,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('filename', help='vtks.pgm.')
args = parser.parse_args()
return args.filename
def main():
colors = vtkNamedColors()
file_name = get_program_parameters()
# Read the image.
reader = vtkImageReader2Factory().CreateImageReader2(file_name)
reader.file_name = file_name
# The fft stuff.
fft = vtkImageFFT()
mag = vtkImageMagnitude()
center = vtkImageFourierCenter()
compress = vtkImageLogarithmicScale(constant=15)
# Create the actors.
original_actor = vtkImageActor()
original_actor.property.interpolation_type = VolumePropertyInterpolationType().VTK_NEAREST_INTERPOLATION
compressed_actor = vtkImageActor()
compressed_actor.property.interpolation_type = VolumePropertyInterpolationType().VTK_NEAREST_INTERPOLATION
create_image_actor(compressed_actor, 160, 120)
# Set up the pipelines.
reader >> original_actor.mapper
reader >> fft >> mag >> center >> compress >> compressed_actor.mapper
# Define the viewport ranges.
# (xmin, ymin, xmax, ymax)
original_viewport = [0.0, 0.0, 0.5, 1.0]
compressed_viewport = [0.5, 0.0, 1.0, 1.0]
# Setup the renderers.
original_renderer = vtkRenderer(background=colors.GetColor3d('SlateGray'), viewport=original_viewport)
compressed_renderer = vtkRenderer(background=colors.GetColor3d('LightSlateGray'), viewport=compressed_viewport)
original_renderer.AddActor(original_actor)
compressed_renderer.AddActor(compressed_actor)
original_renderer.ResetCamera()
compressed_renderer.ResetCamera()
render_window = vtkRenderWindow(size=(600, 300), window_name='VTKSpectrum')
render_window.AddRenderer(original_renderer)
render_window.AddRenderer(compressed_renderer)
render_window_interactor = vtkRenderWindowInteractor()
style = vtkInteractorStyleImage()
render_window_interactor.SetInteractorStyle(style)
render_window_interactor.SetRenderWindow(render_window)
render_window_interactor.Initialize()
render_window_interactor.Start()
def create_image_actor(actor, color_window, color_level):
wlut = vtkWindowLevelLookupTable(window=color_window, level=color_level)
wlut.Build()
# Map the image through the lookup table.
color = vtkImageMapToColors(lookup_table=wlut)
actor.mapper.input >> color
color >> actor.mapper
return
@dataclass(frozen=True)
class VolumePropertyInterpolationType:
VTK_NEAREST_INTERPOLATION: int = 0
VTK_LINEAR_INTERPOLATION: int = 1
VTK_CUBIC_INTERPOLATION: int = 2
if __name__ == '__main__':
main()
src/Testing/Baseline/PythonicAPI/ImageProcessing/TestAttenuation.png

130 B

src/Testing/Baseline/PythonicAPI/ImageProcessing/TestEnhanceEdges.png

131 B

src/Testing/Baseline/PythonicAPI/ImageProcessing/TestGaussianSmooth.png

131 B

src/Testing/Baseline/PythonicAPI/ImageProcessing/TestVTKSpectrum.png

130 B

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment