# Apply transformation to image and canvas

### Background

I have an image in figure like this:

``````from skimage import data
import matplotlib.pyplot as plt

fig, ax = plt.subplots(sharex='all', sharey='all')
ax.imshow(data.coins())
ax.set_ylim(1500, 0)
ax.set_xlim(-1500, 1500)
plt.show()
``````

### Challenges

I would like to apply a transformation to an image (rotation + translation). When I tried, the transformation was applied to the image but its background (canvas?) remained in place:

``````from skimage import data
import matplotlib.pyplot as plt
import numpy as np

[0, 0, 1]])
tform_euclidean = transform.EuclideanTransform(matrix)
img_warp_euclidean = transform.warp(data.coins(), tform_euclidean)

fig, ax = plt.subplots(sharex='all', sharey='all')
ax.imshow(img_warp_euclidean)
ax.set_ylim(1500, 0)
ax.set_xlim(-1500, 1500)
plt.show()
``````

Is there a way to apply the transformation to the image plus its canvas?

Hi @Olivier,

Is this (or something similar) what youâ€™re after?

If so, then you can do it like this:

``````matrix = np.array([[np.cos(np.deg2rad(5)), -np.sin(np.deg2rad(5)), 0],
[0, 0, 1]])
tform_euclidean = transform.EuclideanTransform(matrix)

coins_img = data.coins()

# Compute the max of the bounding box that maps into the image.
# Note that we need
pts = np.array([[0,0]])
for x,y in itertools.product( [0,coins_img.shape[0]],[0,coins_img.shape[1]] ):
tformed_pt = tform_euclidean.inverse([y,x]) # need to flip xy
pts = np.concatenate( (pts,tformed_pt), axis=0 )

# ceil and flip x-y back
max_pt = np.flip(np.ceil( np.amax( pts, axis=0 )))

# tell transform.warp what the new (bigger) bounding box is
img_warp_euclidean = transform.warp( data.coins(), tform_euclidean, output_shape=max_pt )

fig, ax = plt.subplots(sharex='all', sharey='all')
ax.imshow(img_warp_euclidean)
ax.set_ylim(1500, 0)
ax.set_xlim(-1500, 1500)
plt.show()
``````

Hopefully the comments are helpful, but post back if something is unclear
John

2 Likes

Thanks @bogovicj!
why do the edges seem more â€śpixelisedâ€ť in your example?
My original intention was to not see any bounding box. Is it possible to not see the dark background left after the transformation?

Hi @Olivier,

probably because i took a pretty low-res screenshot

My original intention was to not see any bounding box. Is it possible to not see the dark background left after the transformation?

As I understand it, that would be matplotlibâ€™s job more than scikit-imageâ€™s job, I imagine something like this should work:

1. Generate a matplotlib patch matching your image
2. Transform the image as above (resulting in a too-big bounding box)
3. Transform the patch to match it.
4. Clip the image with the transformed patch (which i think should fix the bounding box)

John

Great, I will look into this. Many thanks!

Good luck!
and please post back if you manage to get it working!

You can use `cval=np.nan` in the call to `warp` to fill the parts outside the image with `nan`, which matplotlib renders as transparent.

1 Like

Thank you @jni, this completes nicely the solution proposed by @bogovicj

``````matrix = np.array([[np.cos(np.deg2rad(5)), -np.sin(np.deg2rad(5)), 0],
[0, 0, 1]])
tform_euclidean = transform.EuclideanTransform(matrix)
coins_img = data.coins()

# Compute the max of the bounding box that maps into the image.
# Note that we need
pts = np.array([[0, 0]])
for x, y in itertools.product([0, coins_img.shape[0]], [0, coins_img.shape[1]]):
tformed_pt = tform_euclidean.inverse([y, x])  # need to flip xy
pts = np.concatenate((pts, tformed_pt), axis=0)

# ceil and flip x-y back
max_pt = np.flip(np.ceil(np.amax(pts, axis=0)))

# tell transform.warp what the new (bigger) bounding box is
img_warp_euclidean = transform.warp(data.coins(), tform_euclidean, output_shape=max_pt, cval=np.nan)

fig, ax = plt.subplots(sharex='all', sharey='all')
ax.imshow(img_warp_euclidean)
ax.set_ylim(1500, 0)
ax.set_xlim(-1500, 1500)
plt.show()
``````

3 Likes