{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "\"Open\n", "\n", "| - | - |\n", "|-----------------------------------------------------------------|-----------------------------------------------------------------|\n", "| [Exercise 11 (to grayscale)](<#Exercise-11-(to-grayscale)>) | [Exercise 12 (radial fade)](<#Exercise-12-(radial-fade)>) |\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Image processing\n", "\n", "An image is a collection of *pixels*, which is abbreviation for picture elements.\n", "A grayscale image can be represented as as two dimensional array, whose first axis corresponds to the x coordinate of the image and the second axis corresponds to the y coordinate. The array contains at each coordinate pair (x,y) a value, which is typically a float between 0.0 and 1.0, or an integer between 0 and 255. This specifies the level of grayness. For example, if the array contains value 255 at coordinates (0,0), then in the image the pixel at top left is white.\n", "\n", "In color images there is third axis is for the red, green, and blue components of each pixel. For each of these color components there is a value between 0.1 and 1.0 (or between 0 and 255). The combinations of different values for the three components red, green, and blue can result in at least 16.7 million colors.\n", "\n", "Since images can be represented as multidimensional arrays, we can easily process images using NumPy functions. Let's see examples of these." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "painting=plt.imread(\"painting.png\")\n", "print(painting.shape)\n", "print(f\"The image consists of {painting.shape[0] * painting.shape[1]} pixels\")\n", "plt.imshow(painting);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Because the image is now a NumPy array, we can easily perform some operations:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.imshow(painting[:,::-1]); # mirror the image in x direction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the following we set the pixels on the first 30 rows white:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "painting2 = painting.copy() # don't mess the original painting!\n", "painting2[0:30, :, :] = 1.0 # max value for all three components produces white\n", "plt.imshow(painting2);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For a bit more complicated operation we can create a function that returns a copy of the image so that it fades to black as we move to left." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def fadex(image):\n", " height, width = image.shape[:2]\n", " m=np.linspace(0,1, width).reshape(1,width,1)\n", " result = image*m # note that we rely on broadcasting here\n", " return result" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "modified=fadex(painting)\n", "print(modified.shape)\n", "plt.imshow(modified);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "####
Exercise 11 (to grayscale)
\n", "\n", "This exercise can give two points at maximum!\n", "\n", "Part 1.\n", "\n", "Write a function `to_grayscale` that takes an RGB image (three dimensional array) and returns a two dimensional gray-scale image. The conversion to gray-scale should take a weighted sum of the red, green, and blue values, and use that as the value of gray. The first axis is the x, the second is y, and the third is the color components (red, green, blue).\n", "Use the weights 0.2126, 0.7152, and 0.0722 for red, green, and blue, respectively. These weights are so because the human eye is most sensitive to green color and least sensitive to blue color.\n", "\n", "In the main function you can, for example, use the provided image `src/painting.png`. Display the grayscale image with the `plt.imshow` function. You may have to call the function `plt.gray` to set the color palette (colormap) to gray.\n", "(See `help(plt.colormaps)` for more information about colormaps.)\n", "\n", "Part 2.\n", "\n", "Write functions `to_red`, `to_green`, and `to_blue` that get a three dimensional array as a parameter and return a three dimensional arrays. For instance, the function `to_red` should zero out the green and blue color components and return the result. In the `main` function create a figure with three subfigures: the top one should be the red image, the middle one the green image, and the bottom one the blue image.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "####
Exercise 12 (radial fade)
\n", "\n", "Make program that does fading of an image as earlier, except now not in horizontal direction but in radial direction. As we move away from the centre of the image, the pixels fade to black.\n", "\n", "Part1.\n", "\n", "Write function `center` that returns coordinate pair (center_y, center_x) of the image center. Note that these coordinates might not be integers. Example of usage:\n", "```python\n", "print(center(np.zeros((10, 11, 3))))\n", "(4.5, 5)\n", "```\n", "The function should work both for two and three dimensional images, that is grayscale and color images.\n", "\n", "Write also function `radial_distance` that returns for image with width `w` and height `h` an array with shape (h,w), where the number at index (i,j) gives the euclidean distance from the point (i,j) to the center of the image.\n", "\n", "Part 2.\n", "\n", "Create function `scale(a, tmin=0.0, tmax=1.0)` that returns a copy of the array `a` with its elements scaled to be in the range `[tmin,tmax]`.\n", "\n", "Using the functions `radial_distance` and `scale` write function `radial_mask` that takes an image as a parameter and returns an array with same height and width filled with values between 0.0 and 1.0. Do this using the `scale` function. To make the resulting array values near the center of array to be close to 1 and closer to the edges of the array are values closer to be 0, subtract the previous array from 1.\n", "\n", "Write also function `radial_fade` that returns the image multiplied by its radial mask.\n", "\n", "Test your functions in the `main` function, which should create, using matplotlib, a figure that has three subfigures stacked vertically. On top the original `painting.png`, in the middle the mask, and on the bottom the faded image.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Finding clusters in an image\n", "\n", "Let's first generate some data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "n=5\n", "l=256\n", "im = np.zeros((l,l))\n", "np.random.seed(0)\n", "points = np.random.randint(0, l, (2, n**2)) # sample n*n pixels from the array im\n", "im[points[0], points[1]] = 1\n", "plt.imshow(im);" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from scipy import ndimage\n", "im2 = ndimage.gaussian_filter(im, sigma=l/(8.*n)) # blur the image a bit\n", "plt.imshow(im2);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's try to find clusters from the above image:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mask = im2 > im2.mean() # mask those pixels whose intensity is above mean\n", "label_im, nb_labels = ndimage.label(mask) # connected components form clusters\n", "print(f\"Number of clusters is {nb_labels}\")\n", "plt.imshow(label_im);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Although this method we used was very simple, it could still be used for example to automatically count number of birds or stars in an image. Of course, humans can do this easily, but when there are hundreds or thousands of images, then it is better to use machines to do this mechanical work." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is large number of applications of image processing of which we list only a few here:\n", "\n", "* denoising\n", "* deblurring\n", "* image segmentation\n", "* feature extraction\n", "* zooming, rotating\n", "* filtering" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Additional libraries" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The are several libraries written in Python that allow easy processing of images. Few examples of these:\n", "\n", "* [pillow](https://python-pillow.org/)\n", "* [scikit-image](https://scikit-image.org/)\n", "* In Scipy there is the subpackage [ndimage](https://docs.scipy.org/doc/scipy/reference/tutorial/ndimage.html) that also contains routines for processing images" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "\"Open\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.8" }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }