รูปปกบทความ

1. 🎯 ตอนที่ 6: เบิกเนตร AI! ดึงภาพจากกล้องและวิดีโอด้วย VideoCapture

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

ในตอนที่แล้ว เราเรียนรู้วิธีให้ AI มองเห็น “ภาพนิ่ง” กันไปแล้ว แต่ในโลกของ Machine Vision จริงๆ ในโรงงานอุตสาหกรรม หรือระบบ Surveillance (กล้องวงจรปิด) ของที่วิ่งบนสายพานไม่ได้หยุดรอให้เราถ่ายรูปนะครับ! ทุกอย่างมันเกิดขึ้นแบบ Real-time การให้ AI มองเห็นภาพนิ่งภาพเดียวก็เหมือนการให้ยามดูรูปถ่ายโจรแค่ใบเดียวแล้วหวังว่าจะจับโจรที่กำลังวิ่งหนีได้ มันไม่ทันกินครับ!

ดวงตาของ AI จำเป็นต้องมองเห็นความเคลื่อนไหว วันนี้พี่จะมาชงกาแฟ แล้วพาน้องๆ ไปรู้จักกับเวทมนตร์บทใหม่ที่จะทำให้โปรแกรมของเราดึงภาพจาก “กล้อง Webcam” หรือ “ไฟล์วิดีโอ” มาประมวลผลแบบเฟรมต่อเฟรม (Frame-by-frame) ด้วยคลาสระดับพระเอกที่ชื่อว่า VideoCapture และการบันทึกผลงานลงฮาร์ดดิสก์ด้วย VideoWriter รับรองว่าจบตอนนี้น้องๆ จะทำแอปเปิดกล้องได้แบบหล่อๆ เลยครับ!

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

ก่อนจะเขียนโค้ด เราต้องเข้าใจหลักการพื้นฐานของ “วิดีโอ” ในมุมมองของ Computer Vision ก่อนครับ จริงๆ แล้ววิดีโอก็คือ “ภาพนิ่ง (Image Matrix) ที่ถูกนำมาฉายต่อเนื่องกันอย่างรวดเร็ว” จนตาเรามองเห็นเป็นการเคลื่อนไหว

ดังนั้น การทำงานกับวิดีโอใน OpenCV จึงอาศัย 3 องค์ประกอบหลัก:

  • 1. VideoCapture (ประตูเชื่อมต่อตากล้อง): นี่คือคลาสที่ทำหน้าที่ดึงภาพ (Grab) และถอดรหัส (Decode) วิดีโอออกมาเป็น cv::Mat ให้เราใช้งาน
    • ถ้าเราใส่ตัวเลข (Index) เช่น VideoCapture cap(0); มันจะไปดึงภาพจากกล้อง Webcam ตัวแรกของเครื่อง
    • ถ้าเราใส่ชื่อไฟล์ เช่น VideoCapture cap("factory.mp4"); มันก็จะไปเปิดไฟล์วิดีโอแทน
    • เราสามารถใช้คำสั่ง cap.get() เพื่อดึงคุณสมบัติของกล้องมาดูได้ เช่น ดึงความกว้าง (Width), ความสูง (Height), หรือ เฟรมเรต (FPS)
  • 2. The Infinite Loop (หัวใจของการเต้น Real-time): เพื่อที่จะอ่านวิดีโอ เราต้องสร้างลูป (เช่น while(true)) เพื่อวนดึงภาพ (Frame) ออกมาทีละภาพไปเรื่อยๆ หากดึงภาพไม่ได้แล้ว (ภาพเป็น Empty) ก็แปลว่าวิดีโอจบ หรือกล้องหลุด เราก็จะสั่ง Break ออกจากลูปครับ
  • 3. VideoWriter (เครื่องบันทึกความทรงจำ): เมื่อเราใส่ Filter หรือวาด Bounding Box ลงบนเฟรมภาพเสร็จแล้ว หากต้องการเซฟเป็นไฟล์วิดีโอ (เช่น .avi หรือ .mp4) เราจะใช้คลาสนี้ โดยเราต้องกำหนด “FourCC Codec” (รหัส 4 ตัวอักษรที่ใช้บอกรูปแบบการบีบอัด เช่น MJPG, XVID), ค่า FPS, และขนาดของวิดีโอให้ตรงกับภาพที่เราจะเซฟเป๊ะๆ
รูปประกอบ

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

เตรียมกล้อง Webcam ของน้องๆ ให้พร้อม! เรามาดูโครงสร้างโค้ด C++ มาตรฐานในการดึงภาพจากกล้อง วาดอะไรลงไปนิดหน่อย แล้วเซฟกลับเป็นไฟล์วิดีโอกันครับ

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

using namespace cv;
using namespace std;

