รูปปกบทความ

1. 🎯 ตอนที่ 7: เจาะลึกโครงสร้างภาพ - ขนาด, จำนวนช่องสี และความลึก (Size, Channels, Depth)

2. 📖 เปิดฉาก (The Hook)

น้องๆ เคยเจอปัญหาแบบนี้ไหมครับ? เขียนโค้ดดึงภาพจากกล้องมาซะดิบดี กะว่าจะเอาภาพสองภาพมาลบกันเพื่อหาของที่ขยับบนสายพาน (Motion Detection) หรือกะจะส่งภาพเข้าไปรันในโมเดล Deep Learning ปรากฏว่าพอกดรันปุ๊บ โปรแกรมเด้งหน้าจอแครช (Crash) แจ้งเตือน Error ตัวแดงเถือก หรือบางทีรันผ่าน แต่พอใช้ imshow โชว์ภาพออกมา ภาพดันกลายเป็นสีขาวโพลนทั้งจอซะงั้น!

ปัญหาคลาสสิกนี้ไม่ได้เกิดจากอัลกอริทึมที่ผิดพลาดครับ แต่เกิดจากการที่เรา “ไม่เข้าใจโครงสร้างข้อมูลของภาพ” อย่างถ่องแท้ ในวงการ Computer Vision ถ้าเราเอาน้ำหนึ่งแกลลอนไปเทใส่แก้วน้ำใบเล็กๆ ข้อมูลมันก็ล้น (Overflow) ใช่ไหมครับ? วันนี้พี่จะมาชงกาแฟ แล้วพาน้องๆ มุดลงไปดูไส้ในของคลาส cv::Mat ว่าตาราง Excel ขนาดยักษ์นี้ มันบอก “ขนาด” “ความหนาของสี” และ “ความจุของแต่ละพิกเซล” ให้เราทราบได้อย่างไร รับรองว่าเข้าใจเรื่องนี้แล้ว บั๊กกวนใจจะหายไปเกินครึ่งครับ!

3. 🧠 แก่นวิชา (Core Concepts)

