#!/usr/bin/env python3 import numpy as np import matplotlib.pyplot as plt def load_image(path): """Load the specified image as uint8 Numpy array. Args: path (str or file-like): The image file to read: a filename, or a file-like object opened in read-binary mode. (Copied from plt.imread's documentation) Returns: np.ndarray: A NumPy-Array of type ``uint8`` that contains the specified image. The returned array has shape (M, N, 3) for RGB images, and (M, N) for grayscale images. """ return np.uint8(plt.imread(path) * 255) def image2pixels(image): """Create a list of ``(R, G, B, X, Y)`` tuples from a given 3d image array. This function is the inverse to the function ``pixels2image``, i.e. ```pixels2image(image2pixels(image)) = image.``` Args: image (np.uint8-array): A NumPy-Array of type ``uint8`` and shape (M, N, 3). Returns: List[Tuple[np.uint8, np.uint8, np.uint8, int, int]]: A List containing all ``(R, G, B)``-values of the ``image`` together with the coordinates ``(X, Y)`` of the respective pixel. """ # TODO m, n, k = np.shape(image) result = [] for i in range(m): for j in range(n): result.append((image[i][j][0], image[i][j][1], image[i][j][2], j, i)) return result def pixels2image(pixels): """Create a 3d image array from a list of (R, G, B, X, Y) pixels. This function is the inverse to the function ``image2pixels``, i.e. ```image2pixels(pixels2image(pixels))) = pixels.``` Args: pixels (List[Tuple[np.uint8, np.uint8, np.uint8, int, int]]): A List containing the ``(R, G, B)``-values of pixels at the position ``(X, Y)``. Returns: np.uint8-array: A NumPy-Array of type ``uint8`` and shape (M, N, 3) representing the image given by ``pixels``. """ # TODO m, n = (0, 0) for t in pixels: if m < t[4]: m = t[4] if n < t[3]: n = t[3] image = np.zeros((m+1, n+1, 3)) for t in pixels: image[t[4]][t[3]][0] = t[0] image[t[4]][t[3]][1] = t[1] image[t[4]][t[3]][2] = t[2] return image def bounding_box(pixels): """Return a tuple ``((Rmin, Rmax), (Gmin, Gmax), (Bmin, Bmax))`` with the respective minimum and maximum values of each color. Args: pixels (List[Tuple[np.uint8, np.uint8, np.uint8, int, int]]): A List containing the ``(R, G, B)``-values of pixels at the position ``(X, Y)``. Returns: Tuple[Tuple[np.uint8, np.uint8], ...]: A tuple containing the respective minimum and maximum values of each color in the image represented by ``pixels``. """ # TODO Rmin = pixels[0][0] Rmax = pixels[0][0] Gmin = pixels[0][1] Gmax = pixels[0][1] Bmin = pixels[0][2] Bmax = pixels[0][2] for p in pixels: if Rmin > p[0]: Rmin = p[0] if Rmax < p[0]: Rmax = p[0] if Gmin > p[1]: Gmin = p[1] if Gmax < p[1]: Gmax = p[1] if Bmin > p[2]: Bmin = p[2] if Bmax < p[2]: Bmax = p[2] return ((Rmin, Rmax), (Gmin, Gmax), (Bmin, Bmax)) def color_average(pixels): """Return list of tuples (Ravg, Gavg, Bavg) with averaged color values. Args: pixels (List[Tuple[np.uint8, np.uint8, np.uint8, int, int]]): A List containing the ``(R, G, B)``-values of pixels at the position ``(X, Y)``. Returns: Tuple[int, int, int]: A tuple containing the average value of red, green, and blue color values in the image represented by ``pixels``. """ # TODO Ravg, Gavg, Bavg = (0, 0, 0) for p in pixels: Ravg += p[0] Gavg += p[1] Bavg += p[2] listLen = len(pixels) Ravg /= listLen Gavg /= listLen Bavg /= listLen return (np.uint8(round(Ravg, 0)), np.uint8(round(Gavg, 0)), np.uint8(round(Bavg, 0))) def main(): """ Main-Function. Is called if this module is executed at top level. Loads the image ``shibuya.png``, prints its bounding box as well as the color average, and then shows the image using matplotlib. """ shibuya = load_image('shibuya.png') pixels = image2pixels(shibuya) print(bounding_box(pixels)) print(color_average(pixels)) plt.imshow(pixels2image(pixels)) plt.show() if __name__ == "__main__": main()