Noel Jeffrey Pinton
Department of Computer Science
University of the Philippines Cebu
Noel Jeffrey Pinton
Department of Computer Science
University of the Philippines Cebu
By the end of this module, you will be able to:
Pixel-wise intensity transformations
Point Operation: A transformation where each output pixel depends only on the corresponding input pixel.
$$g(x,y) = T[f(x,y)]$$
Why are point operations highly parallelizable?
Because each output pixel depends only on the corresponding input pixel, all pixels can be processed independently and simultaneously.
Click the blurred area to reveal the answer
Common intensity transformation functions: linear, logarithmic, power-law (gamma)
$$g = \alpha \cdot f + \beta$$
$$g = c \cdot f^\gamma$$
Effects of brightness, contrast, and gamma adjustments on an image
Enhancing contrast through histogram manipulation
Histogram: A graphical representation of the distribution of pixel intensities in an image.
Low contrast images have narrow histograms; high contrast images span the full range.
Histogram equalization spreads intensities to utilize the full dynamic range
What is the goal of histogram equalization?
To redistribute pixel intensities so that they are more uniformly distributed across the available range, thereby enhancing image contrast.
Click the blurred area to reveal the answer
import cv2
import numpy as np
# Equalize histogram
img = cv2.imread('image.jpg', 0)
eq = cv2.equalizeHist(img)
# Using NumPy
hist, bins = np.histogram(img.flatten(), 256, [0,256])
cdf = hist.cumsum()
cdf_normalized = cdf * 255 / cdf.max()CLAHE applies equalization locally, preventing over-amplification of noise
CLAHE: Contrast Limited Adaptive Histogram Equalization - divides image into tiles and applies equalization with clipping.
import cv2
# Create CLAHE object
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
# Apply to grayscale image
img = cv2.imread('image.jpg', 0)
cl_img = clahe.apply(img)
# For color images, apply to L channel in LAB
lab = cv2.cvtColor(color_img, cv2.COLOR_BGR2LAB)
lab[:,:,0] = clahe.apply(lab[:,:,0])
result = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
The fundamental operation in image filtering
2D Convolution: A mathematical operation that combines an image with a kernel (filter) to produce a filtered output.
$$g(x,y) = \sum_{i=-k}^{k} \sum_{j=-k}^{k} f(x-i, y-j) \cdot h(i,j)$$
The kernel slides over the image, computing weighted sums at each position
What happens at each position during convolution?
The kernel is centered at a pixel, corresponding values are multiplied, and all products are summed to produce the output pixel value.
Click the blurred area to reveal the answer
Kernel is flipped (180°)
$g = f * h$
Kernel is not flipped
$g = f \star h$
Different padding strategies: zero, replicate, reflect, wrap
Convolution Theorem:
$$f * h = \mathcal{F}^{-1}\{\mathcal{F}\{f\} \cdot \mathcal{F}\{h\}\}$$
Convolution in spatial domain = Multiplication in frequency domain
Why is the convolution theorem useful for large kernels?
For large kernels, performing FFT, multiplication, and inverse FFT is faster than direct spatial convolution. The crossover point is typically around 11×11 kernel size.
Click the blurred area to reveal the answer
Frequency domain analysis of images
2D DFT: Decomposes an image into its constituent frequency components (sinusoidal patterns).
$$F(u,v) = \sum_{x=0}^{M-1} \sum_{y=0}^{N-1} f(x,y) \cdot e^{-j2\pi(ux/M + vy/N)}$$
Image and its magnitude spectrum (log scale, centered)
Key properties: linearity, shift, rotation, scaling
Decomposing an image into low and high frequency components
What image features correspond to high frequencies?
Edges, fine details, textures, and noise - anywhere there are rapid changes in pixel intensity.
Click the blurred area to reveal the answer
import numpy as np
import cv2
# Read grayscale image
img = cv2.imread('image.jpg', 0)
# Compute 2D FFT
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f) # Center the spectrum
# Magnitude spectrum (log scale for display)
magnitude = 20 * np.log(np.abs(fshift) + 1)
# Apply a simple low-pass filter
rows, cols = img.shape
crow, ccol = rows//2, cols//2
mask = np.zeros((rows, cols), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1
# Apply filter and inverse FFT
filtered = fshift * mask
f_ishift = np.fft.ifftshift(filtered)
result = np.abs(np.fft.ifft2(f_ishift))
Key Takeaways
Thank you for your attention!
Interactive notebook available for hands-on practice
Questions?