অধ্যায়Phase 1 · ফাউন্ডেশন
1.5 18 মিনিট পড়া

Image Processing-এর জন্য NumPy

Array slicing, broadcasting, dtype।

🎬 গল্প দিয়ে শুরু
OpenCV-এর প্রতিটি function-এর নিচে কী লুকিয়ে আছে জানেন? উত্তর — NumPy। ছবি যেহেতু matrix, এবং NumPy matrix নিয়ে কাজের জন্যই তৈরি, তাই NumPy ভালোভাবে না জানলে Computer Vision-এর গভীরে যাওয়া অসম্ভব।

কেন NumPy?

Python-এর সাধারণ list দিয়ে একটি 1920×1080 ছবিতে loop চালালে হাজার গুণ ধীর হবে। NumPy ভেতরে C-তে লেখা, এবং একসাথে পুরো array-তে operation চালায় (vectorization)। এটি Image Processing-কে real-time করে তোলে।

python
speed comparison
import numpy as np, time

py = list(range(1_000_000))
np_arr = np.arange(1_000_000)

t = time.time(); _ = [x*2 for x in py];        print("Python:", time.time()-t)
t = time.time(); _ = np_arr * 2;               print("NumPy :", time.time()-t)

Array তৈরি — basics

python
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])        # 2x3
zeros = np.zeros((100, 100), dtype=np.uint8) # কালো ছবি
ones  = np.ones((100, 100), dtype=np.uint8) * 255  # সাদা ছবি
rand  = np.random.randint(0, 256, (100, 100), dtype=np.uint8)  # noise

print(a.shape, a.dtype, a.ndim)
dtype খুব গুরুত্বপূর্ণ
OpenCV-তে ছবির default dtype uint8 (0–255)। কোনো operation করতে গিয়ে যদি ২৫৫-এর বেশি হয়ে যায়, তা wrap around করে ভুল ফল দেবে। তাই গাণিতিক operation আগে float-এ convert করুন, শেষে np.clip + astype(uint8)

Slicing — ছবির অংশ কেটে নেওয়া

NumPy slicing-এর সাহায্যে ছবির যেকোনো region access করা যায়। Syntax: array[y_start:y_end, x_start:x_end]

python
slicing.py
import cv2

img = cv2.imread("face.jpg")   # (H, W, 3)
H, W = img.shape[:2]

# মাঝখানের 200x200 region
cy, cx = H // 2, W // 2
center = img[cy-100:cy+100, cx-100:cx+100]

# শুধু উপরের অর্ধেক
top = img[: H // 2, :]

# Red channel-কে কালো করে দাও (BGR-এ index 2)
img[:, :, 2] = 0

cv2.imwrite("no_red.jpg", img)
লাইন-বাই-লাইন ব্যাখ্যা
img[y1:y2, x1:x2]
Rectangular region (ROI) cut। OpenCV/NumPy-এ আগে y, পরে x।
img[:, :, 2] = 0
সব pixel-এর Red channel একসাথে শূন্য — কোনো loop দরকার নেই।
:H//2
শুরু থেকে অর্ধেক পর্যন্ত — start বাদ দিলে ০ ধরা হয়।

Broadcasting — magic মুহূর্ত

আলাদা shape-এর দুটি array-তে NumPy automatic ভাবে operation চালাতে পারে। এটি “broadcasting”। একে ছাড়া image processing লেখা প্রায় অসম্ভব হয়ে যেত।

python
import numpy as np

img = np.random.randint(0, 256, (4, 4, 3), dtype=np.uint8)

# প্রতিটি pixel-এ ৫০ যোগ — ছবি brighter হবে
brighter = np.clip(img.astype(int) + 50, 0, 255).astype(np.uint8)

# শুধু Blue channel-এ ৩০ যোগ (shape mismatch হলেও কাজ করে)
img[:, :, 0] = np.clip(img[:, :, 0].astype(int) + 30, 0, 255)

# একটি 1D array (3,) প্রতিটি pixel-এ যোগ — R, G, B আলাদা scaling
scale = np.array([0.8, 1.0, 1.2])
img2  = np.clip(img * scale, 0, 255).astype(np.uint8)

Reshape, Transpose, Flatten

python
import numpy as np

a = np.arange(12)              # shape (12,)
m = a.reshape(3, 4)            # 3x4 matrix
t = m.T                        # transpose -> 4x3
flat = m.flatten()             # 1D

# ML model-এ অনেক সময় শেপ লাগে (1, H, W, C) — extra dim যোগ
img = np.zeros((224, 224, 3))
batch = img[np.newaxis, ...]   # (1, 224, 224, 3)

Boolean Masking — pixel-level filter

python
import cv2, numpy as np

img = cv2.imread("scene.jpg", cv2.IMREAD_GRAYSCALE)

# 100-এর নিচের সব pixel কালো, বাকি অপরিবর্তিত (simple threshold)
dark_mask = img < 100
img[dark_mask] = 0

# 200-এর উপরের সব pixel-এর গড় বের করা
bright_avg = img[img > 200].mean()
শক্তিশালী idiom
Mask + assignment হলো image processing-এর সবচেয়ে ব্যবহৃত pattern। Threshold, segmentation, ROI সব এর উপর দাঁড়িয়ে আছে।
প্র্যাকটিস টাস্ক
  1. একটি ছবির সব pixel-এ ৫০ যোগ করে brighter ছবি তৈরি করুন (clip সহ)।
  2. একটি color ছবি থেকে শুধু সবুজ-প্রধান অঞ্চলের mask বানান (G > R and G > B)।
  3. একটি 256×256 ছবিকে 4টি কোয়াড্রেন্টে ভাগ করে আলাদা ফাইলে save করুন।

সারসংক্ষেপ

  • NumPy = ছবির গাণিতিক ইঞ্জিন; loop নয়, vectorized operation।
  • Slicing দিয়ে ROI cut, channel access, region operation — সব সম্ভব।
  • Broadcasting আলাদা shape-এর array-কে একসাথে কাজ করায়।
  • uint8 overflow এড়াতে আগে float, শেষে clip + uint8।