Given a random-sampled selection of pixels from an image, scipy.interpolate.griddata
could be used to interpolate back to a representation of the original image. The code below does this, when fed the name of an image file on the command line.
# img_interp.py
import os
import sys
import numpy as np
from scipy.interpolate import griddata
import matplotlib.pyplot as plt
from PIL import Image
def make_interpolated_image(nsamples):
"""Make an interpolated image from a random selection of pixels.
Take nsamples random pixels from im and reconstruct the image using
scipy.interpolate.griddata.
"""
ix = np.random.randint(im.shape[1], size=nsamples)
iy = np.random.randint(im.shape[0], size=nsamples)
samples = im[iy,ix]
int_im = griddata((iy, ix), samples, (Y, X))
return int_im
# Read in image and convert to greyscale array object
img_name = sys.argv[1]
im = Image.open(img_name)
im = np.array(im.convert('L'))
# A meshgrid of pixel coordinates
nx, ny = im.shape[1], im.shape[0]
X, Y = np.meshgrid(np.arange(0, nx, 1), np.arange(0, ny, 1))
# Create a figure of nrows x ncols subplots, and orient it appropriately
# for the aspect ratio of the image.
nrows, ncols = 2, 2
fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(6,4), dpi=100)
if nx < ny:
w, h = fig.get_figwidth(), fig.get_figheight()
fig.set_figwidth(h), fig.set_figheight(w)
# Convert an integer i to coordinates in the ax array
get_indices = lambda i: (i // nrows, i % ncols)
# Sample 100, 1,000, 10,000 and 100,000 points and plot the interpolated
# images in the figure
for i in range(4):
nsamples = 10**(i+2)
axes = ax[get_indices(i)]
axes.imshow(make_interpolated_image(nsamples),
cmap=plt.get_cmap('Greys_r'))
axes.set_xticks([])
axes.set_yticks([])
axes.set_title('nsamples = {0:d}'.format(nsamples))
filestem = os.path.splitext(os.path.basename(img_name))[0]
plt.savefig('{0:s}_interp.png'.format(filestem), dpi=100)
Here are trial example images: mona-lisa.jpg, goat.jpg
Run the script as, for example:
python img_interp.py mona-lisa.jpg