Image Fundamentals
Introduction to digital images: color spaces, channel splitting, sampling and quantization.
Learning Objectives
- ✓Understand BGR, RGB, Grayscale and Binary color spaces
- ✓Split and visualize individual color channels
- ✓Apply sampling and quantization to control bit depth
Color Spaces
OpenCV reads images in BGR order (not RGB). You must convert to RGB before displaying with matplotlib. Grayscale reduces three channels to one luminance channel. Binary thresholds the grayscale image at a cutoff (e.g. 127) to produce pure black-and-white.
import cv2
import numpy as np
import matplotlib.pyplot as plt
Img = cv2.imread('forest.jpg')
Img_RGB = cv2.cvtColor(Img, cv2.COLOR_BGRA2RGB)
Img_Gray = cv2.cvtColor(Img_RGB, cv2.COLOR_RGB2GRAY)
_, Img_Binary = cv2.threshold(Img_Gray, 127, 255, cv2.THRESH_BINARY)
plt.subplot(2,2,1), plt.imshow(Img), plt.title('BGR'), plt.axis('off')
plt.subplot(2,2,2), plt.imshow(Img_RGB), plt.title('RGB'), plt.axis('off')
plt.subplot(2,2,3), plt.imshow(Img_Gray, cmap='gray'), plt.title('Grayscale'), plt.axis('off')
plt.subplot(2,2,4), plt.imshow(Img_Binary,cmap='gray'), plt.title('Binary'), plt.axis('off')
plt.tight_layout()
plt.show()Color Channel Splitting
An RGB image has three channels: Red, Green, and Blue. cv2.split() separates them. To display a single channel in color, merge it with zero-filled arrays for the other two channels.
B, G, R = cv2.split(Img)
zeros = np.zeros_like(B)
B_color = cv2.merge([B, zeros, zeros])
G_color = cv2.merge([zeros, G, zeros])
R_color = cv2.merge([zeros, zeros, R])
plt.subplot(2,2,1), plt.imshow(Img_RGB), plt.title('RGB'), plt.axis('off')
plt.subplot(2,2,2), plt.imshow(B_color), plt.title('Blue'), plt.axis('off')
plt.subplot(2,2,3), plt.imshow(G_color), plt.title('Green'), plt.axis('off')
plt.subplot(2,2,4), plt.imshow(R_color), plt.title('Red'), plt.axis('off')
plt.tight_layout()
plt.show()Sampling & Quantization
Quantization reduces the number of intensity levels. An n-bit image has 2ⁿ levels. For example, a 1-bit image is pure black-and-white; an 8-bit image has 256 levels. The formula: quantize each pixel by rounding to the nearest level gap.
Img = cv2.imread('rose.jpg').astype(np.float64)
for num_bits in range(1, 9):
num_levels = 2 ** num_bits
level_gap = 256 / num_levels
q_img = np.uint8(np.clip(np.ceil(Img / level_gap) * level_gap - 1, 0, 255))
plt.subplot(4, 4, num_bits)
plt.imshow(q_img)
plt.title(f'{num_bits}-bit')
plt.axis('off')
plt.tight_layout()
plt.show()