Threshold ও morphology
এই পাঠে যা শিখবেন
- Global, Otsu ও adaptive thresholding
- Erosion, dilation — structuring element
- Opening ও closing — কখন কোনটা
- OpenCV-তে practical mask cleanup
১ · Thresholding কী?
ThresholdingThresholdingপ্রতিটি pixel-কে একটি cutoff value-র সাথে compare — তার বেশি হলে 255, কম হলে 0। Image-কে binary mask-এ রূপান্তর — segmentation-এর সবচেয়ে সরল উপায়।-এর সূত্র সরল:
$$ \text{out}(x, y) = \begin{cases} 255 & \text{if } I(x, y) > T \\ 0 & \text{otherwise} \end{cases} $$
ফলাফল — একটি binary mask। সাদা = object (foreground), কালো = background। এর উপর ভিত্তি করে contour, area, centroid বের করা যায়।
Thresholding = "এই pixel কি object-এর অংশ?" — এর সরলতম উত্তর। কাজ করে যখন object ও background-এর brightness আলাদা।
২ · Global threshold-এর সমস্যা
একটি fixed cutoff (যেমন T=128) সব ছবিতে কাজ করে না।
- উজ্জ্বল ছবিতে background-ই 200+ — সব সাদা।
- অন্ধকার ছবিতে object 100 — সব কালো।
- একটি ছবির এক অংশ আলোকিত, অন্য অংশ ছায়ায় — single T পারে না।
তাই দু'টি smarter পদ্ধতি — Otsu (automatic global) ও Adaptive (local)।
৩ · Otsu's method — automatic threshold
Nobuyuki Otsu (১৯৭৯) — histogram-এর variance বিশ্লেষণ করে সেরা T বেছে।
মূল ধারণা: ছবিতে দু'টি class — foreground ও background। সেরা T সেটাই — যা দু'টি class-এর between-class variance maximize করে।
$$T^* = \arg\max_T \; \sigma_b^2(T) = w_0(T) w_1(T) [\mu_0(T) - \mu_1(T)]^2$$
যেখানে $w_0, w_1$ class probability, $\mu_0, \mu_1$ class mean।
৪ · Adaptive thresholding
প্রতি pixel-এর threshold আলাদা — তার চারপাশের छোট window-এর mean বা Gaussian-weighted mean।
$$T(x, y) = \mu_{N(x,y)} - C$$
যেখানে $N(x, y)$ = $(x, y)$-এর চারপাশের window, $C$ = constant offset।
Use case: uneven lighting (পুরোনো document scan, X-ray, side-lit photo)। OCR-এর জন্য আদর্শ।
৫ · Morphology — mask cleanup
Threshold-এর পর mask সাধারণত noisy — small dot, hole, gap। MorphologyMathematical Morphologyসেট-ভিত্তিক image processing — Matheron ও Serra (১৯৬০-৭০)। Structuring element দিয়ে shape probe — erosion, dilation এর মূল operation। এই noise পরিষ্কার করে।
একটি structuring element (kernel) দিয়ে mask-এ scan। সাধারণ kernel — 3×3 বা 5×5 ones।
৬ · Erosion ও Dilation
- Erosion: pixel তখনই 1 থাকে যখন তার চারপাশের সব kernel-cell-ই 1। ফলে — সাদা region সংকুচিত। ছোট white noise dot হারায়।
- Dilation: pixel 1 হয় যদি চারপাশের কোনো একটিও 1। সাদা region বিস্তৃত। ছোট hole পূরণ।
সূত্রে:
$$\text{erode}(I)(x,y) = \min_{(i,j) \in K} I(x+i, y+j)$$
$$\text{dilate}(I)(x,y) = \max_{(i,j) \in K} I(x+i, y+j)$$
৭ · Opening ও Closing
- Opening = erosion → dilation। ছোট white noise সরায়, কিন্তু object-এর আকার retain।
- Closing = dilation → erosion। ছোট hole পূরণ, ভাঙা edge join।
Practical rule:
- সাদা dot/specks বিরক্ত? → Opening
- Object-এর ভিতরে ছোট কালো hole? → Closing
- প্রায়শই দু'টোই sequence-এ — Open → Close।
৮ · OpenCV-তে threshold
import cv2
import numpy as np
# একটি synthetic gradient ছবি
img = np.tile(np.linspace(0, 255, 200, dtype=np.uint8), (100, 1))
print("shape:", img.shape, "min:", img.min(), "max:", img.max())
# Global threshold T=128
_, binary = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY)
print("Binary unique:", np.unique(binary))
# Otsu — automatic
T, otsu = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
print(f"Otsu chose T = {T}")
# Inverse — object dark on white
_, inv = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY_INV)
print("Inverted unique:", np.unique(inv))
cv2.threshold দু'টি জিনিস return করে — chosen T ও binary image। THRESH_BINARY_INV object-এ কালো রাখে — OCR-এ দরকার যেখানে text কালো।
৯ · Morphology হাতে-কলমে
import cv2
import numpy as np
# একটি noisy binary mask বানাই
mask = np.zeros((100, 100), dtype=np.uint8)
mask[30:70, 30:70] = 255 # square object
mask[40:50, 40:50] = 0 # হোল
mask[10, 10] = 255 # noise dot
mask[80, 85] = 255 # noise dot
kernel = np.ones((3, 3), np.uint8)
eroded = cv2.erode(mask, kernel, iterations=1)
dilated = cv2.dilate(mask, kernel, iterations=1)
opened = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
closed = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
print("Original white pixels:", np.count_nonzero(mask))
print("Eroded :", np.count_nonzero(eroded))
print("Dilated :", np.count_nonzero(dilated))
print("Opened :", np.count_nonzero(opened))
print("Closed :", np.count_nonzero(closed))
ভাবনার প্রশ্ন
প্র ০১ Otsu's method bimodal histogram-এ কাজ করে। কিন্তু একটি page scan-এ histogram unimodal বা trimodal হলে — কী হয়? বিকল্প কী?
Otsu-র assumption — দু'টি well-separated class। বাস্তবে অনেক ছবিতে এই assumption ভাঙে।
Unimodal histogram-এ:
- সব pixel একই brightness range-এ — যেমন solid white background-এ light gray text।
- Otsu arbitrary T pick করে — meaningful না।
- Output প্রায় সব black বা সব white হতে পারে।
Trimodal/multimodal:
- ৩টি object class — যেমন কালো text, ধূসর background, সাদা margin।
- Otsu শুধু একটি T দেয় — দু'টি class merge হয়।
- Multi-Otsu (extension) — multiple T পেতে।
বিকল্প:
- Adaptive thresholding: uneven lighting-এ best — local mean বা Gaussian।
- Sauvola binarization: document-এ gold standard — local mean ও std-নির্ভর। Tesseract OCR এতেই preprocess।
- Niblack: Sauvola-র predecessor — simpler কিন্তু noise-prone।
- K-means clustering: ৩+ class যখন।
- GMM (Gaussian Mixture Model): probabilistic — soft assignment।
- Deep U-Net: শেষ আশ্রয় — hand-crafted threshold ব্যর্থ হলে CNN দিয়ে binarize।
Pre-processing tricks:
- Histogram equalization আগে → contrast stretch।
- CLAHE (Contrast Limited Adaptive Histogram Eq) — local equalization, robust।
- Background subtraction — top-hat morphology দিয়ে।
- Bilateral filter — edge preserve করে smooth।
মূল উপলব্ধি: "Threshold = simple" — হ্যাঁ algorithm-এ। কিন্তু ভালো T পাওয়া কঠিন। Real document binarization এখনও research topic — DIBCO competition প্রতি বছর।
প্র ০২ আপনি একটি color document থেকে শুধু লাল sticker detect করতে চান। HSV mask করার পর mask noisy। Open আগে না close আগে?
এটি pipeline ordering-এর একটি classic question। উত্তর — সাধারণত open আগে, তারপর close।
কেন এই sequence?
- HSV color mask সাধারণত দু'ধরনের noise তৈরি করে: false-positive specks (যা sticker না কিন্তু color match) এবং true-positive holes (sticker-এর reflection-এ color shift)।
- Step 1 — Opening: ছোট false-positive specks dissolve। Sticker bounding region unchanged।
- Step 2 — Closing: sticker-এর ভিতরে glare/reflection-এর holes পূরণ। External shape preserve।
উল্টো করলে কী হয়?
- Close → Open: প্রথমে close — noise speck-এর চারপাশের কালো region পূরণ করে speck enlarge। Then open — কিন্তু এখন speck বড় হয়ে গেছে, removable নাও হতে পারে।
- সংক্ষেপে — noise propagate।
Kernel size strategy:
- Open kernel: noise-এর scale-এ — সাধারণত 3×3 বা 5×5।
- Close kernel: hole scale-এ — 7×7 বা 11×11 (sticker হোলগুলো বড় হতে পারে)।
- Object-এর scale-এর চেয়ে বড় kernel ব্যবহার করবেন না — object distort হবে।
আরেকটি best practice:
- Median filter আগে: mask-এর আগে original ছবিতে — speckle noise আগেই কমে।
- Connected component analysis: morphology-র পর — area threshold দিয়ে ছোট blob discard।
- Convex hull: sticker convex শেপ — non-convex artifact ফেলে দেওয়া।
Domain example:
- Traffic sign detection: Open(3) → Close(11) → CC area > 200 px।
- Cell counting in microscopy: Open(5) → Close(3) — small cells cleanup।
- License plate: Close(15, 5) (rectangular kernel) → Open(3) — text-region join।
মূল উপলব্ধি: Morphology recipe — domain-specific। Default rule "open then close, kernel small to large", কিন্তু সবসময় visualize করে adjust করুন।
প্র ০৩ Deep learning-এর যুগে এই classical morphology কি অপ্রাসঙ্গিক? CNN কি সব শিখে নিতে পারে না?
এই প্রশ্ন প্রতিটি CV course-এ আসে। উত্তর — না, morphology এখনো গুরুত্বপূর্ণ। কিন্তু role ভিন্ন।
কেন এখনো প্রাসঙ্গিক:
- Post-processing: CNN segmentation output প্রায়ই jagged — opening/closing দিয়ে smooth।
- Industrial inspection: defect detection — high-contrast, controlled lighting → threshold + morphology সরাসরি কাজ করে। CNN overkill।
- Edge devices: Raspberry Pi, MCU-তে CNN expensive — classical pipeline 100x faster।
- Medical imaging: bone segmentation, cell counting — morphology FDA-validated।
- Document processing: Sauvola + morphology এখনও OCR pipeline-এর backbone।
CNN-এর সাথে hybrid:
- U-Net output → connected component → morphological cleanup।
- YOLO bounding box → mask refinement morphology দিয়ে।
- Mask R-CNN-এর instance mask polish — boundary smoothing।
CNN যা শেখে:
- Implicit edge detection — early conv layer-এ Sobel-like filter।
- Implicit morphology — pooling effectively erosion/dilation-এর কাছাকাছি।
- কিন্তু explicit morphology-এর precise control নেই।
Differentiable morphology:
- Recent research — morphological op-কে differentiable করে CNN-এ embed।
- "DeepMorpho" papers — interpretable + trainable।
কখন pure DL চাই:
- Complex texture, fine-grained category।
- Variable lighting, occlusion।
- Large labeled dataset available।
কখন classical morphology যথেষ্ট:
- Controlled environment (factory line)।
- Binary task (defect/no-defect)।
- Compute-limited deployment।
- Explainability required (legal, medical)।
মূল উপলব্ধি: "DL replaces classical" — myth। ভাল CV engineer দু'টোই tool box-এ রাখে। Right tool for right job।
প্র ০৪ একটি OMR sheet (multiple choice answer paper) থেকে marked answer detect করার pipeline ডিজাইন করুন। Threshold ও morphology কোথায় fit?
OMR — classical CV-র perfect use case। Pure morphology ও threshold দিয়ে production-grade solution বানানো যায়।
Pipeline:
- Capture & deskew: phone/scanner থেকে image → corner detect (Harris) → 4-point perspective transform → ideal rectangular sheet।
- Grayscale + denoise: Gaussian blur (3×3) — paper texture noise কমায়।
- Adaptive threshold: uneven lighting compensate — Sauvola বা
cv2.adaptiveThreshold(...MEAN_C..., 11, 2)। - Inverse mask: dark mark = white in mask — counting easier।
- Morphology cleanup:
- Open(3×3) — page texture noise dissolve।
- Close(5×5) — pencil mark-এর gap পূরণ (light pressure)।
- Bubble grid alignment: known template → ROI extract per bubble।
- Per-bubble fill ratio: bubble area ÷ filled pixels — > 30% = marked।
- Multi-mark check: এক question-এ একাধিক marked → flag।
- Confidence: very low (< 10%) বা ambiguous (40-60%) — manual review।
Where threshold/morphology shine:
- Adaptive threshold uneven scan handle।
- Closing — graphite-এর uneven streak নিরাপদে পূরণ।
- Opening — scan dust speckle ফেলে।
- Top-hat morphology — background pattern subtract।
Edge cases handle:
- Erased mark — partial fill — confidence threshold tune।
- Two marks crossed (corrected) — flag।
- Ink bleed — saturation থেকে detect।
- Sheet folded — perspective transform corner-এ extra check।
কেন CNN লাগে না?
- Bubble = standardized circle। Variability low।
- Lighting controlled (scanner) বা compensable।
- Speed critical — 1000 sheet/min processing।
- Deterministic — debug যোগ্য।
Production-এ যা যোগ:
- Aruco/QR code corner — robust deskew।
- Per-question confidence log — audit trail।
- Outlier student detect — pattern based।
- OCR for student ID region।
মূল উপলব্ধি: "Boring" classical pipeline — high-volume, mission-critical use case-এ আজও gold standard। Bangladesh-এর HSC, JSC examiners এই ধরনের system-ই ব্যবহার করে।
অনুশীলন
-
Otsu প্রয়োগ: একটি bimodal synthetic image (50% pixel=80, 50% pixel=200) বানান। Otsu কী T দেয়?
import cv2, numpy as np img = np.where(np.random.rand(100,100) < 0.5, 80, 200).astype(np.uint8) T, _ = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) print("Otsu T =", T) # ~140 (80 ও 200-এর মাঝামাঝি) -
Pipeline বানান: threshold → close → open এর একটি function লিখুন যা যেকোনো grayscale image-এ clean binary mask দেয়।
def clean_mask(gray, k=3): _, m = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) kernel = np.ones((k,k), np.uint8) m = cv2.morphologyEx(m, cv2.MORPH_OPEN, kernel) m = cv2.morphologyEx(m, cv2.MORPH_CLOSE, kernel) return m -
ভাবুন: একটি cross-shaped structuring element
cv2.MORPH_CROSSrectangular-এর তুলনায় কেমন behavior দেয়? কখন ব্যবহার?Cross kernel — শুধু horizontal ও vertical neighbor consider করে, diagonal না। Connectivity 4 (vs 8)। Thin line preserve-এ ভাল — যেমন road map-এ vector skeleton, fingerprint ridge। Rectangular kernel-এ rounded corner হয়, cross-এ sharper।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পাঠ ০৫ · Filter ও convolution kernel পরবর্তী পাঠ Morphology kernel বুঝেছেন — এবার convolution kernel।
- পাঠ ০৩ · OpenCV I/O আগের পাঠ যেখান থেকে শুরু — load করা ছবিতে এই operation।
- পাঠ ০৬ · Edge detection এগিয়ে Threshold-এর পরের গভীর pixel analysis।
- সব AI Courses দেখুন ABCL TECH Python, ML, DL, NLP, CV, GenAI, RL, MLOps — সব AI কোর্স একসাথে।