Skip to content

Instantly share code, notes, and snippets.

@pelson
Created August 31, 2014 15:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pelson/bf7cd805ea2d3eabc6a4 to your computer and use it in GitHub Desktop.
Save pelson/bf7cd805ea2d3eabc6a4 to your computer and use it in GitHub Desktop.
Image manipulation using mpl for @stefanv.
"""
Example of applying text to an image for Stefan VdW.
The image is not transfomed throgh the mpl pipeline, and is instead
constrained to pixel space of the figure's resulting image.
"""
def new_figure(width, height):
"""
Creates a figure, outside of the PyPlot interface, which can draw mpl
components on top of an image.
"""
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.figure import Figure
fig = Figure(figsize=(width / 100., height / 100.), dpi=100)
# Create the canvas for the figure (which gets attached to the
# figure inside the constructor.
FigureCanvasAgg(fig)
return fig
def figure_image(figure, image):
"""Adds a FirgureImage instance to a figure.
A FigureImage is an image which is not transformed in the mpl
stack, and so its pixels are 1-to-1 with the final figure. If the
final figure is not of the **exact** size of the image, parts of the
image will either be cropped, or parts of the figure will be empty.
"""
from matplotlib.image import FigureImage
figimg = FigureImage(figure)
figimg.set_array(image)
figure.images.append(figimg)
return figimg
def verify(new_img, old_img):
import matplotlib.pyplot as plt
plt.switch_backend('tkagg')
fig, axes = plt.subplots(3, 3, sharex=True, squeeze=True, sharey=True)
axes[0, 0].set_title('Original')
axes[0, 1].set_title('New')
axes[0, 2].set_title('Diff (0 masked)')
axes[0, 0].set_ylabel('Red')
axes[1, 0].set_ylabel('Green')
axes[2, 0].set_ylabel('Blue')
for channel in range(3):
axes[channel, 0].imshow(old_img[:, :, channel], interpolation='none')
axes[channel, 1].imshow(new_img[:, :, channel], interpolation='none')
diff = img[:, :, channel] - new_img[:, :, channel]
diff = np.ma.masked_equal(diff, 0)
axes[channel, 2].imshow(diff)
plt.show()
if __name__ == '__main__':
from skimage.data import lena
img = lena()
width, height = img.shape[:2]
# Create a new figure. This can either be with PyPlot (with the right
# dpi etc.) or just by calling the utility function.
fig = new_figure(width, height)
# fig = plt.figure(figsize=(width / 100., height / 100.), dpi=100)
figure_image(fig, img)
# Do whatever we want on the figure (a transform=None) will give us
# pixel coordinates from the **bottom left** of the figure.
text = fig.text(200, 100, 'Hello Lena', size=20)
text.set_transform(None)
# We can pump this to a file.
fig.savefig('out.png', dpi=100)
# Or get hold of it as an array.
import numpy as np
import numpy.ma
new_img = np.array(fig.canvas.buffer_rgba()).reshape([width, height, 4])
verify(new_img, img)
@pelson
Copy link
Author

pelson commented Aug 31, 2014

@stefanv - threw this together on the train. I'm not sure what's going on with the red channel - looks like the image itself is being modified which is unexpected.

HTH

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment