Learn image processing by seeing, coding, and experimenting
Study each concept with a visual example, compare Python and MATLAB commands, then log in to process your own images in the lab.
💻 Modules Available:
Select a module to learn about its mathematical core and apply it in real-time inside the lab.
Histogram Equalization
Enhance the global contrast of images by redistributing intensity frequencies evenly across the histogram.
import cv2
import numpy as np
# Grayscale Histogram Equalization
equalized_gray = cv2.equalizeHist(gray_img)
# Color Histogram Equalization (YCrCb)
ycrcb = cv2.cvtColor(color_img, cv2.COLOR_BGR2YCrCb)
ycrcb[:, :, 0] = cv2.equalizeHist(ycrcb[:, :, 0])
equalized_color = cv2.cvtColor(ycrcb, cv2.COLOR_YCrCb2BGR)
% Grayscale Histogram Equalization
equalized_gray = histeq(gray_img);
% Color Histogram Equalization (L*a*b*)
lab = rgb2lab(color_img);
lab(:,:,1) = histeq(lab(:,:,1)/100)*100;
equalized_color = lab2rgb(lab);
Color Space Conversion
Convert images between different color models (BGR, Grayscale, and HSI) with side-by-side components.
import cv2
import numpy as np
# BGR to Grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Grayscale to JET pseudocolor
jet = cv2.applyColorMap(gray, cv2.COLORMAP_JET)
# BGR to HSI model conversion
img_f = img.astype(np.float32) / 255.0
b, g, r = cv2.split(img_f)
i = (r + g + b) / 3.0
num = 0.5 * ((r-g) + (r-b))
den = np.sqrt((r-g)**2 + (r-b)*(g-b)) + 1e-6
h = np.arccos(np.clip(num/den, -1.0, 1.0)) / (2*np.pi)
h[g < b] = 1.0 - h[g < b]
% RGB to Grayscale
gray = rgb2gray(img);
% Grayscale to JET pseudocolor
jet = ind2rgb(gray, jet(256));
% RGB to HSI conversion
hsv = rgb2hsv(img); % HSV is close to HSI
H = hsv(:,:,1);
S = hsv(:,:,2);
I = hsv(:,:,3);
Frequency Domain
Compute 2D Discrete Fourier Transforms to display centered Magnitude and Phase spectrums.
import cv2
import numpy as np
# Compute 2D DFT & Center Spectrum
dft = np.fft.fft2(gray_img)
dft_shift = np.fft.fftshift(dft)
# Log-scaled Magnitude Spectrum
mag = np.abs(dft_shift)
mag_log = np.log(1.0 + mag)
# Phase Spectrum
phase = np.angle(dft_shift)
% Compute 2D FFT & Center Spectrum
f = fft2(double(gray_img));
fshift = fftshift(f);
% Log-scaled Magnitude Spectrum
mag = abs(fshift);
mag_log = log(1.0 + mag);
% Phase Spectrum
phase = angle(fshift);
Gray Transformations
Perform intensity mapping including Negative, Log, Gamma, Contrast Stretching, and Bit Slicing.
import cv2
import numpy as np
# Negative Image
negative = 255 - gray
# Gamma Correction (Power Law)
table = np.array([((i / 255.0) ** 1.5) * 255 for i in range(256)]).astype("uint8")
gamma = cv2.LUT(gray, table)
# Bit-plane Slicing (extract bit 7)
bit_plane = (gray >> 7) & 1
bit_img = bit_plane * 255
% Negative Image
negative = imcomplement(gray);
% Gamma Correction (Power Law)
gamma = imadjust(gray, [], [], 1.5);
% Bit-plane Slicing (extract bit 8)
bit_img = bitget(gray, 8) * 255;
Image Filter
Apply spatial linear/non-linear filters or frequency filters, analyze metrics with added noise.
import cv2
import numpy as np
# Spatial Gaussian Blur
blur = cv2.GaussianBlur(img, (5, 5), 0)
# Frequency Butterworth Low Pass Filter
rows, cols = gray.shape
crow, ccol = rows//2, cols//2
u, v = np.meshgrid(np.arange(rows), np.arange(cols), indexing='ij')
D = np.sqrt((u-crow)**2 + (v-ccol)**2)
H = 1 / (1 + (D / 30.0)**(2*2)) # D0=30, order=2
f_shift = np.fft.fftshift(np.fft.fft2(gray)) * H
filtered = np.uint8(np.real(np.fft.ifft2(np.fft.ifftshift(f_shift))))
% Spatial Gaussian Filter
blur = imgaussfilt(img, 2);
% Frequency Butterworth Low Pass Filter
[M, N] = size(gray);
[U, V] = dftuv(M, N);
D = sqrt(U.^2 + V.^2);
H = 1 ./ (1 + (D./30).^(2*2));
f = fftshift(fft2(double(gray)));
filtered = real(ifft2(ifftshift(f .* H)));
Restoration & Denoise
Denoise corrupted images using NL-Means or repair surface scratches with interactive mask inpainting.
import cv2
import numpy as np
# Fast Non-Local Means Denoising
denoised = cv2.fastNlMeansDenoisingColored(
img, None, h=10, hColor=10,
templateWindowSize=7, searchWindowSize=21
)
# Navier-Stokes Inpainting
restored = cv2.inpaint(img, mask_gray, 3, cv2.INPAINT_NS)
% Non-Local Means Denoising
denoised = imnlmfilt(img);
% Mask-based Inpainting (coherent inpainting)
% (Requires Image Processing Toolbox)
restored = inpaintCoherent(img, mask);
Segmentation
Isolate structures and extract key regions using thresholding and local binarization techniques.
import cv2
import numpy as np
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Otsu Thresholding
_, th_otsu = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# Adaptive Gaussian Thresholding
th_adap = cv2.adaptiveThreshold(
gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2
)
gray = rgb2gray(img);
% Otsu Thresholding
level = graythresh(gray);
th_otsu = imbinarize(gray, level);
% Adaptive Local Thresholding
th_adap = imbinarize(gray, 'adaptive', ...
'Sensitivity', 0.5);
Image Compression
Analyze JPEG quantization, compression ratios, and byte-savings under different quality levels.
import cv2
import numpy as np
# JPEG compress in memory
quality = 80
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), quality]
success, encoded = cv2.imencode('.jpg', img, encode_param)
# Decode back to image format
compressed = cv2.imdecode(encoded, cv2.IMREAD_COLOR)
% JPEG compress to disk
imwrite(img, 'output.jpg', 'jpg', 'Quality', 80);
% Read back
compressed = imread('output.jpg');
Image Morphology
Modify structures using kernel elements, skeletonization, Top-Hats, Hit-or-Miss, and Convex Hull.
import cv2
import numpy as np
# Rectangular Structuring Element
se = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
open_img = cv2.morphologyEx(img, cv2.MORPH_OPEN, se)
# White Top-Hat
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, se)
# Convex Hull boundary
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
hull_img = np.zeros_like(binary)
for c in contours:
hull = cv2.convexHull(c)
cv2.drawContours(hull_img, [hull], -1, 255, -1)
% Structuring Element
se = strel('rectangle', [5 5]);
open_img = imopen(img, se);
% White Top-Hat
tophat = imtophat(img, se);
% Convex Hull boundary
hull = bwconvhull(binary);
Alignment & Fusion
Align multi-model images (Rigid, Affine, TPS) using SIFT keypoints and fuse via average/multiply blending.
import cv2
import numpy as np
# Extract SIFT keypoints & descriptors
sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
# Match and estimate Affine
bf = cv2.BFMatcher(cv2.NORM_L2)
matches = bf.knnMatch(des1, des2, k=2)
good = [m for m, n in matches if m.distance < 0.75 * n.distance]
matrix, mask = cv2.estimateAffine2D(pts2, pts1, method=cv2.RANSAC)
aligned = cv2.warpAffine(img2, matrix, (width, height))
% Extract SIFT features
ptsRef = detectSIFTFeatures(grayRef);
ptsMov = detectSIFTFeatures(grayMov);
[fRef, vRef] = extractFeatures(grayRef, ptsRef);
[fMov, vMov] = extractFeatures(grayMov, ptsMov);
% Match & Warp using Affine model
idx = matchFeatures(fRef, fMov, 'Unique', true);
tform = estimateGeometricTransform2D(...
matchedMov, matchedRef, 'affine');
aligned = imwarp(moving, tform, ...
'OutputView', imref2d(size(ref)));
Image Reconstruction
Compute 1D projections via Radon transform and perform CT reconstructions (BP, FBP, MLEM, OSEM).
import cv2
import numpy as np
# Radon Transform projection
angles = np.arange(0, 180, 4)
sinogram = radon_transform(image, angles)
# Filtered Backprojection reconstruction
# 1. Apply Ramp filter to Sinogram
filtered_sinogram = apply_ramp_filter(sinogram)
# 2. Backproject filtered sinogram
fbp_recon = backproject(filtered_sinogram, angles)
% Radon Transform (Sinogram)
angles = 0:4:179;
[sinogram, xp] = radon(image, angles);
% Filtered Backprojection reconstruction
% (using Ram-Lak filter)
fbp_recon = iradon(sinogram, angles, 'Ram-Lak');
🚀 Ready to Experiment?
Log in with your student credentials to access the laboratory environment and run operations in real time!
Login now