Filter ও convolution kernel
এই পাঠে যা শিখবেন
- Convolution operation — গণিত ও জ্যামিতি
- Common kernel — blur, sharpen, Sobel, emboss
- Padding, stride, separable kernel
- OpenCV-তে filter2D ও custom kernel
১ · Convolution কী?
একটি ছোট matrix (3×3, 5×5) — যাকে kernelKernel / Filterএকটি ছোট matrix যা ছবিতে slide করে weighted sum compute করে। Image processing ও CNN-এর মূল operation। বা filter বলি — ছবির প্রতিটি pixel-এর উপরে বসিয়ে weighted sum হিসাব করি। এটিই convolution।
$$\text{out}(x, y) = \sum_{i,j} K(i, j) \cdot I(x + i, y + j)$$
kernel ছবিতে slide করে — প্রতিটি অবস্থানে একটি নতুন pixel value বের করে। ফলাফল — একই size-এর (বা সামান্য ছোট) নতুন ছবি।
Kernel-এর সংখ্যাই বলে দেয় filter কী করছে। Same convolution operation — ভিন্ন kernel = ভিন্ন effect। এই simple framework-এ blur, edge, sharpen, এমনকি modern CNN — সবই বসে।
২ · একটি ছোট উদাহরণ
3×3 input ও 3×3 mean (averaging) kernel:
$$ K = \frac{1}{9}\begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix}, \quad I = \begin{bmatrix} 10 & 20 & 30 \\ 40 & 50 & 60 \\ 70 & 80 & 90 \end{bmatrix} $$
কেন্দ্র (50)-এ output:
$$\text{out}(1,1) = \frac{1}{9}(10 + 20 + ... + 90) = \frac{450}{9} = 50$$
কেন্দ্র = ৯ neighbor-এর গড়। এটিই box blur।
৩ · Kernel "চিড়িয়াখানা" — common filter
Identity (কিছুই করে না):
$$K = \begin{bmatrix} 0 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 0 \end{bmatrix}$$
Box blur (mean):
$$K = \frac{1}{9}\begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix}$$
Gaussian blur (center weighted):
$$K = \frac{1}{16}\begin{bmatrix} 1 & 2 & 1 \\ 2 & 4 & 2 \\ 1 & 2 & 1 \end{bmatrix}$$
Sharpen (center boost, neighbor subtract):
$$K = \begin{bmatrix} 0 & -1 & 0 \\ -1 & 5 & -1 \\ 0 & -1 & 0 \end{bmatrix}$$
Edge (Laplacian):
$$K = \begin{bmatrix} 0 & -1 & 0 \\ -1 & 4 & -1 \\ 0 & -1 & 0 \end{bmatrix}$$
Emboss (3D effect):
$$K = \begin{bmatrix} -2 & -1 & 0 \\ -1 & 1 & 1 \\ 0 & 1 & 2 \end{bmatrix}$$
৪ · Gaussian blur — গণিত
প্রতিটি weight Gaussian function-এ:
$$G(x, y) = \frac{1}{2\pi \sigma^2} e^{-\frac{x^2 + y^2}{2 \sigma^2}}$$
$\sigma$ যত বড়, blur তত বেশি। OpenCV-তে cv2.GaussianBlur(img, (k,k), sigma)।
৫ · Padding — boundary সমস্যা
Kernel ছবির প্রান্তে গেলে — kernel-এর কিছু অংশ ছবির বাইরে। কী করব?
- Zero padding: বাইরে 0। সরল কিন্তু dark border আসে।
- Reflect: mirror করে। natural, OpenCV default।
- Replicate: edge pixel repeat।
- Wrap: opposite side থেকে wrap। কম common।
৬ · Stride ও separable kernel
- Stride: kernel কতটি pixel skip করে slide করে। stride=1 default; stride=2 output অর্ধেক size।
- Separable kernel: 2D kernel = দু'টি 1D kernel-এর product। যেমন Gaussian-কে horizontal-vertical ভাগে আলাদা করা। 5×5 = 25 multiplication-এর বদলে 5+5 = 10। বড় kernel-এ বিশাল speedup।
৭ · OpenCV-তে custom filter
import cv2
import numpy as np
# একটি synthetic ছবি — diagonal stripes
img = np.zeros((100, 100), dtype=np.uint8)
for i in range(100):
img[i, max(0, i-5):min(100, i+5)] = 255
# Sharpen kernel
sharpen_k = np.array([
[ 0, -1, 0],
[-1, 5, -1],
[ 0, -1, 0]
], dtype=np.float32)
sharpened = cv2.filter2D(img, -1, sharpen_k)
# Box blur
blur_k = np.ones((5, 5), np.float32) / 25
blurred = cv2.filter2D(img, -1, blur_k)
# Gaussian blur (built-in)
gauss = cv2.GaussianBlur(img, (5, 5), sigmaX=1.5)
print("Original mean:", img.mean())
print("Sharpened diff:", np.abs(sharpened.astype(int) - img.astype(int)).mean())
print("Blurred mean:", blurred.mean())
print("Gaussian mean:", gauss.mean())
cv2.filter2D(img, -1, kernel) — যেকোনো custom kernel। -1 মানে output dtype = input dtype (uint8)। NumPy দিয়ে নিজে কোনো filter design করুন।
৮ · Filter ও CNN-এর সংযোগ
Classical filter: kernel hand-designed (কেউ Gaussian-এর সূত্র বের করেছেন, কেউ Sobel)।
CNN filter: একই convolution operation — কিন্তু kernel-এর সংখ্যা training-এ data থেকে শেখা। প্রথম layer-এ অনেকটা edge-detector-এর মতো শেখে — কারণ এটাই কাজে লাগে।
ResNet-এর প্রথম conv layer-এর filter visualize করলে — Gabor-like, Sobel-like, color-blob detector পাওয়া যায়। AI কেই hand-coded filter "discover" করেছে।
৯ · ভাল kernel design-এর rule
- Sum of weights: blur kernel-এ ১, edge-এ ০ (high-pass)।
- Symmetry: orientation-invariant filter symmetric।
- Normalization: output-এ overflow এড়াতে।
- Odd size: kernel size 3, 5, 7… — center pixel define করার জন্য।
ভাবনার প্রশ্ন
প্র ০১ "Convolution" আসলে গণিতে kernel flip করে। OpenCV-র filter2D flip করে না — সেটা cross-correlation। CNN-এ কোনটা? বাস্তবে কী পার্থক্য?
এটি একটি subtle কিন্তু গুরুত্বপূর্ণ পার্থক্য — যা বেশিরভাগ practitioner ignore করেন।
সত্যিকারের convolution:
- $\text{out}(x,y) = \sum_{i,j} K(i,j) \cdot I(x-i, y-j)$ — kernel flipped (180° rotate)।
- Mathematician-এর definition। Signal processing-এ standard।
- Property: associative, commutative — Fourier theorem-এ কাজে লাগে।
Cross-correlation:
- $\text{out}(x,y) = \sum_{i,j} K(i,j) \cdot I(x+i, y+j)$ — flip ছাড়া।
- Practical filter implementation।
- Template matching-এ ব্যবহৃত।
OpenCV কী করে? cv2.filter2D — cross-correlation (flip ছাড়া)। সত্যিকারের convolution চাইলে — kernel আগে flip করুন।
CNN কী করে? "Convolutional Neural Network" — misnomer। আসলে cross-correlation। কারণ:
- Kernel শেখা হয় — flip বা না করে আউটপুট same শেখা যায়।
- Implementation-এ flip skip = সামান্য fast।
- Conceptually convolution-এর বদলে cross-corr ভাবা সহজ।
কখন পার্থক্য matters?
- Symmetric kernel: Gaussian, box blur — flip = no change। মাত্র ব্যাপার নাই।
- Asymmetric kernel: Sobel-x — flip-এ -Sobel-x হবে। sign flip।
- Fourier theorem: shortcut convolution = pointwise multiply in frequency domain — শুধু true convolution-এ কাজ করে।
- Mathematical proof: derivative of convolution = derivative of one × other — শুধু true convolution-এ।
Practical advice: ML-এ পার্থক্য ignorable। Signal processing/DSP-তে সাবধান। SciPy-র scipy.signal.convolve2d true convolution; correlate2d cross-corr — choose wisely।
মূল উপলব্ধি: "Convolution" শব্দটি CNN-এ inaccurate কিন্তু entrenched। এই detail জানা = senior engineer signal।
প্র ০২ একটি 1024×1024 ছবিতে 21×21 Gaussian blur direct apply করলে কত operation? Separable trick কেন বাঁচায়?
এটি কেন large-kernel filtering CV-তে slow ছিল — তার গণিত। Separable kernel CNN architecture-এও কাজে লাগে (depthwise separable conv)।
Direct convolution cost:
- প্রতিটি output pixel: $21 \times 21 = 441$ multiply + 440 add।
- Total pixels: $1024 \times 1024 \approx 10^6$।
- Total ops: $441 \times 10^6 \approx 4.4 \times 10^8$ ≈ 440 million।
- Modern CPU 1 billion op/sec — প্রায় 0.5 second।
Separable trick:
Gaussian 2D kernel = Gaussian 1D × Gaussian 1D-এর outer product:
$$K_{2D}(i, j) = K_x(i) \cdot K_y(j)$$
তাই 2D convolution = horizontal 1D conv → vertical 1D conv।
Separable cost:
- Horizontal pass: $21$ ops × $10^6$ pixel = $21 \times 10^6$।
- Vertical pass: same — $21 \times 10^6$।
- Total: $42 \times 10^6$ — ~10x কম।
- Speedup ratio = $441 / 42 \approx 10.5\times$।
General formula:
- Direct: $O(k^2)$ per pixel।
- Separable: $O(2k)$ per pixel।
- Speedup: $k/2$ — kernel যত বড়, gain তত বেশি।
কোন kernel separable?
- Gaussian: always separable।
- Box blur: separable।
- Sobel: separable! $S_x = [1, 0, -1]^T \cdot [1, 2, 1]$।
- Laplacian: NOT separable (rotation-symmetric, কিন্তু rank > 1)।
- Random kernel: usually not — SVD দিয়ে check।
SVD test: 2D kernel-এর SVD নিন। Rank=1 → separable। Rank>1 → low-rank approximation দিয়ে approximate separable।
CNN-এ:
- MobileNet: depthwise separable conv — channel separable + spatial separable। 8-9x fewer params, similar accuracy।
- Inception v3: 7×7 conv-এর বদলে 1×7 + 7×1 — separable approximation।
FFT alternative: বড় kernel-এ ($k > 50$) — frequency-domain multiply আরো fast। Forward + inverse FFT cost = $O(N \log N)$।
মূল উপলব্ধি: Algorithmic efficiency CV-র backbone। Math করতে জানা = production-grade code লেখা।
প্র ০৩ Bilateral filter — Gaussian blur-এর মতো কিন্তু "edge preserving"। কীভাবে এই magic? Convolution থেকে কেমন আলাদা?
Bilateral — Tomasi & Manduchi (১৯৯৮) — Photography ও CV-তে যুগান্তকারী। Photoshop-এর "Surface Blur" — এটাই।
Standard Gaussian blur-এর সমস্যা:
- সব neighbor-এর weight শুধু distance-নির্ভর।
- Edge crossing-এ — কালো ও সাদা mix → ধূসর border।
- Detail হারায়।
Bilateral-এর insight: দু'টি weight গুণ —
$$w(x, y, i, j) = \underbrace{G_s(d)}_{\text{spatial}} \cdot \underbrace{G_r(|I(x,y) - I(i,j)|)}_{\text{range}}$$
- Spatial Gaussian: traditional — distance-নির্ভর।
- Range Gaussian: intensity পার্থক্য-নির্ভর। Brightness মিল না হলে weight কম।
ফল:
- Smooth area-এ — blur পূর্ণ।
- Edge-এ — across-edge weight কম, edge intact।
- Skin smoothing-এ আদর্শ — pore blur, eye/nose edge sharp।
Convolution-এর সাথে পার্থক্য:
- Convolution = linear + spatially invariant।
- Bilateral = non-linear — kernel weight প্রতিটি location-এ ভিন্ন (input-নির্ভর)।
- তাই FFT trick কাজ করে না, separable না (সরাসরি)।
- Computational cost বেশি — practical-এ approximation (joint bilateral, guided filter)।
Variants:
- Joint bilateral: range weight অন্য ছবি থেকে — flash/no-flash photography।
- Guided filter (He et al., 2010): faster bilateral approximation। OpenCV-তে
ximgproc.guidedFilter। - Cross bilateral: depth + color — RGB-D processing।
- Permutohedral lattice: O(N) bilateral — Adams et al.।
Modern relevance:
- Smartphone camera "portrait mode" — bilateral-derived skin smooth।
- RAW denoising।
- HDR tone mapping।
- Stylization (cartoon effect)।
DL alternative: Edge-preserving denoising এখন U-Net-এ — DnCNN, Restormer। কিন্তু bilateral এখনো mobile-এ unavoidable — fast, no training।
মূল উপলব্ধি: Convolution = linear filter-এর ভিত। Non-linear filter (bilateral, median) — সরাসরি convolution না, কিন্তু আজও essential।
প্র ০৪ CNN-এর প্রথম conv layer-এ যে kernels শেখে — ResNet/VGG-তে visualize করলে edge, blob, color দেখা যায়। মানুষ কি Sobel/Gabor design করেছিল কাকতালীয়, নাকি universal pattern?
এটি Computer Vision-এর সবচেয়ে আলোচিত findings-এর একটি। Hubel & Wiesel-এর ১৯৬২-এর বিড়ালের visual cortex experiment-এর সাথে সরাসরি লিঙ্ক।
Hubel-Wiesel finding:
- বিড়ালের visual cortex-এর V1 neurons — oriented edge detector।
- Simple cell → orientation-specific edge।
- Complex cell → orientation + translation invariant।
- Nobel Prize ১৯৮১।
Gabor filter (১৯৪৬):
- Gaussian-এ sine wave multiply।
- Edge orientation + frequency capture করে।
- V1 neuron-এর response model করে accurately।
CNN first layer যা শেখে:
- AlexNet first layer visualize (২০১২) — Gabor-like oriented edges, color blobs।
- Random init থেকে শুরু — ImageNet train শেষে এই pattern।
- VGG, ResNet, EfficientNet — সব same pattern।
- এমনকি unsupervised pretraining-ও same শেখে।
কেন universal?
- Natural image statistics: real photo-তে edge prevalent। Edge-detector compute-efficient feature।
- Sparse coding hypothesis (Olshausen & Field, 1996): natural images compress করার জন্য Gabor basis optimal — independent of biological constraint।
- Information theoretic: Gabor wavelet — space-frequency uncertainty সর্বনিম্ন (Heisenberg-like)।
CNN ও brain-এর parallel:
- Layer 1: edges (Gabor-like) ↔ V1।
- Layer 2-3: textures, junctions ↔ V2-V4।
- Higher layers: object parts, then objects ↔ IT cortex।
- Yamins & DiCarlo (2014): CNN activations predict primate IT cortex response — 60%+ variance।
Sobel/Canny-র sign:
- Sobel = বিশেষ Gabor (low-frequency edge)।
- Canny = Sobel + non-max suppression + hysteresis।
- Hand-design = brain-inspired biological mimicry।
- CNN = data-driven যা একই place-এ পৌঁছেছে।
Implication:
- Nature-এর শাশ্বত pattern — biology, hand-design, ML একই জায়গায় converge।
- "কোনো design আবিষ্কার" — সেটা data ও physics-এর constraint থেকে inevitable হয়।
- Foundation model age-এ এটাই rationale — large enough data থেকে general representation emerge।
মূল উপলব্ধি: ভাল Engineering = nature-এর reverse engineering। CV-তে এটি সবচেয়ে স্পষ্ট। Hand-coded ও learned filter-এর convergence — AI-র সবচেয়ে বড় philosophical lesson।
অনুশীলন
-
হিসাব: Identity kernel ও sharpen kernel-এর difference কী? Sharpen কেন একে "high-pass filter" বলা হয়?
Sharpen = identity + Laplacian negate-er sum। মানে — original + edge highlight। High-pass বলা হয় কারণ low-frequency (smooth area) cancel হয়, high-frequency (edge) boost।
-
Filter বানান: একটি motion blur kernel — শুধু horizontal direction-এ 9 pixel গড়। NumPy দিয়ে।
import numpy as np k = np.zeros((9,9), dtype=np.float32) k[4, :] = 1/9 # এই kernel শুধু একটি horizontal row-এ 1/9 — আনুভূমিক motion blur -
ভাবুন: CNN-এ kernel size 3×3 popular কেন, 5×5 বা 7×7 না?
VGG-র paper দেখাল — তিনটি 3×3 conv = এক 7×7 conv-এর effective receptive field, কিন্তু parameter কম (3·9=27 vs 49) ও more non-linearity (3 ReLU vs 1)। তাই 3×3 standard হয়ে গেছে।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পাঠ ০৬ · Edge detection — Sobel ও Canny পরবর্তী পাঠ Filter-ভিত্তিক edge detector — হাতে design।
- পাঠ ০৪ · Threshold & morphology আগের পাঠ Filter-এর আগের step।
- পাঠ ০৯ · CNN পুনরাবৃত্তি এগিয়ে এই kernel শিখে নেয় যে নেটওয়ার্ক।
- সব AI Courses দেখুন ABCL TECH Python, ML, DL, NLP, CV, GenAI, RL, MLOps — সব AI কোর্স একসাথে।