Search code examples
pythonscikit-image

skimage: defining vertical shear


Python skimage package has a function transform.AffineTransform() where one of the options is shear which does horizontal shear.

Obviously, I can do a vertical shear by switching axes back and forth. This is what I do:

from skimage import data, transform
import matplotlib.pyplot as plt
import numpy as np

img = data.astronaut()/255

v = 0.3

tf = transform.AffineTransform(shear=-v)
img2 = transform.warp(img, tf, order=1, preserve_range=True, mode='constant')

img3 = np.swapaxes(img, 0, 1)
img3 = transform.warp(img3, tf, order=1, preserve_range=True, mode='constant')
img3 = np.swapaxes(img3, 0, 1)

plt.imshow(np.hstack([img, img2, img3]))
plt.show()

shear

Anyway, I am surprised there is no more direct way to define a vertical shear option... Am I mistaken?


Solution

  • Your question (and linked page) holds the answer... as AffineTransform allows you to specify the transformation matrix, and your linked wiki page shows what this is, it is pretty straight forward to reduce the number of operations by directly specifying the transformation matrix, e.g.

    from skimage import data, transform
    import matplotlib.pyplot as plt
    import numpy as np
    
    img = data.astronaut()/255
    
    v = 0.3
    
    tf = transform.AffineTransform(shear=-v)
    img2 = transform.warp(img, tf, order=1, preserve_range=True, mode='constant')
    
    img3 = np.swapaxes(img, 0, 1)
    img3 = transform.warp(img3, tf, order=1, preserve_range=True, mode='constant')
    img3 = np.swapaxes(img3, 0, 1)
    
    plt.imshow(np.hstack([img, img2, img3]))
    
    # Using the transformation matrix directly...
    
    tf_h = transform.AffineTransform(
        np.array([[1, 0.3, 0], [0, 1, 0], [0, 0, 1]]))
    img4 = transform.warp(img, tf, order=1, preserve_range=True, mode='constant')
    tf_v = transform.AffineTransform(
        np.array([[1, 0, 0], [0.3, 1, 0], [0, 0, 1]]))
    img4 = transform.warp(img, tf_h, order=1, preserve_range=True, mode='constant')
    img5 = transform.warp(img, tf_v, order=1, preserve_range=True, mode='constant')
    
    plt.figure()
    plt.imshow(np.hstack([img, img4, img5]))
    
    plt.show()
    

    You should see two figures with the same set of images.