ใน OpenCV ภาพทุกภาพจะถูกเก็บในรูปแบบของ cv::Mat (Image Matrix) ซึ่งมีคุณสมบัติ (Properties) หลักๆ ที่วิศวกรสาย Vision ต้องเช็กให้ชัวร์ก่อนนำไปประมวลผลเสมอ ได้แก่,:

  • 1. ขนาดของภาพ (Dimensions: rows และ cols)

    • rows (จำนวนแถว): คือ “ความสูง” (Height) ของภาพในหน่วยพิกเซล
    • cols (จำนวนคอลัมน์): คือ “ความกว้าง” (Width) ของภาพในหน่วยพิกเซล
    • เปรียบเทียบ: เหมือนเรากางตาราง Excel ถ้าภาพขนาด 1920x1080 ก็คือมี 1080 แถว และ 1920 คอลัมน์ครับ
  • 2. จำนวนช่องสี (Channels: channels())

    • ถ้าภาพเป็น Grayscale (ขาวดำ) จะมีเพียง 1 Channel (เก็บแค่ค่าความสว่าง),.
    • ถ้าภาพเป็นสีมาตรฐาน จะมี 3 Channels (ใน OpenCV คือ B-G-R เรียงตามลำดับ),.
    • ถ้าภาพโปร่งใส (มี Alpha channel) จะมี 4 Channels (BGRA).
    • เปรียบเทียบ: สำหรับภาพสี ให้จินตนาการว่าเราเอาตาราง Excel 3 แผ่น (แผ่นสีน้ำเงิน สีเขียว สีแดง) มาวางซ้อนทับกันครับ
  • 3. ความลึกของข้อมูล (Depth / Data Type: depth()) นี่คือจุดที่คนตกม้าตายเยอะที่สุด! depth() คือตัวบอกว่า “ใน 1 ช่องพิกเซล เราใช้พื้นที่หน่วยความจำเท่าไหร่ในการเก็บตัวเลข” ซึ่งแบ่งเป็น 3 กลุ่มหลักๆ ที่เจอบ่อย:

    • 8-bit Unsigned (CV_8U): เก็บตัวเลขจำนวนเต็มบวกได้ตั้งแต่ 0 ถึง 255,. นี่คือรูปแบบมาตรฐานของภาพทั่วไป (JPG, PNG) ที่เราโหลดเข้ามาครับ
    • 16-bit Unsigned (CV_16U / CV_16S): เก็บตัวเลขได้ตั้งแต่ 0 ถึง 65,535. มักใช้กับกล้องอุตสาหกรรม (Machine Vision Cameras), กล้องการแพทย์ หรือกล้อง Depth Sensor ที่ต้องการความละเอียดของแสง (Dynamic Range) สูงๆ
    • 32-bit Float (CV_32F): เก็บตัวเลขทศนิยม นิยมปรับสเกลให้อยู่ในช่วง 0.0 ถึง 1.0,. ทำไมเราต้องใช้ทศนิยม? เพราะเวลาเราเอาภาพไปคูณ หาร หรือหาค่าเฉลี่ยทางคณิตศาสตร์ (เช่น การทำ Filter, การป้อนเข้า Neural Networks) ถ้าใช้แบบ 8-bit ค่ามันจะล้น 255 หรือปัดเศษทิ้งจนข้อมูลเพี้ยนครับ! เราเลยต้องแปลงเป็น Float ก่อนคำนวณเสมอ,
  • รหัสลับของ OpenCV (Type Macro): เวลาเราประกาศสร้าง cv::Mat เราจะใช้ Macro ที่รวม Depth และ Channels เข้าด้วยกัน เช่น CV_8UC3,

    • 8U = 8-bit Unsigned Integer
    • C3 = 3 Channels (สี BGR)
    • ถ้าเป็น CV_32FC1 ก็จะหมายถึงภาพทศนิยม 32-bit แบบ 1 Channel (Grayscale) ครับ
รูปประกอบ

4. 💻 ร่ายมนต์คำสั่ง (Show me the Code)

เรามาดูตัวอย่างโค้ด C++ ในการตรวจสอบคุณสมบัติของภาพ และการแปลงชนิดข้อมูลจาก 8-bit ไปเป็น 32-bit Float เพื่อเตรียมความพร้อมสำหรับการทำ Machine Learning กันครับ

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    // 1. โหลดภาพสีต้นฉบับเข้ามา (ค่าเริ่มต้นเป็น CV_8UC3)
    Mat img = imread("factory_defect.jpg", IMREAD_COLOR);
    if(img.empty()) return -1;

    // 2. ดึงคุณสมบัติ (Properties) พื้นฐานออกมาดู
    cout << "--- Image Properties ---" << endl;
    cout << "Width  (Cols) : " << img.cols << " pixels" << endl;
    cout << "Height (Rows) : " << img.rows << " pixels" << endl;
    cout << "Channels      : " << img.channels() << " (BGR)" << endl;
    
    // คืนค่าเป็นรหัสตัวเลข (เช่น 0 คือ CV_8U, 5 คือ CV_32F)
    cout << "Depth Code    : " << img.depth() << endl; 

    // 3. ปัญหา: ถ้าเราเอา img ไปคูณ 2.5 ค่าพิกเซลที่เกิน 255 จะถูกตัดทิ้ง (Overflow)
    // ทางแก้: แปลงภาพเป็น 32-bit Float (CV_32F) 
    Mat imgFloat;
    // แปลงประเภทข้อมูล พร้อมกับหาร 255.0 เพื่อบีบสเกลให้อยู่ในช่วง 0.0 - 1.0 (Normalization)
    img.convertTo(imgFloat, CV_32FC3, 1.0 / 255.0); 

    // 4. ลองเช็กค่า Properties ของภาพใหม่ดู
    cout << "\n--- Converted Image ---" << endl;
    cout << "New Channels  : " << imgFloat.channels() << endl;
    cout << "New Depth Code: " << imgFloat.depth() << " (CV_32F)" << endl;

    // 5. แสดงผลภาพ
    // ฟังก์ชัน imshow ฉลาดพอที่จะรู้ว่าถ้าเป็น Float (0.0-1.0) มันจะคูณ 255 กลับให้ตอนโชว์จอ
    imshow("Original 8-bit", img);
    imshow("Normalized 32-bit Float", imgFloat);
    waitKey(0);

    return 0;
}

