Basic image manipulation with arrays in NumPy - Time & Space Complexity
When working with images as arrays, it is important to understand how the time to process them grows as the image size increases.
We want to know how the time to manipulate image pixels changes when the image gets bigger.
Analyze the time complexity of the following code snippet.
import numpy as np
height, width = 100, 100 # Define height and width for the image
# Create a sample image as a 2D array (grayscale)
image = np.random.randint(0, 256, size=(height, width), dtype=np.uint8)
# Invert the image colors
inverted_image = 255 - image
# Increase brightness by 50, clip max value to 255
bright_image = np.clip(image + 50, 0, 255)
# Create a mask for pixels above 200
mask = image > 200
# Set those pixels to 255 (white)
image[mask] = 255
This code creates a grayscale image as a 2D array and performs simple pixel-wise operations like inversion, brightness increase, and masking.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Pixel-wise arithmetic and comparisons over the entire image array.
- How many times: Once for each pixel in the image (height x width times).
As the image size grows, the number of pixels to process grows too, so the time grows proportionally.
| Input Size (pixels) | Approx. Operations |
|---|---|
| 10 x 10 = 100 | About 100 pixel operations |
| 100 x 100 = 10,000 | About 10,000 pixel operations |
| 1000 x 1000 = 1,000,000 | About 1,000,000 pixel operations |
Pattern observation: The operations increase directly with the number of pixels, so doubling width and height quadruples the work.
Time Complexity: O(n)
This means the time to manipulate the image grows linearly with the total number of pixels.
[X] Wrong: "The operations only depend on width or height, not both."
[OK] Correct: Each pixel is identified by both row and column, so total pixels are width x height, not just one dimension.
Understanding how image size affects processing time helps you explain efficiency in real tasks like photo editing or computer vision.
"What if we changed the image from grayscale (2D array) to color (3D array with RGB channels)? How would the time complexity change?"
Practice
Solution
Step 1: Understand image representation
A grayscale image is made of pixels arranged in rows and columns, each pixel having a brightness value.Step 2: Connect to numpy array structure
A 2D numpy array stores these brightness values in a grid matching the image layout.Final Answer:
Pixel brightness values arranged in rows and columns -> Option AQuick Check:
Grayscale image = 2D pixel brightness array [OK]
- Confusing pixel values with file names
- Thinking 2D arrays store color channels
- Mixing image size with pixel data
img vertically?Solution
Step 1: Understand vertical flip axis
Vertical flip reverses rows, which corresponds to axis 0 in numpy arrays.Step 2: Match numpy functions to axis
np.flip(img, axis=0) flips vertically.Final Answer:
np.flip(img, axis=0) -> Option CQuick Check:
Vertical flip = axis 0 flip [OK]
- Using axis=1 flips horizontally
- np.flip(img) without axis reverses all axes
- Forgetting axis parameter in np.flip
import numpy as np img = np.array([[10, 20], [30, 40]]) new_img = img + 5 print(new_img)
What is the output?
Solution
Step 1: Understand numpy array addition
Adding 5 to a numpy array adds 5 to every element (broadcasting).Step 2: Calculate new array values
Each element increases by 5: 10+5=15, 20+5=25, 30+5=35, 40+5=45.Final Answer:
[[15 25] [35 45]] -> Option DQuick Check:
Array + 5 adds 5 to all elements [OK]
- Thinking addition changes shape
- Adding 5 only to first row or column
- Confusing addition with multiplication
img?:cropped = img[0:2, 0:3]
Solution
Step 1: Analyze slicing indices
The slice img[0:2, 0:3] selects rows 0 and 1 (2 rows) and columns 0,1,2 (3 columns).Step 2: Compare to desired crop size
We want a 2x2 crop, but this selects 2x3, so it includes one extra column.Final Answer:
It crops 2 rows but 3 columns, not 2 columns -> Option AQuick Check:
Slicing columns 0:3 selects 3 columns [OK]
- Assuming slicing is exclusive of end index
- Expecting error from out-of-range slice
- Confusing rows and columns order
img with shape (100, 100, 3). How do you create a new image gray_img by averaging the color channels for each pixel?Solution
Step 1: Understand image shape and channels
The shape (100, 100, 3) means 100x100 pixels with 3 color channels (RGB) along axis 2.Step 2: Average color channels per pixel
Using img.mean(axis=2) calculates the average of the 3 channels for each pixel, producing a 2D grayscale image.Final Answer:
gray_img = img.mean(axis=2) -> Option BQuick Check:
Mean over axis 2 averages color channels [OK]
- Summing over wrong axis
- Selecting only one color channel
- Using flip instead of averaging
Ready to prove it?
Pass the test and this pattern moves unknown
