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 -bit image has levels ā a 1-bit image is pure black-and-white ( levels), while an 8-bit image has levels. Each pixel is quantized 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()