Skip to content

Instantly share code, notes, and snippets.

@soply
Last active July 7, 2021 21:17
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 soply/94799abf53a533cd5dad65bb2652e2a0 to your computer and use it in GitHub Desktop.
Save soply/94799abf53a533cd5dad65bb2652e2a0 to your computer and use it in GitHub Desktop.
Simple utilities for creating an image manifold from a base image by rotations around certain degrees. Can be easily extended to other create image manifolds from other types of transformations
import numpy as np
from skimage import transform
class TestImage(object):
"""
Handler class for generating test images from different source types
such as from the skimage built-in images or from academic examples defined
by some 2D function (evaluation = pixel values).
"""
def __init__(self, image_str, sourcetype):
""" Constructor for the test image handler. Parameters:
-image_str: Parameter defines the image that is loaded. Concrete meaning
depends on the source type:
filename if sourcetype folder (e.g. "cameraman"),
suffix if sourcetype academic (e.g. "1"),
name if sourcetype skimage (e.g. "astronaut").
-sourcetype: States the source of which we want to use an image. Can be:
skimage: Use skimage built-in example images.
academic: Define a function in this class with not used suffix
and use this as the image.
folder: Load image from the TestImages folder.
"""
self.image_str = image_str
self.sourcetype = sourcetype
self.resized_img = None
self.cached = False
def generate(self, xv, yv):
""" Generates the image on the given meshgrid.
-xv: Numpy 2D array resulting from meshgrid operation.
-yv: Numpy 2D array resulting from meshgrid operation.
"""
# If we have already created an image, we assume that we need to
# generate the same and just return the cached image.
if self.cached == True:
return self.resized_img
# Creation dependent on type of the image
if self.sourcetype == "academic":
image = eval("self._academic_" + str(self.image_str) + "(xv, yv)")
self.resized_img = image
self.cached = True
elif self.sourcetype == "skimage":
from skimage import data
caller = getattr(data, self.image_str)
image = caller()
resized_img = transform.resize(image, (len(xv[0]), len(yv[0])))
self.resized_img = resized_img
self.cached = True
else:
raise NotImplementedError("sourcetype must be 'folder', 'academic'" + \
" or 'skimage'.")
return self.resized_img
""" Some academic test examples below. """
def _academic_1(self, x, y):
fx = 0.25 + np.sin(2 * np.pi * x) + 0.5
return 0.5 * np.pi + np.arctan(1 * (y - fx))
def _academic_2(self, x, y):
def f(x,y):
distance = 0.25
if (x > distance and x < (1.0 - distance)) and (y > distance and \
y < (1.0 - distance)):
m = 1.0/(1.0 - 2.0 * distance)
return 1 + m * distance - m * x
else:
return x
image = np.zeros((len(x[0]), len(y[0])))
for i in range(len(x[0])):
for j in range(len(y[0])):
image[i,j] = f(x[0][i], y[j][0])
return image
def _academic_3(self, x, y):
def f(x,y):
radius = 0.5
mid_x = 0.4
mid_y = 0.0
if ((x-mid_x) ** 2) + ((y - mid_y) ** 2) < radius ** 2:
return radius ** 2 - ((x-mid_x) ** 2) - ((y - mid_y) ** 2)
else:
return 0
image = np.zeros((len(x[0]), len(y[0])))
for i in range(len(x[0])):
for j in range(len(y[0])):
image[i,j] = f(x[0][i], y[j][0])
return image
class ImageGenerator(object):
def __init__(self, image_function, pixelx = 32, pixely = 32):
""" Constructor of an image. image_function must be a function taking
two arguments and returning the scalar grayscale value of the image that
corresponds to given input coordinates of the function.
Example: image_function is
def image_function(x, y):
return x + y
"""
self._f = image_function
self.pixelx = pixelx
self.pixely = pixely
def generate(self, angle, noise_level = 0):
"""
Generate an image and apply a rotation by angle (0-360) degrees. Nonzero noise level
adds entrywise Gaussian white noise with standard deviation given by noise level.
Returns image as 1D reshaped numpy array.
"""
return self.to_vector(self.generate_image(angle, noise_level = noise_level))
def generate_image(self, angle, noise_level = 0):
"""
Generate an image and apply a rotation by angle (0-360) degrees. Nonzero noise level
adds entrywise Gaussian white noise with standard deviation given by noise level.
Returns image as 2D numpy array.
"""
image = self.__class__._rotate(self.basic_image(noise_level = noise_level), angle)
return image * 255.0 / np.max(np.max(image))
def basic_image(self, noise_level=0):
"""
Returns image as 2D numpy array. Adds entrywise Gaussian white noise
with standard deviation prescribed by noise level.
Returns image as 2D numpy array.
"""
x = np.linspace(-1, 1, self.pixelx)
y = np.linspace(-1, 1, self.pixely)
xv, yv = np.meshgrid(x, y)
noise = noise_level * np.random.standard_normal([len(x), len(y)])
return self._f(xv, yv) + noise
def to_vector(self, image):
""" Returns image reshaped as a vector of size pixelx * pixely. """
return np.reshape(image, self.pixelx * self.pixely)
def to_image(self, image_as_vector):
""" Returns image reshaped as the matrix of size pixelx x pixely. """
return np.reshape(image_as_vector, (self.pixelx, self.pixely))
@staticmethod
def _rotate(image, angle, noise_level = 0):
""" Returns image rotated by given angle as vector of size pixelx * pixely. """
return transform.rotate(image, angle, resize=False, mode="edge")
if __name__ == "__main__":
""" Example usage """
test = TestImage('camera', "skimage")
generator = ImageGenerator(test.generate, 64, 64)
import matplotlib.pyplot as plt
plt.imshow(generator.generate_image(90))
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment