Wednesday, October 14th, 2026¶
Last week, we started to look at multi-dimensional numpy arrays.
import matplotlib.pyplot as plt
import numpy as np
np.ones((10,6))
array([[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.]])
Visualizing 2-dimensional arrays¶
Consider the following 2D-array, filled with integers 0 up to 99.
A = np.arange(100).reshape(10,10)
print(A)
[[ 0 1 2 3 4 5 6 7 8 9] [10 11 12 13 14 15 16 17 18 19] [20 21 22 23 24 25 26 27 28 29] [30 31 32 33 34 35 36 37 38 39] [40 41 42 43 44 45 46 47 48 49] [50 51 52 53 54 55 56 57 58 59] [60 61 62 63 64 65 66 67 68 69] [70 71 72 73 74 75 76 77 78 79] [80 81 82 83 84 85 86 87 88 89] [90 91 92 93 94 95 96 97 98 99]]
For this array, it is small enough that we can simply print the array to understand its contents. For other larger arrays, this becomes infeasable. The plt.imshow function is a very useful tool for visualizing 2D arrays of any size. The basic syntax is plt.imshow(<some 2D array>).
plt.imshow(A)
<matplotlib.image.AxesImage at 0x29d4a891160>
When calling plt.imshow on a 2D array, the graph places a colored block at each row & column index pair. The color of the block is determined by the value of the array in that row & column position. The colors are assigned according to a designated colormap.
The colors are assigned so that the lowest value in the array is assigned the "lowest" color in the colormap (dark blue by default) and the highest value of the array is assigned the "highest" color in the colormap (yellow by default). Intermdiate values are assigned intermediate colors between the "lowest" and "highest" colors in the colormap.
Let's make some changes to the A array and see how the output of plt.imshow is affected. For example, suppose we want to set the values in rows 3 or 4 and columns 6 or 7 to be 120.
my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
print(my_list[3:4+1])
['d', 'e']
A[3:5, 6:8]
array([[36, 37],
[46, 47]])
A[3:5, 6:8] = 120
print(A)
[[ 0 1 2 3 4 5 6 7 8 9] [ 10 11 12 13 14 15 16 17 18 19] [ 20 21 22 23 24 25 26 27 28 29] [ 30 31 32 33 34 35 120 120 38 39] [ 40 41 42 43 44 45 120 120 48 49] [ 50 51 52 53 54 55 56 57 58 59] [ 60 61 62 63 64 65 66 67 68 69] [ 70 71 72 73 74 75 76 77 78 79] [ 80 81 82 83 84 85 86 87 88 89] [ 90 91 92 93 94 95 96 97 98 99]]
plt.imshow(A)
<matplotlib.image.AxesImage at 0x29d4c100a50>
Note: Just like the plt.plot function, we can take manual control of the figure and axes generation using plt.figure and plt.subplot. We can use plt.imshow within a subplot in the same way that we use plt.plot. There are also many optional arguments that can be included to modify the default behavior of plt.imshow. For example:
- We can supply a value
vminthat the "darkest" color will be assigned to. Any values in the array that are below this minimum value will also be mapped to the "darkest" color. - We can supply a value
vmaxthat the "brightest" color will be assigned to. Any values in the array that are above this maximum value will also be mapped to the "brightest" color.
plt.imshow(A, vmax=99)
<matplotlib.image.AxesImage at 0x29d4c1665d0>
plt.imshow(A, vmin=20, vmax=99)
<matplotlib.image.AxesImage at 0x29d4c1c3750>
By default, plt.imshow will not interpolate colors between neighboring array positions (unless your screen's resolution is too low to display all of the colored blocks). That is, we can see a discrete set of boxes of colors. We can modify this behavior by using the interpolation keyword. Some available interpolation methods include:
'nearest': each pixel is colored according to the closest colored block to that pixel'bilinear': each pixel is colored according to a bilinear interpolation (both horizontally and vertically) between nearby colored blocks'bicubic': each pixel is colored according to a bicubic interpolation (both horizontally and vertically) between nearby colored blocks'lanczos': each pixel is colored according to Lancsoz interpolation (both horizontally and vertically) between nearby colored blocks
plt.imshow(A, vmin=20, vmax=99, interpolation='bilinear')
<matplotlib.image.AxesImage at 0x29d4c2bd450>
plt.imshow(A, vmin=20, vmax=99, interpolation='lanczos')
<matplotlib.image.AxesImage at 0x29d4c373250>
We can also modify the color choices used by plt.imshow. These choices are called colormaps. A collection of colormaps can be found on the Matplotlib documentation page.
The cmap keyword argument can be used to change colormaps:
plt.imshow(A, vmin=20, vmax=99, interpolation='bicubic', cmap='plasma')
<matplotlib.image.AxesImage at 0x29d4a99d090>
Note: The figures produced above do not indicate what the actual values in the array are. We can call plt.colorbar to add a colorbar that indicates which values correspond to which colors.
plt.imshow(A, vmin=20, vmax=99, interpolation='bicubic', cmap='plasma')
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x29d4a891550>
We can also use colormaps in plt.plot to assign colors to our plots. The colormaps can be found in the cm submodule of matplotlib.
import matplotlib.cm as cm
#help(cm)
cm.plasma
Each colormap works as a function that takes in a float, where:
- any input
0or less returns the color at the left-end of the colormap, - any input
1or more returns the color at the right-end of the colormap, - any input between
0and1returns the color that is proportionally between the left-end and right-end of the colormap.
cm.viridis
cm.inferno
cm.rainbow
What does the output actually look like when we plug a float into a colormap?
print(cm.plasma(0))
(np.float64(0.050383), np.float64(0.029803), np.float64(0.527975), np.float64(1.0))
print(cm.rainbow(255))
(np.float64(1.0), np.float64(1.2246467991473532e-16), np.float64(6.123233995736766e-17), np.float64(1.0))
RGB(A) values¶
The output from the colormap above is an Red/Green/Blue/Alpha value, or RGBA value. That is, we have a tuple (R, G, B, A) where:
Ris the amount of red in the color (R=1means full red,R=0means no red),Gis the amount of green in the color (G=1means full green,G=0means no green),Bis the amount of blue in the color (B=1means full blue,B=0means no blue),Ais the transparency of the color (A=1means fully opaque,A=0means fully transparent).
If the transparency channel is omitted (i.e. if we work with a pure RGB triple), the color is assume to be fully opaque. We can also supply our own RGB(A) tuples in plt.plot to specify colors.
t = np.linspace(0,1,1000)
y1 = t**2
y2 = t**2 + 1
y3 = t**2 + 2
plt.plot(t,y1, color=(.3, .7, .4))
plt.plot(t,y2, color=(0, .6, .8))
plt.plot(t,y3, color=(1, .2, .4))
[<matplotlib.lines.Line2D at 0x29d4c652c10>]
The plt.imshow function can also work with RGB(A) values. Instead of supplying a 2D-array, we can supply a 3D-array where:
- The first axis corresponds to the row of the array,
- The second axis corresponds to the column of the array,
- The third axis corresponds to the RGB(A) values of the array.
For example, let's define a 10 by 20 array with 3 color channels (RGB) called RGB_array.
RGB_array = np.zeros((10,20,3))
RGB_array[4, 6] # Get the element in row 4, column 6
array([0., 0., 0.])
RGB_array[8, 1]
array([0., 0., 0.])
plt.imshow(RGB_array)
<matplotlib.image.AxesImage at 0x29d4c6cd090>
For the above array, we will think of RGB_array[:,:,0] as a $2D$-array containing the red data. Similarly, RGB_array[:,:,1] contains the green data, and RGB_array[:,:,2] contains the blue data. Let's add some colored stripes to the array.
Note: We can take slices through the rows/columns of an (m,n,3) array of RGB values. For example, RGB_array[:4, 3:7] will give a (4,4,3) array consisting of the RGB triples in rows 0, 1, 2, 3 and columns 3, 4, 5, 6. If we set RGB_array[:4, 3:7] = (.1, .7, .9), then every RGB triple in these rows/columns will be set to (.1, .7, .9). This is called broadcasting, and is a very useful feature of NumPy.
RGB_array[:4, 3:7].shape
(4, 4, 3)
RGB_array[:4, 3:7] = (.1, .7, .9)
plt.imshow(RGB_array)
<matplotlib.image.AxesImage at 0x29d4c72f610>
RGB_array[:4, 3:7] = (.1, .7, .9)
RGB_array[7:10, -4:] = (1, .7, .7)
RGB_array[4:7, :] = (0, 1, 1)
RGB_array[:, 10:15] = (1, 0, 1)
RGB_array[7:,5:10] = (1, 1, 0)
plt.imshow(RGB_array)
<matplotlib.image.AxesImage at 0x29d4da80cd0>
Most computer images are stored as arrays of RGB(A) values. We can read an image file into an RGB(A) array using plt.imread. The syntax is: plt.imread(<path to some image file>). For example, download the image mario.png from the course webpage and place it into the same folder as this Jupyter notebook.
mario = plt.imread('mario.png')
plt.imshow(mario)
<matplotlib.image.AxesImage at 0x29d4fb3fed0>
mario.shape
(224, 256, 4)
print(mario[0, 0])
[0.36078432 0.5803922 0.9882353 1. ]
We can look at the shape of the array to see if it contains RGB or RGBA values. In this case, the mario.png image file includes a transparency channel.
mario.shape
(224, 256, 4)
Exercise: Use NumPy slicing to remove the transparency channel from the mario array.
my_list = [1,2,3,4,5]
my_list[:4]
[1, 2, 3, 4]
my_list[:-1]
[1, 2, 3, 4]
mario[:, :, :3].shape
(224, 256, 3)
mario = mario[:,:,:3]
mario.shape
(224, 256, 3)
Exercise: Use NumPy slicing and plt.imshow to zoom in on Mario (in the lower-left corner).
mario[180:210, 35:65].shape
(30, 30, 3)
plt.imshow(mario[180:210, 35:65])
<matplotlib.image.AxesImage at 0x29d4f9c20d0>
Exercise: Create an array blueless_mario where the blue channel information from mario has been removed (i.e. set to 0) and plot using plt.imshow.
blueless_mario = mario.copy() # Create a copy so that we don't modify the original array
blueless_mario[:,:,2] = 0
plt.imshow(blueless_mario)
<matplotlib.image.AxesImage at 0x29d4fe97ed0>
Exercise: Create an array mixed_mario where:
- the red channel of
mixed_mariomatches the green channel ofmario, - the green channel of
mixed_mariomatches the blue channel ofmario, - the blue channel of
mixed_mariomatches the red channel ofmario.
mixed_mario = mario.copy()
mixed_mario[:,:,0] = mario[:,:,1] # Set red channel of mixed array to green channel of original
mixed_mario[:,:,1] = mario[:,:,2] # Set green channel of mixed array to blue channel of original
mixed_mario[:,:,2] = mario[:,:,0] # Set blue channel of mixed array to red channel of original
plt.imshow(mixed_mario)
<matplotlib.image.AxesImage at 0x29d4ff27390>
Note: For the next project, we will be working with integer-valued RGB triples. The integer-values will range from 0 to 255. An integer 0 means no color while an integer 255 means full color (equivalent to a float of 1).
Exercise: Convert the mario array to an integer-type array mario_RGB_int containing RGB triples with values between 0 and 255.
mario[0,0]
array([0.36078432, 0.5803922 , 0.9882353 ], dtype=float32)
mario_RGB_int = (mario*255).astype(int)
plt.imshow(mario_RGB_int)
<matplotlib.image.AxesImage at 0x29d511dd090>
Exercise: Convert the mario_RGB_int array into a float-type array containing RGB triples with values between 0 and 1.
mario_RGB_float = mario_RGB_int / 255
plt.imshow(mario_RGB_float)
<matplotlib.image.AxesImage at 0x29d5125c550>