OpenCV-এ ছবি পড়া ও লেখা
এই পাঠে যা শিখবেন
- OpenCV install ও basic flow
imreadflag — color, grayscale, unchanged- JPG, PNG, BMP, WebP ফরম্যাট কোনটা কখন
- Resize, crop ও basic save
১ · OpenCV কী?
OpenCVOpenCVOpen Source Computer Vision Library — ১৯৯৯-এ Intel-এ শুরু। C++ মূল, Python, Java, JavaScript binding। ২৫০০+ algorithm, প্রায় সব CV কাজের de-facto library। CV-র সবচেয়ে জনপ্রিয় library। ছবি পড়া-লেখা থেকে শুরু করে edge detection, face recognition — সবই আছে। Install:
pip install opencv-python
OpenCV-তে ছবি = NumPy ndarray। তাই NumPy যা কিছু পারে — slicing, broadcasting, vectorize — সবই OpenCV ছবিতে কাজ করে।
২ · imread — file থেকে tensor
cv2.imread(path, flag) — file load করে NumPy array দেয়। সফল না হলে None।
cv2.IMREAD_COLOR(default, 1) — BGR 3-channel। Alpha (transparency) discard।cv2.IMREAD_GRAYSCALE(0) — সরাসরি 1-channel grayscale। দ্রুত।cv2.IMREAD_UNCHANGED(-1) — সব channel + alpha (PNG-এ 4-channel)।
imread = file-এর pixel গুলো decoder দিয়ে decompress করে memory-তে আনা। JPEG-এর Huffman+DCT, PNG-এর zlib — সব internally।
৩ · imwrite — save
cv2.imwrite('out.jpg', img, [params])। Extension থেকে format ঠিক হয় — .jpg, .png, .bmp, .webp।
Quality control:
- JPEG:
[cv2.IMWRITE_JPEG_QUALITY, 95](0-100) - PNG:
[cv2.IMWRITE_PNG_COMPRESSION, 3](0-9, higher=smaller-but-slower) - WebP:
[cv2.IMWRITE_WEBP_QUALITY, 85]
৪ · ফরম্যাট তুলনা
| ফরম্যাট | Compression | Alpha | Best for |
|---|---|---|---|
| JPEG | Lossy | না | photo, web |
| PNG | Lossless | হ্যাঁ | graphic, mask |
| BMP | নেই | না | debug, raw |
| WebP | দু'টোই | হ্যাঁ | modern web |
| TIFF | Lossless | হ্যাঁ | scientific, medical |
৫ · imshow — display
Desktop Python: cv2.imshow('window', img) + cv2.waitKey(0)।
Notebook/Colab: matplotlib (plt.imshow) ব্যবহার করুন — কারণ headless environment-এ imshow error।
৬ · একটি ছবি load ও save
import cv2
import numpy as np
# একটি synthetic ছবি বানাই (যাতে file লাগবে না)
img = np.zeros((200, 300, 3), dtype=np.uint8)
img[:100, :150] = [255, 100, 50] # নীলাভ patch (BGR)
img[100:, 150:] = [50, 200, 100] # সবুজ patch
# JPG-তে save (quality 90)
cv2.imwrite('demo.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 90])
# আবার load করি
loaded = cv2.imread('demo.jpg')
print("Shape:", loaded.shape) # (200, 300, 3)
print("Dtype:", loaded.dtype) # uint8
print("ক্ষতিগ্রস্ত মান (lossy):", np.abs(img.astype(int) - loaded.astype(int)).mean())
৭ · Resize ও crop
import cv2
import numpy as np
img = np.random.randint(0, 256, (480, 640, 3), dtype=np.uint8)
print("Original:", img.shape)
# Resize — (width, height) order!
small = cv2.resize(img, (224, 224))
print("Resized:", small.shape) # (224, 224, 3)
# Aspect-ratio preserving resize
h, w = img.shape[:2]
target_w = 320
target_h = int(h * target_w / w)
fit = cv2.resize(img, (target_w, target_h))
print("Fit:", fit.shape)
# Crop — NumPy slicing
crop = img[100:300, 200:400]
print("Crop:", crop.shape) # (200, 200, 3)
cv2.resize-এ size = (width, height) — NumPy shape-এর উল্টো। মনে রাখার একটি common pitfall।
৮ · Interpolation method
Resize-এ interpolation:
cv2.INTER_NEAREST— দ্রুত, blocky। mask resize-এ আদর্শ।cv2.INTER_LINEAR(default) — bilinear, balanced।cv2.INTER_CUBIC— bicubic, smoother (slow)।cv2.INTER_AREA— shrinking-এ best, no aliasing।cv2.INTER_LANCZOS4— highest quality, slow।
৯ · Common pitfall
- imread None: path ভুল বা format unsupported। always check।
- BGR vs RGB: matplotlib-এ দেখাতে গেলে convert করুন।
- Path with non-ASCII: কিছু OpenCV build-এ Bangla path fail করে — use absolute ASCII path।
- EXIF rotation: imread auto-rotate করে না; PIL করে। ফলে phone photo upside down হতে পারে।
imread-এর return None check করুন — file missing, permission denied, বা corrupt হলে নীরবে None আসে। assertion দিন।
ভাবনার প্রশ্ন
প্র ০১ একটি 5MB JPG ছবি load করে আবার 95% quality-তে save করলাম। ফাইল আকার ৫MB থেকে ৪MB হলো। আবার load-save করলে আরো ছোট হবে? কেন?
এটি generation loss — JPEG-এর কুখ্যাত সমস্যা। প্রতিটি save-এ ছবি কিছুটা ক্ষতিগ্রস্ত হয়।
কেন আকার বদলায়?
- প্রথম save-এ original-এর কিছু high-frequency detail হারায় — DCT coefficient quantize হয়।
- পরের save-এ ক্ষতি হওয়া ছবি input — কিছু detail আগেই নেই, তাই compress easier।
- কয়েক generation পর — visible artifact (block, ringing, color fade)।
আকার আরও ছোট হয় কি?
- প্রথম কয়েকবার সামান্য ছোট হবে।
- পরে stable — কারণ "compressible" detail সব চলে গেছে।
- কিন্তু visual quality ক্রমাগত খারাপ — ১০ generation-এ ছবি প্রায় unrecognizable।
প্রমাণ — ৫০০ time round-trip:
img = cv2.imread('orig.jpg')
for i in range(500):
cv2.imwrite('temp.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 90])
img = cv2.imread('temp.jpg')
# এখন img প্রায় cartoonish, washed-out
Practical implication:
- Photo editing — PNG বা TIFF-এ intermediate save।
- Final export-ই JPEG।
- ML augmentation-এ JPEG re-save এড়ান — model JPEG artifact শিখে নিতে পারে।
- Forensics — JPEG ghost detection generation analysis দিয়ে edit prove করে।
মূল উপলব্ধি: Lossy = irreversible। Source-of-truth কখনো overwrite করবেন না — backup archival format।
প্র ০২ OpenCV-তে ছবি resize করার সময় INTER_AREA কেন shrinking-এ best, কিন্তু enlarging-এ INTER_CUBIC? Aliasing কী ঘটছে?
এটি signal processing-এর একটি deep concept। Image resize = sampling + reconstruction।
Shrinking (downsample) — যা ঘটে:
- 1000×1000 → 100×100 — প্রতি ১০ pixel-এ ১টি পিক্সেল-এ মেপ করতে হয়।
- Aliasing: high-frequency detail (ছোট pattern) misrepresent — moiré pattern, jagged edge।
- Nyquist-এর সূত্র: target frequency-র অন্তত দ্বিগুণ rate-এ sample চাই।
INTER_AREA-এর কৌশল:
- প্রতিটি output pixel = source-এর corresponding rectangular area-এর গড়।
- মূলত box filter — natural anti-aliasing।
- Detail হারায় কিন্তু moiré আসে না।
Enlarging (upsample) — যা ঘটে:
- 100×100 → 1000×1000 — মাঝখানে পিক্সেল "তৈরি" করতে হয়।
- সমস্যা ভিন্ন — aliasing না, blurriness।
INTER_CUBIC vs INTER_LINEAR:
- Linear: 4 neighbor-এর weighted avg। দ্রুত কিন্তু slightly blurry।
- Cubic: 16 neighbor + cubic spline। edge-এ sharper, but slow ও কিছু overshoot (halo) হতে পারে।
- Lanczos: 64+ neighbor, sinc-based। highest quality।
Mask/label resize:
- Segmentation mask-এ
INTER_NEARESTব্যবহার — অন্যথা class label interpolate হয়ে invalid value। - e.g. class 1 ও 2-এর মাঝে 1.5 — যা কোনো class না।
মূল উপলব্ধি: Resize trivial না — sampling theory-র গভীরে। ML pipeline-এ wrong interpolation ৫% accuracy-র পার্থক্য আনতে পারে।
প্র ০৩ একটি ১০,০০০ ছবির dataset-এ training করতে গিয়ে I/O bottleneck — disk read slow। কী কী strategy আছে?
DL-এর সবচেয়ে underrated bottleneck — disk I/O। GPU 99% idle হয়ে বসে থাকে যখন data loader slow।
(১) Sequential read optimize:
- HDF5/LMDB/TFRecord: ১০,০০০ ছোট file-এর বদলে এক বড় container। random seek 10x faster।
- WebDataset: tar archive-এ shards — sequential streaming।
(২) Caching:
- প্রথম epoch-এ disk read, RAM-এ cache। পরের epoch RAM থেকে।
- Linux page cache automatic — যথেষ্ট RAM থাকলে।
- Decoded ছবি cache — JPEG decode CPU-heavy।
(৩) Parallel loading:
- PyTorch
num_workers=8— multi-process data load। - GPU train করার সময় CPU পরের batch prepare।
pin_memory=True— pinned memory → GPU transfer fast।
(৪) Storage choice:
- HDD → SSD: 10× speedup typically।
- SSD → NVMe: 3-5× more।
- Network FS এড়ান training-এ — local copy।
(৫) On-the-fly decoding:
- NVIDIA DALI: GPU-decoded JPEG — CPU bypass।
- libjpeg-turbo: 2× faster than default libjpeg।
- Pillow-SIMD: PIL-এর SIMD-optimized fork।
(৬) Data format:
- Resize ১ বার — একবার preprocess, পুনরায় না।
- JPEG quality 80 যথেষ্ট — file ছোট, decode fast।
- Critical task: lossless WebP বা PNG।
Profiling rule: GPU utilization 70%-র নিচে হলে — I/O bottleneck। Optimize আগে measure।
মূল উপলব্ধি: "Bigger model" নয়, "faster pipeline" — অনেকসময় বড় গেইন। MLOps-এর core skill।
প্র ০৪ একটি phone থেকে নেওয়া ছবি OpenCV-তে load করলে দেখলেন — orientation rotated (পাশে শুয়ে আছে)। কী হচ্ছে, কীভাবে fix?
এটি EXIF orientation-এর problem। প্রায় সব phone camera ছবি তোলে landscape sensor-এ — orientation metadata-তে store।
EXIF কী?
- Exchangeable Image File Format — JPEG-এর header-এ metadata।
- Camera model, GPS, exposure, ও orientation tag (1-8)।
- Tag 1 = normal, 6 = 90° CW rotate, 8 = 90° CCW, 3 = 180°।
সমস্যা OpenCV-তে:
- OpenCV
imreadEXIF orientation respect করে না। - Pixel data যেমন sensor-এ ছিল তেমনই load হয় — phone-এর "vertical" ছবি horizontal।
- Phone gallery, Pillow, browser auto-rotate দেখায় বলে user বোঝে না।
সমাধান (Pillow ব্যবহার):
from PIL import Image, ImageOps
import numpy as np
import cv2
pil_img = Image.open('phone_photo.jpg')
pil_img = ImageOps.exif_transpose(pil_img) # auto rotate
img_rgb = np.array(pil_img)
img_bgr = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR)
সমাধান (manual EXIF read):
import piexif
exif = piexif.load('photo.jpg')
orientation = exif['0th'].get(piexif.ImageIFD.Orientation, 1)
# তারপর cv2.rotate() করে correct
OpenCV 4.7+: cv2.imread(path, cv2.IMREAD_IGNORE_ORIENTATION | cv2.IMREAD_COLOR) — opposite, EXIF apply default 4.7+ থেকে। Version-ভেদে behavior ভিন্ন!
Production checklist:
- User upload-এ orientation normalize করুন server-side।
- Database-এ storage-এর আগে EXIF strip + rotate apply।
- ML inference-এ orientation না জানলে — rotation augmentation দিয়ে training।
মূল উপলব্ধি: Real-world image data noisy — metadata, encoding, orientation সবই inconsistent। CV engineer-এর কাজ pipeline-এ এই সব handle করা।
অনুশীলন
-
Quality experiment: একটি ছবি quality 10, 50, 95-এ JPG save করুন। File size ও visual difference compare করুন।
for q in [10, 50, 95]: cv2.imwrite(f'q{q}.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, q]) import os for q in [10, 50, 95]: print(q, os.path.getsize(f'q{q}.jpg'), 'bytes')সাধারণত 95 → 50 → 10 আকার ১০x ছোট হয়, কিন্তু q=10 এ visible block artifact।
-
Aspect-ratio safe resize: যেকোনো size-এর ছবিকে max dimension=512 রেখে resize করার একটি function লিখুন।
def resize_max(img, max_dim=512): h, w = img.shape[:2] scale = max_dim / max(h, w) if scale >= 1: return img new_w, new_h = int(w*scale), int(h*scale) return cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_AREA) -
ভাবুন: একটি AI medical app-এ DICOM (16-bit) X-ray image। JPEG-এ save করলে কী সমস্যা?
JPEG 8-bit only — 16→8 bit conversion-এ subtle tissue contrast হারায়। Lossy compression cancer detect-এর critical region damage করতে পারে। Medical-এ DICOM বা lossless TIFF-ই standard।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পাঠ ০৪ · Threshold ও morphology পরবর্তী পাঠ Load করা ছবিতে binary mask তৈরি ও cleanup।
- পাঠ ০২ · Color spaces আগের পাঠ কোন space-এ load করবেন বুঝতে।
- পাঠ ০৮ · Image augmentation এগিয়ে I/O ও preprocessing pipeline-এর বাকি অংশ।
- সব AI Courses দেখুন ABCL TECH Python, ML, DL, NLP, CV, GenAI, RL, MLOps — সব AI কোর্স একসাথে।