ছবি কীভাবে tensor হয় — পিক্সেল ও চ্যানেল
এই পাঠে যা শিখবেন
- পিক্সেল কী — একটি ছবির ক্ষুদ্রতম একক
- Grayscale বনাম RGB — চ্যানেলের ধারণা
- একটি ছবির shape কীভাবে পড়তে হয় — (H, W, C)
- NumPy দিয়ে ছবিকে tensor হিসেবে ব্যবহার
১ · একটি ছবি আসলে কী?
আপনি একটি বিড়ালের ছবি দেখলে সাথে সাথেই বুঝে যান — এটি বিড়াল। কিন্তু কম্পিউটারের চোখে ছবি বলে কিছু নেই — শুধু সংখ্যা। একটি ছবি হলো পিক্সেলPixel"Picture Element"-এর সংক্ষেপ। ছবির ক্ষুদ্রতম একক — একটি ছোট চৌকো ঘর যাতে একটি রঙ বা brightness বসে। ছবির resolution মানে কত পিক্সেল আছে।-এর গ্রিড। প্রতিটি পিক্সেল একটি সংখ্যা — সাধারণত 0 (কালো) থেকে 255 (সাদা) পর্যন্ত।
ছবি = সংখ্যার সাজানো গ্রিড। AI ছবি "চোখে" দেখে না — প্রতিটি পিক্সেলের সংখ্যা থেকে বুঝে। তাই Computer Vision-এর প্রথম কাজ — ছবিকে tensorTensorবহু-মাত্রিক সংখ্যার অ্যারে। ১-D = vector, ২-D = matrix, ৩-D ও তার বেশি = tensor। NumPy/PyTorch-এর মূল ডেটা-কাঠামো।-এ রূপান্তর।
২ · Grayscale ছবি — ২-D matrix
একটি সাদা-কালো ছবি হলো ২-D matrix। প্রতিটি ঘরে একটি সংখ্যা। 0 মানে কালো, 255 মানে সাদা, মাঝের সংখ্যাগুলো ধূসরের নানা ছায়া।
একটি ছোট 3×3 grayscale ছবি কেমন:
$$\text{ছবি} = \begin{bmatrix} 0 & 128 & 255 \\ 64 & 192 & 32 \\ 200 & 50 & 100 \end{bmatrix}$$
এর shape = $(3, 3)$ — মানে height=৩, width=৩।
৩ · RGB ছবি — ৩-D tensor
রঙিন ছবি একটু জটিল — কিন্তু একই ধারণা। প্রতিটি পিক্সেলে এক সংখ্যা না — তিনটি সংখ্যা: R (Red), G (Green), B (Blue)। একে বলে চ্যানেল।
একটি RGB ছবির shape = $(H, W, 3)$ — যেখানে $H$ = height, $W$ = width, ৩ = চ্যানেল সংখ্যা। যেমন একটি 224×224 RGB ছবির shape = $(224, 224, 3)$।
একটি পিক্সেল কেমন? $(255, 0, 0)$ মানে purely red। $(0, 255, 0)$ — green। $(255, 255, 255)$ — সাদা (সব চ্যানেল full)। $(0, 0, 0)$ — কালো (সব চ্যানেল zero)।
৪ · একটি ছবির আকার — গণিতে
$$\text{মোট পিক্সেল} = H \times W \times C$$
যেমন একটি 224×224 RGB ছবি = $224 \times 224 \times 3 = 150{,}528$ সংখ্যা। প্রতিটি 8-bit (1 byte) হলে ছবির মেমোরি প্রায় 150 KB।
৫ · Channel-first বনাম channel-last
দু'টি convention জনপ্রিয়:
- Channel-last (HWC): shape = $(H, W, C)$ — TensorFlow ও OpenCV ব্যবহার করে।
- Channel-first (CHW): shape = $(C, H, W)$ — PyTorch ব্যবহার করে।
একটি library থেকে অন্যটিতে ছবি পাঠাতে গেলে এই অর্ডার বদলাতে হয় — ভুললে shape mismatch error আসবে।
৬ · Pixel value এবং AI
AI মডেলে ছবি ঢুকানোর আগে সাধারণত pixel value ০–১ এ normalizeNormalizationসংখ্যাগুলোকে একটি ছোট পরিসরে আনা — সাধারণত [0, 1] বা [-1, 1]। AI training-এ gradient stable রাখার জন্য জরুরি। করা হয়:
$$\text{normalized} = \frac{\text{pixel}}{255.0}$$
কারণ — নিউরাল নেটওয়ার্কে বড় সংখ্যা gradient explosion ঘটায়। 0–255 এর জায়গায় 0–1 ব্যবহার training stable রাখে।
৭ · NumPy দিয়ে একটি ছবি
আসুন একটি ছোট grayscale ছবি বানিয়ে দেখি — শুধু NumPy দিয়ে।
import numpy as np
# 3x3 grayscale ছবি — হাতে বানানো
img_gray = np.array([
[ 0, 128, 255],
[ 64, 192, 32],
[200, 50, 100]
], dtype=np.uint8)
print("shape:", img_gray.shape) # (3, 3)
print("dtype:", img_gray.dtype) # uint8
print("min:", img_gray.min(), "max:", img_gray.max())
shape: (3, 3) — height=৩, width=৩। dtype: uint8 — unsigned 8-bit integer, যা 0–255 সংখ্যা ধরতে পারে।
৮ · একটি ছোট RGB ছবি বানানো
import numpy as np
# 2x2 RGB ছবি — চারটি পিক্সেল, প্রতিটি 3-channel
img_rgb = np.array([
[[255, 0, 0], [ 0, 255, 0]], # লাল, সবুজ
[[ 0, 0, 255], [255, 255, 255]], # নীল, সাদা
], dtype=np.uint8)
print("shape:", img_rgb.shape) # (2, 2, 3)
print("পিক্সেল [0,0]:", img_rgb[0, 0]) # [255 0 0] — লাল
print("শুধু R channel:")
print(img_rgb[:, :, 0]) # সব পিক্সেলের R মান
img_rgb[:, :, 0] — সব পিক্সেলের শুধু Red চ্যানেল বের করে। AI-তে চ্যানেল আলাদা করে কাজ করা সাধারণ।
৯ · বাস্তব AI-তে ছবির shape
- ImageNet: 224×224×3 — সবচেয়ে জনপ্রিয় size।
- CIFAR-10: 32×32×3 — ছোট ছবি, দ্রুত training।
- MNIST: 28×28×1 — grayscale digit।
- HD photo: 1920×1080×3 ≈ 6.2 million সংখ্যা।
- Batch: AI সাধারণত একসাথে অনেক ছবি দেখে — shape হয় $(N, H, W, C)$ যেখানে $N$ = batch size।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ কেন একটি ছবি 8-bit (0–255) এ store হয়, 16-bit বা 32-bit-এ না? এর সুবিধা ও সীমাবদ্ধতা কী?
মানুষের চোখ একটি চ্যানেলে প্রায় ১০০-২০০ ভিন্ন brightness level আলাদা করতে পারে। 8-bit (২৫৬ level) — চোখের ক্ষমতার চেয়ে সামান্য বেশি — তাই দেখতে স্বাভাবিক।
৮-bit-এর সুবিধা:
- মেমোরি: 4MP RGB ছবি 8-bit-এ ১২MB, 16-bit-এ ২৪MB। ওয়েব, মোবাইল ও ডেটাসেট-এর জন্য বিশাল সাশ্রয়।
- হার্ডওয়্যার: বেশিরভাগ camera sensor, display ও GPU 8-bit native — দ্রুত প্রক্রিয়াকরণ।
- JPEG/PNG compatibility: জনপ্রিয় ফরম্যাট 8-bit-কেই ধরে।
সীমাবদ্ধতা:
- Banding: মসৃণ gradient-এ ধাপে-ধাপে ভাগ দেখা যায় (যেমন আকাশের ছবিতে)।
- HDR loss: খুব উজ্জ্বল ও খুব অন্ধকার একই সাথে capture কঠিন।
- Medical imaging: CT, MRI সাধারণত 12-bit বা 16-bit — ক্ষুদ্র tissue পার্থক্য ধরতে।
- Astronomy/scientific: 16-bit বা float32 — খুব ক্ষীণ আলো ধরা।
আধুনিক বিকল্প:
- HDR (10-bit per channel): Dolby Vision, HDR10 — gaming ও premium display।
- RAW (12-14 bit): DSLR camera — post-processing flexibility-এর জন্য।
- float32 in AI: training-এর সময় normalize করে float-এ কাজ করা হয় — gradient stable রাখতে।
মূল উপলব্ধি: 8-bit একটি engineering compromise — মানব visual system-এর সীমা ও hardware সক্ষমতার balance। AI-তে আমরা একে normalize করে float-এ rotate করি।
প্র ০২ একটি 1MP RGB ছবি (1000×1000×3) AI-তে দেওয়া হলে — flatten করলে ৩,০০০,০০০-মাত্রিক vector। এত বড় vector কি Fully Connected Network-এ সরাসরি দেওয়া যায়? কেন CNN দরকার?
এই প্রশ্নের উত্তরই Computer Vision-এ CNN-এর জন্ম দিয়েছিল। আগের যুগে (LeCun-এর LeNet-এর আগে) ছবি flatten করে MLP-তে দেওয়া হতো — সমস্যা ছিল বিরাট।
সরাসরি FCN-এ দেওয়ার সমস্যা:
- Parameter explosion: 3M input × 1000 hidden neurons = 3 billion parameters শুধু প্রথম layer-এ। GPU memory-তে ধরে না।
- Training data: এত parameter fit করতে শতকোটি ছবি লাগে — যা পাওয়া অসম্ভব।
- Spatial structure হারানো: পাশাপাশি পিক্সেল-এর সম্পর্ক flatten-এ মিশে যায়। বিড়ালের চোখ কোথায় সেটা matter করে।
- Translation invariance নেই: বিড়াল উপরে থাকলেও আর নিচে থাকলেও একই — কিন্তু flatten-এ সেটা ভিন্ন vector।
CNN-এর সমাধান:
- Local connectivity: প্রতিটি neuron শুধু ছোট patch (যেমন 3×3) দেখে — পুরো ছবি নয়।
- Weight sharing: একই kernel পুরো ছবিতে slide করে — parameter কম।
- Translation equivariance: বস্তু যেখানেই থাকুক, একই kernel detect করে।
- Hierarchical features: প্রথম layer edges, পরে textures, তারপর objects — একদম biology-র visual cortex-এর মতো।
সংখ্যায় তুলনা:
- FCN (3M → 1000): 3 billion parameters।
- CNN (3×3×3 kernel × 64 filters): মাত্র ১,৭২৮ parameters — পুরো ছবিতে কাজ করে।
- প্রায় ১.৭ million গুণ কম!
মূল উপলব্ধি: ছবির 2D structure preserve করা ও weight sharing — এই দু'টো ধারণা CV-কে scalable করেছে। CNN ছাড়া আজকের ImageNet, YOLO, Face Recognition — কিছুই হতো না।
প্র ০৩ OpenCV-তে একটি ছবি load করলে শুনেছেন BGR অর্ডারে আসে — RGB না। কেন এই অদ্ভুত choice? এতে কী সমস্যা হয়?
এটি Computer Vision-এর একটি কুখ্যাত quirk। শুরুতে অনেকের ছবি "নীলাভ" দেখায় — কারণ এই BGR/RGB confusion।
কেন BGR?
- OpenCV ১৯৯৯-এ Intel-এ শুরু — তখনকার camera ও Windows BMP ফরম্যাট BGR ব্যবহার করত (little-endian RGB-র memory layout)।
- এই historical decision আজও চলছে — backwards compatibility-র কারণে।
- Internally — Blue first byte, Green second, Red third — যা CPU-এ একটু দ্রুত ছিল সেই যুগে।
সমস্যা যা হয়:
- Matplotlib (RGB ধরে) এ সরাসরি দেখালে — লাল ও নীল উল্টে যায়। গাঢ় লাল গোলাপ দেখাবে নীল।
- PIL/Pillow, TensorFlow, PyTorch — সবই RGB। OpenCV থেকে এদের পাঠানোর আগে convert করতে হয়।
- Color-based detection (যেমন red car detect) — wrong channel-এ search করলে ফল ভুল।
সমাধান:
img = cv2.imread('photo.jpg') # BGR
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img_rgb) # ঠিকঠাক দেখাবে
অন্যান্য library-র convention:
- OpenCV: BGR (channel-last)।
- PIL, Matplotlib, TF: RGB (channel-last)।
- PyTorch: RGB (channel-first)।
- Skimage: RGB।
- DICOM (medical): grayscale বা special encoding।
মূল উপলব্ধি: Library-র convention জেনে রাখা CV engineer-এর duty। প্রথম bug প্রায়ই color channel inversion। Production code-এ সবসময় explicit convert করুন।
প্র ০৪ একটি AI মডেলে ছবি ঢুকানোর আগে আমরা pixel value 0–1 এ normalize করি। কিন্তু কখনও ImageNet mean-std subtract করি, কখনও just /255। কখন কোনটা?
Normalization choice training stability ও accuracy দু'টোতেই প্রভাব ফেলে। ভুল normalization ভাল মডেলকেও ১০-২০% accuracy কমিয়ে দিতে পারে।
(১) /255 (Min-Max scaling):
- সব pixel 0–1 এ আসে।
- Scratch থেকে train করলে — সাধারণত যথেষ্ট।
- সরল, predictable, GPU-friendly।
- ছোট dataset (CIFAR-10) ও simple architecture-এ ভাল কাজ করে।
(২) ImageNet mean-std (Z-score):
- $x' = (x/255 - \mu) / \sigma$ যেখানে $\mu = [0.485, 0.456, 0.406]$, $\sigma = [0.229, 0.224, 0.225]$।
- Pretrained ResNet, VGG, EfficientNet ব্যবহার করলে — অবশ্যই ব্যবহার করতে হবে। কারণ মডেলটি এই distribution-এ train হয়েছে।
- Transfer learning-এ এটাই default।
(৩) [-1, 1] scaling:
- $x' = (x/255) \times 2 - 1$।
- GAN, Stable Diffusion, কিছু Vision Transformer এ standard।
- Tanh activation-এর সাথে mathematical সামঞ্জস্য।
(৪) Custom dataset mean-std:
- Medical imaging, satellite — ImageNet mean-std অপ্রাসঙ্গিক।
- নিজের ডেটাসেটের mean-std হিসাব করে use করুন।
সাধারণ ভুল:
- Pretrained মডেল ব্যবহারে /255-এ থামা — ১০% accuracy drop।
- Inference-এ training-এর normalization apply না করা — ছবি unrecognizable।
- Train ও validation-এ ভিন্ন normalization — silent bug।
Production tip: Normalization preprocessing pipeline-এর প্রথম step হিসেবে dataset class-এ লিখুন। Inference-এর সময় একই function ব্যবহার — train/test skew এড়াতে।
মূল উপলব্ধি: "Normalize করেছি" — যথেষ্ট না। কোন strategy কেন — বুঝতে হবে। মডেলের training distribution match করানো সর্বদা priority।
অনুশীলন
-
Shape হিসাব করুন:
- একটি 1080p RGB ভিডিও frame-এর shape ও মোট পিক্সেল কত?
- একটি 4K (3840×2160) RGBA (4-channel) ছবির shape ও মেমোরি (8-bit) কত?
- ৩২ ছবির একটি batch — প্রতিটি 224×224×3 — shape কী?
- 1080p = 1920×1080×3, shape = $(1080, 1920, 3)$, মোট পিক্সেল = $1920 \times 1080 \times 3 = 6{,}220{,}800$।
- 4K RGBA: shape = $(2160, 3840, 4)$, মেমোরি = $3840 \times 2160 \times 4 \approx 33$ MB।
- Batch shape = $(32, 224, 224, 3)$ — channel-last। PyTorch-এ $(32, 3, 224, 224)$।
-
NumPy-তে চেষ্টা: একটি 5×5 grayscale ছবি বানান যেখানে কেন্দ্রের pixel সবচেয়ে উজ্জ্বল (255) ও কোণায় কালো (0) — gradient pattern।
import numpy as np img = np.zeros((5, 5), dtype=np.uint8) center = (2, 2) for i in range(5): for j in range(5): dist = max(abs(i - center[0]), abs(j - center[1])) img[i, j] = 255 - (dist * 64) print(img) # কেন্দ্রে 255, ১ ঘর দূরে 191, ২ ঘর দূরে 127 -
ভাবুন: একটি ছবি 0–255-এর বদলে -128 থেকে +127 (signed int8) এ store করলে কী সুবিধা/অসুবিধা হবে?
সুবিধা:
- Mean প্রায় 0 — neural network-এ symmetric activation-এর সাথে fit।
- Subtract operation সরাসরি; centered data → faster convergence।
অসুবিধা:
- Display/storage standard (PNG, JPEG) সাধারণত unsigned।
- Conversion overhead প্রতিটি I/O-তে।
- Human intuition: 0=কালো, 255=সাদা — সবার মুখস্থ।
তাই storage-এ uint8, training-এ float-এ centered করা — best of both worlds।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পাঠ ০২ · RGB, HSV, grayscale — color space পরবর্তী পাঠ পিক্সেল বুঝেছেন — এবার রঙের ভাষা ও কেন HSV কাজ করে।
- AI Foundations · ভেক্টর সম্পর্কিত ছবি = উচ্চ-মাত্রিক vector — vector mathematics দেখুন।
- পাঠ ০৩ · OpenCV-এ ছবি পড়া ও লেখা এগিয়ে এবার আসল ছবি load ও save — OpenCV হাতে নিন।
- সব AI Courses দেখুন ABCL TECH Python, ML, DL, NLP, CV, GenAI, RL, MLOps — সব AI কোর্স একসাথে।