int main() {
    // 1. เปิดกล้อง Webcam ตัวแรก (Index 0)
    VideoCapture cap(0); 
    
    // ตรวจสอบว่ากล้องเปิดสำเร็จไหม (ปราการป้องกันบั๊ก!)
    if (!cap.isOpened()) {
        cout << "Error: ไม่สามารถเปิดกล้องได้ครับน้อง!" << endl;
        return -1;
    }

    // 2. ดึงข้อมูลความกว้าง ความสูง และ FPS จากกล้อง
    int frame_width = static_cast<int>(cap.get(CAP_PROP_FRAME_WIDTH));
    int frame_height = static_cast<int>(cap.get(CAP_PROP_FRAME_HEIGHT));
    // ปกติกล้อง Webcam อาจจะคืนค่า FPS ไม่ตรงเป๊ะ เรากำหนดเองเป็น 30.0 ไปก่อนได้
    double fps = 30.0; 

    // 3. สร้างเครื่องบันทึกวิดีโอ (VideoWriter)
    // ใช้ Codec แบบ MJPG เซฟเป็นไฟล์ .avi
    VideoWriter writer("output_camera.avi", VideoWriter::fourcc('M','J','P','G'), 
                       fps, Size(frame_width, frame_height));

    Mat frame;
    // 4. ลูปดึงภาพแบบ Real-time
    while (true) {
        // ดูดภาพจากกล้องเข้ามาเก็บในตัวแปร frame
        cap >> frame; 
        
        // ถ้าไม่มีภาพเข้ามา (เช่น กล้องดับ หรือวิดีโอจบ) ให้หยุดลูป
        if (frame.empty()) break; 

        // แต่งภาพสักนิด: พิมพ์ข้อความลงบนเฟรม
        putText(frame, "LIVE: WP Solution", Point(10, 50), 
                FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 255, 0), 2);

        // 5. แสดงภาพออกหน้าจอ
        imshow("My Live Camera", frame);

        // 6. บันทึกเฟรมนี้ลงไฟล์วิดีโอ
        writer.write(frame); 

        // 7. สั่งให้หยุดรอ 30 มิลลิวินาที (เพื่อให้ภาพแสดงผลทัน) 
        // และรอรับค่าจากคีย์บอร์ด ถ้ากดปุ่ม ESC (ASCII = 27) ให้ Break ลูป
        char c = (char)waitKey(30);
        if (c == 27) break; 
    }

    // 8. คืน Memory ให้ระบบ (สำคัญมาก!)
    cap.release();
    writer.release();
    destroyAllWindows();

    return 0;
}

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

  • กับดักของ waitKey(): ในตอนที่แล้วเราใช้ waitKey(0) เพื่อให้ภาพนิ่งหยุดรอแบบ Infinity ใช่ไหมครับ? แต่อย่าเผลอเอามาใส่ในลูปวิดีโอเด็ดขาด! ไม่งั้นภาพจะค้างที่เฟรมแรกจนกว่าเราจะกดคีย์บอร์ด เราต้องใส่ตัวเลขลงไป เช่น waitKey(30) (รอ 30 มิลลิวินาที) ซึ่งสอดคล้องกับวิดีโอเฟรมเรตประมาณ 30 FPS (1000ms / 30 = 33.3ms)
  • VideoWriter เซฟไฟล์ไม่ได้ ไฟล์เสีย 0 KB: ปัญหาโลกแตกของมือใหม่ครับ! สาเหตุหลักๆ มาจาก “ขนาดของเฟรมภาพ (Size)” ที่เราใส่ตอนตั้งค่า VideoWriter ไม่ตรง กับขนาดของ Mat frame ที่เราจับยัดลงไปใน writer.write(frame) หรืออีกกรณีคือบนเครื่องของน้องๆ ไม่มี Codec ตัวนั้นติดตั้งอยู่ ให้ลองเปลี่ยน FourCC เป็นตัวอื่นดูครับ
  • อย่าลืม Release: แม้ว่า C++ จะมี Destructor คอยช่วยทำลายอ็อบเจ็กต์ตอนจบโปรแกรม แต่การสั่ง cap.release() และ writer.release() ด้วยตัวเองคือ Best Practice ครับ เพราะถ้าเราไม่ปิด VideoWriter ให้สมบูรณ์ ไฟล์วิดีโอปลายทางที่เราเซฟไว้อาจจะพังหรือเปิดไม่ขึ้นเลยก็ได้ครับ

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

เป็นยังไงบ้างครับ! ตอนนี้โปรแกรม AI ของเราลืมตาตื่นขึ้นมามองโลกภายนอกแบบ Real-time ได้อย่างสมบูรณ์แล้ว ไม่ว่าจะดึงภาพจากกล้อง Webcam ในโรงงาน หรืออ่านไฟล์วิดีโอเพื่อนำมาวิเคราะห์ย้อนหลัง โครงสร้างลูป while(true) และการใช้ VideoCapture ก็ยังเป็นหัวใจสำคัญเสมอ

ในตอนต่อไป เราจะเริ่มนำภาพจากวิดีโอที่ได้นี้ มาทำ “Image Processing” เบื้องต้น เช่น การปรับภาพให้เบลอ (Blurring) เพื่อลดสัญญาณรบกวน, การแปลงเป็นขาวดำ และการหาขอบของวัตถุ (Edge Detection) เพื่อเตรียมข้อมูลให้พร้อมก่อนส่งให้ AI วิเคราะห์กันครับ เตรียมตัวให้พร้อม!


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