Welcome to the course! Over the next four units, we will build a complete panorama stitcher from scratch using Python. We will learn how to take multiple overlapping photos and blend them into one seamless wide-angle image.
Before we can perform any complex math or image stitching, our first step is to build a reliable workbench tool. We need a way to load an image, inspect its properties, and view it on our screen. This basic setup provides a dependable way to check our inputs before we run any advanced algorithms.
As a sneak peek, you will be able to take multiple images like these:
And recreate a big image looking like this:

To do this, we will use OpenCV (imported as cv2), which is one of the most popular and powerful computer vision libraries in the world. While you will need to learn how to install OpenCV on your own personal computer, you do not need to worry about that right now. In the CodeSignal environment, OpenCV and all other necessary tools come pre-installed and ready to use!
Also, you will have a small Image Gallery to help you debug your work along the exercises!
Before we dive deeper into the code, it is important to understand what a digital image actually is. To our eyes, it’s a photograph, but to a computer, it is a three-dimensional grid of numbers, also known as a multidimensional array.
- Pixels: The grid is made up of individual dots called pixels. Every pixel in the image contains numerical data that tells the computer what color to display.
- Spatial Dimensions: The first two dimensions of this grid represent the height and width of the image (the number of pixels stacked vertically and horizontally).
- Channels: The third dimension represents color channels.
In digital imaging, colors are created by mixing primary colors of light. Most images use the RGB color model, which consists of three channels: Red, Green, and Blue.
Think of these channels as three separate grayscale layers. When you stack them on top of each other, they blend to create a full-color image. Each pixel in a standard 8-bit image has a value for each channel ranging from 0 (no intensity) to 255 (full intensity). For example:
- A pixel with values
(255, 0, 0)in RGB is pure Red. - A pixel with
(0, 0, 0)is Black (all lights off). - A pixel with
(255, 255, 255)is White (all colors at maximum intensity).

The OpenCV Difference: While the world usually uses RGB, OpenCV reads images in BGR (Blue-Green-Red) order. This means the first layer of data is Blue, the second is Green, and the third is Red. We must keep this in mind whenever we manipulate individual color values!
Let's start by setting up a way to tell our Python script which image we want to load. We can use Python's built-in argparse library to read command-line arguments. This allows us to pass a file path and other options directly into our program.
In this code, we expect the user to provide a path to the image. We also set up optional arguments for saving an output file (--out) and setting a maximum window size for our screen (--preview-size).
Next, we need to load the image into our program. We do this using cv2.imread().
Here, cv2.imread() attempts to read the file. If the file path is incorrect or the file is corrupted, OpenCV will not crash immediately; instead, it simply returns None. Therefore, it is very important to include a safety check. If the image is None, we stop the program and print a helpful error message so that we know exactly what went wrong.
To a computer, an image is not a picture; it is simply a massive grid of numbers known as an array. Let's add some code to inspect the mathematical properties of our newly loaded image.
Let's break down what these properties tell us:
shape: This tells us the dimensions of theimage. For a color image, it returns three numbers:height,width, andcolor channels.dtype: This is the data type. Typically, it isuint8, which stands for an 8-bit unsigned integer.minandmax: These are the lowest and highest pixel values in theimagegrid. Because we are using8-bit integers, the lowest possible value is0(pure black) and the highest is255(pure white or full color).
If you were to run this code on a standard photo, you would see output that looks something like this:
Note the warning we printed at the end! By default, almost all computer graphics use Red-Green-Blue (RGB) order for colors. However, OpenCV has a famous quirk: it loads colors in Blue-Green-Red (BGR) order. It is very helpful to print this reminder so that we do not forget it later.
If you look at the sample output above, the image has a height of 4000 pixels and a width of 6000 pixels. Modern photos are huge! If we try to show this image on a standard computer monitor pixel-for-pixel, it will be much larger than the screen.
To fix this, we will write a custom helper function to shrink the image specifically for our preview window.
Let's explain the math behind this step by step:
- First, we examine the
imageshapeto get theheightandwidth. - Next, we determine which side is the longest using
max(height, width). - We divide our target
max_size(which defaults to900pixels) by that longest edge to find ourscalepercentage. For example, if theimageis1800pixels wide,900 / 1800gives us ascaleof0.5(or 50%). - We use
min(1.0, ...)to ensure that if theimageis already smaller than900pixels, ourscaleremains at1.0. We do not want to stretch small images. - Finally, we use
cv2.resize()to shrink theimageto its new dimensions.
It is crucial to note that this resizing is strictly for our display screen. We want to keep the original, high-quality image array untouched for our actual stitching work later.
Now that we have our original image loaded and a handy resize_long_edge function ready, let's complete our main() function by displaying the image to the user.
Here is what these final few lines do:
- First, we check if the user provided an
--outargument. If they did, we usecv2.imwrite()to save a copy of the full-resolutionimageto their computer. - Next, we use
cv2.imshow(). This command usually creates a pop-up window named "preview" and displays the result of ourresize_long_edgefunction, but in the CodeSignal environment it will be displayed on the Image Gallery. - Crucial Step: We must call
cv2.waitKey(0). This tellsPythonto pause the program indefinitely (where0signifies forever) until the user presses a key on their keyboard. In our case, a button will appear on the Image Gallery to let the program continue. If we forget this line, the window will appear and disappear in a fraction of a second before we can even see it! - Finally, once the user presses a key,
cv2.destroyAllWindows()safely closes the preview window and cleans up the program. In our CodeSignal IDE this will destroy all images inside the Image Gallery.
Excellent work! We have successfully built the foundation for our workbench. We learned how to use command-line arguments to pass in a file path, and we used cv2.imread() to read the image into our program. We explored how to inspect the mathematical properties of the image array, such as its shape and data type. Finally, we created a custom mathematical helper function to resize the image, and we used cv2.imshow() and cv2.waitKey(0) to safely display it on our screen.
You are now ready to put these concepts to work. In the upcoming interactive exercises, you will practice writing these loading, inspecting, and display functions yourself. Becoming comfortable with these basic OpenCV tools now will make it much easier when we move on to the complex math and stitching algorithms in the next lessons!
