RectilinearWipeWidget
Repository source: RectilinearWipeWidget
Description¶
This example illustrates the Rectilinear Wipe widget. This widget is useful for comparing two images. There are 7 different image comparison modes. A rectilinear wipe is a 2x2 checkerboard pattern created by combining two separate images, where various combinations of the checker squares are possible. Using this widget, the user can adjust the layout of the checker pattern, such as moving the center point, moving the horizontal separator, or moving the vertical separator.
Pressing keys 0-6 select the various wipe modes.
For an alternative image comparison widget try the Checkerboard widget.
Other languages
See (Cxx)
Question
If you have a question about this example, please use the VTK Discourse Forum
Code¶
RectilinearWipeWidget.py
# !/usr/bin/env python3
from dataclasses import dataclass
# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.util.execution_model import select_ports
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkIOImage import vtkImageReader2Factory
from vtkmodules.vtkImagingHybrid import vtkImageRectilinearWipe
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleImage
from vtkmodules.vtkInteractionWidgets import vtkRectilinearWipeWidget
from vtkmodules.vtkRenderingCore import (
vtkImageActor,
vtkRenderWindow,
vtkRenderWindowInteractor,
vtkRenderer
)
def get_program_parameters():
import argparse
description = 'Rectilinear Wipe Widget.'
epilogue = '''
'''
parser = argparse.ArgumentParser(description=description, epilog=epilogue,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('file_name1', help='The first file name to use e.g. Gourds2.jpg.')
parser.add_argument('file_name2', help='The second file name to use e.g. Ox.jpg.')
parser.add_argument('-w', '--wipe_mode', required=False, type=int, choices=range(0, 7), default=0, metavar="[0-6]",
help='Image comparison modes. Default is 0.')
args = parser.parse_args()
return args.file_name1, args.file_name2, args.wipe_mode
def main():
file_name1, file_name2, wipe_mode = get_program_parameters()
# Read the images.
reader1 = vtkImageReader2Factory().CreateImageReader2(file_name1)
reader1.file_name = file_name1
reader2 = vtkImageReader2Factory().CreateImageReader2(file_name2)
reader2.file_name = file_name2
# Create a wipe pipeline.
wipe = vtkImageRectilinearWipe(position=(256, 256), wipe=wipe_mode)
reader1 >> select_ports(0, wipe)
reader2 >> select_ports(1, wipe)
# Create the RenderWindow, Renderer and both Actors.
colors = vtkNamedColors()
ren = vtkRenderer(background=colors.GetColor3d('Wheat'))
ren_win = vtkRenderWindow(size=(900, 900), window_name='RectilinearWipeWidget')
ren_win.AddRenderer(ren)
iren = vtkRenderWindowInteractor()
iren.render_window = ren_win
style = vtkInteractorStyleImage()
iren.interaction_style = style
wipe_actor = vtkImageActor()
wipe >> wipe_actor.mapper
# VTK widgets consist of two parts: the widget part that handles
# event processing and the widget representation that defines how
# the widget appears in the scene,
# (i.e., matters pertaining to geometry).
wipe_widget = vtkRectilinearWipeWidget()
wipe_widget.interactor = iren
wipe_widget_rep = wipe_widget.representation
wipe_widget_rep.image_actor = wipe_actor
wipe_widget_rep.rectilinear_wipe = wipe
wipe_widget_rep.property.line_width = 2.0
wipe_widget_rep.property.opacity = 0.75
# Add the actors to the renderer, set the background and size.
ren.AddActor(wipe_actor)
iren.Initialize()
wis = WipeInteractorStyle(wipe, ren_win)
iren.AddObserver('KeyPressEvent', wis.select_layer)
# Render the image.
ren_win.Render()
wipe_widget.On()
iren.Start()
def build_keys():
keycodes = [
'0', 'KP_0',
'1', 'KP_1',
'2', 'KP_2',
'3', 'KP_3',
'4', 'KP_4',
'5', 'KP_5',
'6', 'KP_6',
# '7', 'KP_7',
# '8', 'KP_8',
# '9', 'KP_0',
]
kv = dict()
for v in keycodes:
if 'KP_' in v:
x = int(v.split('_')[1])
else:
x = int(v)
kv[v] = x
return kv
class WipeInteractorStyle():
def __init__(self, wipe, ren_win):
super().__init__()
self.wipe = wipe
self.ren_win = ren_win
self.keys = build_keys()
print(self.keys)
def select_layer(self, caller, ev):
"""
Select the layer to manipulate.
:param caller:
:param ev:
:return:
"""
iren = caller
key = iren.key_sym
if key in self.keys:
self.wipe.SetWipe(self.keys[key])
self.ren_win.Render()
@dataclass(frozen=True)
class InteractorStyleImage:
@dataclass(frozen=True)
class Style:
VTKIS_IMAGE2D: int = 2
VTKIS_IMAGE3D: int = 3
VTKIS_IMAGE_SLICING: int = 4
@dataclass(frozen=True)
class Motion:
VTKIS_WINDOW_LEVEL: int = 1024
VTKIS_SLICE: int = 1025
if __name__ == '__main__':
main()