Last active
July 7, 2021 21:17
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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