Skip to content

Instantly share code, notes, and snippets.

@pierre-haessig
Created October 4, 2012 15:51
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 pierre-haessig/3834536 to your computer and use it in GitHub Desktop.
Save pierre-haessig/3834536 to your computer and use it in GitHub Desktop.
Shake an image to get kind of XKCD-style lines
#!/usr/bin/python
# -*- coding: UTF-8 -*-
""" Shake an image
in relation to the discussion about xkcd-style graphs on matplotlib-users ML
ref: http://mathematica.stackexchange.com/questions/11350/xkcd-style-graphs
Pierre Haessig — October 2012
"""
from os.path import splitext
import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import imread, imsave
from scipy.ndimage.interpolation import map_coordinates
from scipy.ndimage.filters import gaussian_filter
### Read the input image
img_name = 'grid_image.png'
print('Reading "%s"...' % img_name)
img = imread(img_name)
N,P = img.shape[0:2]
print('image shape: %dx%d px' % (P,N))
# 1) Create the indexing grid coordinates:
x,y = np.mgrid[0:N,0:P]
# 1a) Create a displacement noise:
x_noise = np.random.randn(N,P)
y_noise = np.random.randn(N,P)
# 1b) Smooth the noise
radius = 3 # in [px]
x_noise = gaussian_filter(x_noise, radius)
y_noise = gaussian_filter(y_noise, radius)
# 1c) normalize the standard deviation
noise_std = (x_noise.std() + y_noise.std())/2
x_noise /= noise_std
y_noise /= noise_std
# 1d) Add the noise to create a shaken grid
scale = .5 # in [px]
x = x + x_noise * scale
y = y + y_noise * scale
# 2) Resample the image on the new shaken grid, channel per channel
coords = np.array([x,y])
imgR = map_coordinates(img[:,:,0], coords, cval=255)
imgG = map_coordinates(img[:,:,1], coords, cval=255)
imgB = map_coordinates(img[:,:,2], coords, cval=255)
# note: is there a way to process all channels at once?
# 3) Reconstruct the image:
img2 = np.array([imgR, imgG, imgB])
img2 = np.rollaxis(img2, 0, 3)
## Plot before and after images
#fig, (ax1, ax2) = plt.subplots(2,1)
#ax1.imshow(img, interpolation='nearest')
#ax2.imshow(img2, interpolation='nearest')
#plt.show()
### Save the output image ###
out_name = splitext(img_name)[0] + '-shaken' + splitext(img_name)[1]
print('saving the shaken image in "%s"' % out_name)
imsave(out_name, img2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment