পাঠ ০৫ · ৩৫-এর মধ্যে · মডিউল ১
Home / AI Courses / Computer Vision / Filters & kernels

Filter ও convolution kernel

Filters & convolution kernels — the math of image effects
৭ মিনিট পড়া শুরু · Beginner NumPy + OpenCV

এই পাঠে যা শিখবেন

  • 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)।

Gaussian blur = প্রতিটি pixel-এর "প্রতিবেশীদের কথা শোনা" — কিন্তু কাছেরটি বেশি, দূরেরটি কম। Box blur — সবার কথা সমান শোনা — তাই detail বেশি হারায়। Gaussian — সফট, natural।

৫ · 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।
Convolution — kernel slide করে নতুন ছবি Input (5×5) 3 5 2 7 1 4 8 6 9 3 Kernel (3×3) 0 -1 0 -1 5 -1 0 -1 0 sharpen kernel Output (5×5) 19 5·8 - 4 - 6 - 5 - 9 = 19 × sum প্রতিটি output pixel = kernel × neighbor-এর elementwise product → sum এই operation slide করে পুরো ছবিতে
Convolution = kernel × pixel patch → element-wise multiply → sum। ছবিতে slide করে নতুন ছবি।

৭ · OpenCV-তে custom filter

Python · OpenCV
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 করার জন্য।
Kernel size বাড়ালে computational cost quadratic-ভাবে বাড়ে। 3×3 = 9 ops, 9×9 = 81 ops per pixel। বড় blur-এর জন্য Gaussian সরাসরি সমাধান, separable trick দিয়ে fast।

ভাবনার প্রশ্ন

প্র ০১ "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।

অনুশীলন

  1. হিসাব: 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।

  2. 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
  3. ভাবুন: 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-এ আপনার পরবর্তী পদক্ষেপ

কোড রানার কাজ না করলে? ব্রাউজারে কাজ না করলে Google Colab ব্যবহার করুন — Google-এর ফ্রি অনলাইন Python পরিবেশ, শুধু Gmail অ্যাকাউন্ট লাগে।
পূর্ববর্তী পাঠ
পাঠ ০৪ · Threshold ও morphology