5. 🛡️ เคล็ดลับจากคัมภีร์ลับ (Under the Hood / Pro-Tips)

  • อันตรายจากการสุ่มสี่สุ่มห้าคูณเลข (Data Type Mismatch): ปัญหาที่ทำให้แอปพลิเคชันพังบ่อยที่สุดคือการป้อน Mat ผิด Type เข้าไปในฟังก์ชันครับ ตัวอย่างเช่น ฟังก์ชันบางตัวใน OpenCV หรือโมเดล Deep Learning ต้องการภาพแบบ CV_32F เท่านั้น ถ้าน้องๆ โยน CV_8U เข้าไป โปรแกรมจะพ่น cv::Exception แล้วดับทันที ดังนั้นการเช็ก img.type() หรือ img.depth() ก่อนประมวลผลจึงเป็นเรื่องสำคัญมาก
  • กับดักของฟังก์ชัน imshow กับภาพทศนิยม: จำไว้เสมอครับว่า ถ้าเราโชว์ภาพ 8-bit (CV_8U) ตัว imshow จะวาดภาพตามปกติ (0-255) แต่ถ้าเราโยนภาพทศนิยม (CV_32F) ให้มันวาด มันจะทึกทักเอาเองว่าค่าในนั้นต้องอยู่ระหว่าง 0.0 ถึง 1.0 แล้วมันจะเอาไปคูณ 255 ให้เองตอนวาดออกจอ, ถ้าน้องๆ แปลงภาพเป็น CV_32F แต่ลืมหารสเกล (คือค่ายังเป็น 0-255 เท่าเดิม) ภาพที่โชว์ออกมาจะกลายเป็นสีขาวโพลนแสบตาไปทั้งหน้าต่างเลยครับ!

6. 🏁 บทสรุป (To be continued…)

การเข้าใจเรื่อง Size, Channels และที่สำคัญที่สุดคือ Depth (Data Types) เป็นรากฐานที่สำคัญมากในการเขียน Computer Vision Pipeline ระดับอุตสาหกรรม เพราะมันช่วยให้เรารู้ว่าหน่วยความจำเราเก็บข้อมูลแบบไหน และต้องระวังเรื่องการคำนวณทางคณิตศาสตร์อย่างไรไม่ให้ข้อมูลพิกเซลสูญหาย

เมื่อเราเข้าใจโครงสร้างของภาพอย่างทะลุปรุโปร่งแล้ว ในตอนต่อไป พี่จะพาน้องๆ ถลกแขนเสื้อ เจาะลึกลงไปหาวิธีการ “เข้าถึงและแก้ไขพิกเซลทีละจุด” (Pixel Access) เพื่อสร้างเวทมนตร์ Image Filter หรือการลบ Noise เฉพาะจุดด้วยมือของเราเองกันครับ รอติดตามได้เลย!


ต้องการที่ปรึกษาด้านการพัฒนาระบบ AI Camera หรือ Machine Vision ให้กับโรงงานของคุณ? ทีมงาน WP Solution พร้อมให้บริการออกแบบและติดตั้งระบบแบบครบวงจร ดูรายละเอียดบริการของเราได้ที่: www.wpsolution2017.com หรือพูดคุยปรึกษาเบื้องต้นได้ที่ Line: wisit.p