 # 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,coins_img.shape] ):
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, coins_img.shape]):
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