"In this lesson, we'll learn about ways to represent and manipulate images in Python. By the end of this lesson, students will be able to:\n",
"\n",
"- Apply `ndarray` arithmetic and logical operators with numbers and other arrays.\n",
"- Analyze the shape of an `ndarray` and index into a multidimensional array.\n",
"- Apply arithmetic operators, indexing, and slicing to manipulate RGB images.\n",
"\n",
"We'll need two new modules: `imageio`, which provides utilities to read and write images in Python, and `numpy`, which provides the data structures for representing images in Python."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2126b85c-d53a-463d-8823-cc08bf0c5ebd",
"metadata": {},
"outputs": [],
"source": [
"import imageio.v3 as iio\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import pandas as pd"
]
},
{
"cell_type": "markdown",
"id": "fd855599-8f12-4f1d-94a2-59e9f97a0b08",
"metadata": {},
"source": [
"## Reading an image\n",
"\n",
"Let's use `imread` to load a color picture of Dubs II in grayscale with `mode=\"L\"` standing for \"luminance\" or \"lightness\". To show an image, we can plot its pixels using the matplotlib function `imshow`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f6d6301b-0443-4194-a2d1-7c7becc65500",
"metadata": {},
"outputs": [],
"source": [
"dubs = iio.imread(\"dubs.jpg\", mode=\"L\")\n",
"plt.imshow(dubs, cmap=\"gray\")"
]
},
{
"cell_type": "markdown",
"id": "f42ccbb4-e401-43ab-b0ec-c428659c6c98",
"metadata": {},
"source": [
"Pandas uses NumPy to represent a `Series` of values, so many element-wise operations should seem familiar. In fact, we can load an image into a Pandas `DataFrame` and see that this grayscale image is really a 2-d array of color values ranging from [0, 255]."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3c5f2678-3382-4f9c-8a49-85d29a85de92",
"metadata": {},
"outputs": [],
"source": [
"pd.DataFrame(dubs)"
]
},
{
"cell_type": "markdown",
"id": "b80d867b-4d5a-47d7-9e61-2946fec715b1",
"metadata": {},
"source": [
"What would a color image of Dubs II look like instead? Let's try loading the picture without `mode=\"L\"` to maintain its color data."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6ecec20b-31cb-4b2b-86b6-b1a6df48146e",
"metadata": {},
"outputs": [],
"source": [
"dubs = iio.imread(\"dubs.jpg\")\n",
"plt.imshow(dubs)"
]
},
{
"cell_type": "markdown",
"id": "1683c1d1-3421-48c1-a85d-917727ba0800",
"metadata": {},
"source": [
"What do you think the colorful `DataFrame` should look like?"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1013f3f8-c2f7-440f-97b1-9a0073e4851c",
"metadata": {},
"outputs": [],
"source": [
"pd.DataFrame(dubs)"
]
},
{
"cell_type": "markdown",
"id": "58d9c94a-547c-4d14-9120-1b75d123d02f",
"metadata": {},
"source": [
"## Array manipulation\n",
"\n",
"Images are represented in Python with the type `numpy.ndarray` or \"n-dimensional array.\" Grayscale images are 2-dimensional arrays with pixel luminance values indicated in each position. Color images are 3-dimensional arrays with pixel color values indicated for each channel (red, green, blue) in each position. Can you set the left and right sides of this picture to `0` so that Dubs II appears surrounded by black borders?"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "27a95b41-907b-4c1b-aed2-2b04e12b277f",
"metadata": {},
"outputs": [],
"source": [
"dubs = iio.imread(\"dubs.jpg\")\n",
"dubs[:50, :25] = 0\n",
"plt.imshow(dubs)"
]
},
{
"cell_type": "markdown",
"id": "ea64ced6-0e76-47c8-9082-9da808088209",
"metadata": {},
"source": [
"When we're performing an assignment on 2-dimensions of a 3-dimensional image, NumPy follows [**broadcasting rules**](https://numpy.org/doc/stable/user/basics.broadcasting.html#general-broadcasting-rules) to evaluate the operation. The simplest version of broadcasting are just element-wise operations."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "34f56f8f-2472-4d49-9893-36699c8bd0ad",
"metadata": {},
"outputs": [],
"source": [
"plt.imshow(dubs)"
]
},
{
"cell_type": "markdown",
"id": "7b7fdd64-04a6-4af0-bc20-66fe908ccc13",
"metadata": {},
"source": [
"Let's try a more complicated example. Using the floor division operator, fill in the `imshow` call to decrease only the green channel so that the overall picture is much more purple than before."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c6e15361-17db-4a93-affd-4e2538c86ef6",
"metadata": {},
"outputs": [],
"source": [
"dubs = iio.imread(\"dubs.jpg\")\n",
"plt.imshow()"
]
},
{
"cell_type": "markdown",
"id": "3c80b302-c2b7-40e5-af41-18e9db04a5da",
"metadata": {},
"source": [
"## Practice: Instafade\n",
"\n",
"Write code to apply a fading filter to the image. The fading filter reduces all color values to 77% intensity and then adds 38.25 to each resulting color value. (These numbers are somewhat arbitrarily chosen to get the desired effect.)\n",
"\n",
"The provided code converts the `dog` array from integer values to floating-point decimal values. To display the final image, the code converts the numbers in the `dog` array back to `uint8` before passing the result to `imshow`."
"Write code to apply the following operations to an image.\n",
"\n",
"1. **Expand the red colors by 50%** by subtracting 128 from each red channel value, multiply the result by 1.5, and then add 128 to restore the original value range.\n",
"1. **Increase the blue colors by 13** by adding 13 to each blue channel value.\n",
"1. **Add black letterboxing bars** by setting the top 150 and bottom 150 pixels to black.\n",
"1. **Clip color values outside the range [0, 255]** by reassign all values above 255 to 255 and all values below 0 to 0."
In this lesson, we'll learn about ways to represent and manipulate images in Python. By the end of this lesson, students will be able to:
- Apply `ndarray` arithmetic and logical operators with numbers and other arrays.
- Analyze the shape of an `ndarray` and index into a multidimensional array.
- Apply arithmetic operators, indexing, and slicing to manipulate RGB images.
We'll need two new modules: `imageio`, which provides utilities to read and write images in Python, and `numpy`, which provides the data structures for representing images in Python.
Let's use `imread` to load a color picture of Dubs II in grayscale with `mode="L"` standing for "luminance" or "lightness". To show an image, we can plot its pixels using the matplotlib function `imshow`.
Pandas uses NumPy to represent a `Series` of values, so many element-wise operations should seem familiar. In fact, we can load an image into a Pandas `DataFrame` and see that this grayscale image is really a 2-d array of color values ranging from [0, 255].
Images are represented in Python with the type `numpy.ndarray` or "n-dimensional array." Grayscale images are 2-dimensional arrays with pixel luminance values indicated in each position. Color images are 3-dimensional arrays with pixel color values indicated for each channel (red, green, blue) in each position. Can you set the left and right sides of this picture to `0` so that Dubs II appears surrounded by black borders?
When we're performing an assignment on 2-dimensions of a 3-dimensional image, NumPy follows [**broadcasting rules**](https://numpy.org/doc/stable/user/basics.broadcasting.html#general-broadcasting-rules) to evaluate the operation. The simplest version of broadcasting are just element-wise operations.
Let's try a more complicated example. Using the floor division operator, fill in the `imshow` call to decrease only the green channel so that the overall picture is much more purple than before.
Write code to apply a fading filter to the image. The fading filter reduces all color values to 77% intensity and then adds 38.25 to each resulting color value. (These numbers are somewhat arbitrarily chosen to get the desired effect.)
The provided code converts the `dog` array from integer values to floating-point decimal values. To display the final image, the code converts the numbers in the `dog` array back to `uint8` before passing the result to `imshow`.
Write code to apply the following operations to an image.
1.**Expand the red colors by 50%** by subtracting 128 from each red channel value, multiply the result by 1.5, and then add 128 to restore the original value range.
1.**Increase the blue colors by 13** by adding 13 to each blue channel value.
1.**Add black letterboxing bars** by setting the top 150 and bottom 150 pixels to black.
1.**Clip color values outside the range [0, 255]** by reassign all values above 255 to 255 and all values below 0 to 0.