A kernel (or filter) is a small matrix used to apply effects to an image.
Examples:
Size: Usually small (3×3, 5×5, 7×7) and odd-sized Purpose: Define how to combine neighborhood pixels
Convolution is sliding a kernel over an image and computing weighted sums.
Process:
Formula: Output(x,y) = Σ Kernel(i,j) × Image(x+i, y+j)
Output(x,y) = Σ Kernel(i,j) × Image(x+i, y+j)
Result: One output pixel value = -60
Problem: Kernel extends beyond image border
Solutions:
OpenCV default: Reflection (cv2.BORDER_REFLECT_101)
cv2.BORDER_REFLECT_101
import cv2import numpy as np# define a 3x3 identity kernelkernel = np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]], dtype=np.float32)# apply convolutionresult = cv2.filter2D(img, -1, kernel)#ans: -1 means output same depth as input# identity kernel returns original image#ans: center weight=1, others=0, no change
# 3x3 averaging kernelkernel = np.ones((3, 3), dtype=np.float32) / 9#ans: all weights = 1/9, sums to 1# apply box blurblurred = cv2.filter2D(img, -1, kernel)#ans: same as cv2.blur(img, (3, 3))# 5x5 box blur kernelkernel = np.ones((5, 5), dtype=np.float32) / 25result = cv2.filter2D(img, -1, kernel)#ans: averages 25 pixels, more blur
# sharpen kernel (enhances edges)kernel = np.array([[ 0, -1, 0], [-1, 5, -1], [ 0, -1, 0]], dtype=np.float32)#ans: center=5, neighbors=-1, enhances differencessharpened = cv2.filter2D(img, -1, kernel)#ans: edges become more pronounced# why does this sharpen?#ans: amplifies center, subtracts neighbors (enhances edges)
# horizontal edge detection (Prewitt)kernel_h = np.array([[-1, -1, -1], [ 0, 0, 0], [ 1, 1, 1]], dtype=np.float32)#ans: detects horizontal edges (top-bottom transition)# vertical edge detectionkernel_v = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]], dtype=np.float32)#ans: detects vertical edges (left-right transition)edges_h = cv2.filter2D(gray, -1, kernel_h)edges_v = cv2.filter2D(gray, -1, kernel_v)#ans: apply to grayscale for best results
# 5x5 gaussian kernel approximationkernel = np.array([[1, 4, 6, 4, 1], [4, 16, 24, 16, 4], [6, 24, 36, 24, 6], [4, 16, 24, 16, 4], [1, 4, 6, 4, 1]], dtype=np.float32) / 256#ans: weights decrease from center (gaussian distribution)gaussian = cv2.filter2D(img, -1, kernel)#ans: similar to cv2.GaussianBlur but custom kernel
Why normalize? Keep output in valid range (0-255)
Formula: Divide by sum of kernel weights
# unnormalized kernelkernel = np.array([[1, 2, 1], [2, 4, 2], [1, 2, 1]], dtype=np.float32)# sum of weightskernel_sum = kernel.sum() # = 16#ans: sum = 1+2+1+2+4+2+1+2+1 = 16# normalizekernel_norm = kernel / kernel_sum#ans: ensures output stays in range
# what does convolution do?#ans: slides kernel over image, computes weighted sums# why odd kernel sizes?#ans: needs center pixel for symmetry# what is identity kernel?kernel = np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]])#ans: returns original image (no change)# what does sum of weights=1 ensure?#ans: preserves brightness, no amplification
# what detects vertical edges?#ans: kernel with [-1, 0, 1] pattern horizontally# what is cv2.filter2D ddepth parameter?result = cv2.filter2D(img, -1, kernel)#ans: -1 means same depth as source# difference between blur and sharpen kernels?#ans: blur averages (positive weights), sharpen enhances (negative neighbors)# why apply edge detection on grayscale?#ans: simpler, one channel, intensity changes are edges
# create 3x3 identity kernel#ans: kernel = np.array([[0, 0, 0],#ans: [0, 1, 0],#ans: [0, 0, 0]], dtype=np.float32)# apply identity kernel#ans: result = cv2.filter2D(img, -1, kernel)# create 3x3 box blur kernel#ans: kernel = np.ones((3, 3), dtype=np.float32) / 9#ans: result = cv2.filter2D(img, -1, kernel)
# create sharpen kernel#ans: kernel = np.array([[ 0, -1, 0],#ans: [-1, 5, -1],#ans: [ 0, -1, 0]], dtype=np.float32)# apply sharpen#ans: sharpened = cv2.filter2D(img, -1, kernel)# create horizontal edge kernel#ans: kernel = np.array([[-1, -1, -1],#ans: [ 0, 0, 0],#ans: [ 1, 1, 1]], dtype=np.float32)
# create emboss kernel#ans: kernel = np.array([[-2, -1, 0],#ans: [-1, 1, 1],#ans: [ 0, 1, 2]], dtype=np.float32)#ans: embossed = cv2.filter2D(gray, -1, kernel)# create outline kernel#ans: kernel = np.array([[-1, -1, -1],#ans: [-1, 8, -1],#ans: [-1, -1, -1]], dtype=np.float32)#ans: outline = cv2.filter2D(img, -1, kernel)
# normalize a custom kernelkernel = np.array([[1, 2, 1], [2, 4, 2], [1, 2, 1]], dtype=np.float32)#ans: kernel_norm = kernel / kernel.sum()#ans: sum = 16, so divide by 16# what is the sum after normalization?#ans: 1.0 (preserves brightness)# create strong sharpen (center=9)#ans: kernel = np.array([[ 0, -1, 0],#ans: [-1, 9, -1],#ans: [ 0, -1, 0]], dtype=np.float32)
# 5x5 average kernel#ans: kernel = np.ones((5, 5), dtype=np.float32) / 25# left edge detection#ans: kernel = np.array([[1, 0, -1],#ans: [2, 0, -2],#ans: [1, 0, -1]], dtype=np.float32)#ans: this is Sobel-X kernel# combine two edge detectionsedges_h = cv2.filter2D(gray, -1, kernel_h)edges_v = cv2.filter2D(gray, -1, kernel_v)#ans: edges = cv2.addWeighted(edges_h, 0.5, edges_v, 0.5, 0)#ans: combines horizontal and vertical edges
# motion blur kernel (horizontal)#ans: kernel = np.zeros((5, 5), dtype=np.float32)#ans: kernel[2, :] = 1/5#ans: horizontal motion blur effect# apply convolution with border handling#ans: result = cv2.filter2D(img, -1, kernel, borderType=cv2.BORDER_CONSTANT)# create custom gaussian-like kernel#ans: kernel = np.array([[1, 2, 1],#ans: [2, 4, 2],#ans: [1, 2, 1]], dtype=np.float32) / 16
Google tag (gtag.js)