รูปปกบทความ

1. 🎯 ตอนที่ 12: เวทมนตร์แห่งแสงและเงา! การใช้ Bitwise Operations ตัดต่อภาพเบื้องต้น

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

น้องๆ เคยสงสัยไหมครับว่า AI ในโรงงานมัน “ตัด” เอาเฉพาะรูปน็อตที่อยู่บนสายพานออกมาวิเคราะห์ โดยทิ้งพื้นหลังที่รกๆ ไปได้ยังไง? ถ้าเป็นคนทำกราฟิก คงต้องเปิดโปรแกรม Photoshop แล้วเอาเครื่องมือมานั่งไดคัทลบพื้นหลัง (Die-cut) ทีละรูปใช่ไหมครับ แต่ในโลกของ Machine Vision ที่กล้องรันด้วยความเร็ว 60 FPS เราไม่มีเวลามานั่งทำแบบนั้นแน่ๆ

แล้วเราจะทำยังไงดี? คำตอบคือเราต้องใช้ “แม่พิมพ์” (Stencil) มาทาบลงบนภาพครับ! ในโลกของ Image Processing เราเรียกแม่พิมพ์นี้ว่า Mask (หน้ากาก) และเครื่องมือที่จะเอามาใช้ทาบแล้วตัดภาพออกมาก็คือ Bitwise Operations นั่นเองครับ วันนี้พี่จะมาชงกาแฟ แล้วพาน้องๆ ไปดูเวทมนตร์ระดับตรรกะ (Logic) ที่จะเปลี่ยนภาพพื้นหลังรกๆ ให้เหลือแต่สิ่งที่เราสนใจกันครับ!

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

คำว่า Bitwise Operations คือการคำนวณทางตรรกศาสตร์ในระดับ “บิต” (0 และ 1) ของแต่ละพิกเซลครับ ใน OpenCV หากเรามองภาพในรูปแบบ Grayscale หรือ Mask แบบ Binary สีดำจะมีค่าเป็น 0 (Off / ปิด) และสีขาวจะมีค่าเป็น 255 หรือ 1 (On / เปิด)

เมื่อเรานำภาพ 2 ภาพมาทำ Bitwise กัน มันจะเปรียบเทียบพิกเซลต่อพิกเซลเลยครับ โดยมีฟังก์ชันฮีโร่ 4 ตัวหลักๆ ดังนี้:

  • 1. bitwise_not (เวทย์กลับตาลปัตร):
    • หน้าที่: ทำการกลับบิต (Invert) สีดำจะกลายเป็นสีขาว และสีขาวจะกลายเป็นสีดำ
    • การใช้งาน: สมมติเราทำ Thresholding แล้วได้พิกเซลของวัตถุเป็นสีดำ พื้นหลังเป็นสีขาว แต่ AI ของเราต้องการให้วัตถุเป็นสีขาว เราก็ใช้ bitwise_not สลับสีมันซะเลย!
  • 2. bitwise_and (กรรไกรตัดภาพ):
    • หน้าที่: นำภาพ 2 ภาพมา “และ” กัน พิกเซลผลลัพธ์จะเป็นสีขาว (หรือสีต้นฉบับ) ก็ต่อเมื่อพิกเซลตำแหน่งนั้นของ ทั้งสองภาพ ต้องไม่ใช่สีดำ (0)
    • การใช้งาน: นี่คือพระเอกของการทำ Masking! เราจะใช้ภาพต้นฉบับเป็นภาพที่ 1 และ 2 แล้วใส่ mask ที่เป็นสีขาว-ดำเข้าไป ส่วนไหนของ Mask ที่เป็น “สีขาว” ข้อมูลภาพต้นฉบับจะทะลุผ่านออกมาได้ ส่วนไหนเป็น “สีดำ” ภาพจะถูกตัดทิ้งกลายเป็นความมืดทันที!
  • 3. bitwise_or (เวทย์รวมร่าง):
    • หน้าที่: นำภาพ 2 ภาพมา “หรือ” กัน ขอแค่พิกเซลภาพใดภาพหนึ่งมีค่ามากกว่า 0 ผลลัพธ์ก็จะสว่างทันที
    • การใช้งาน: เหมาะสำหรับการรวม Bounding Box หรือ Contours จากหลายๆ เงื่อนไขเข้าด้วยกัน (เช่น เอา Mask ของวัตถุสีแดง มารวมกับ Mask ของวัตถุสีน้ำเงิน)
  • 4. bitwise_xor (เวทย์จับผิด):
    • หน้าที่: “Exclusive OR” จะให้ผลลัพธ์เป็นค่าสว่าง ก็ต่อเมื่อพิกเซลของภาพที่ 1 และ 2 ต้องมีค่าไม่เหมือนกัน เท่านั้น!
    • การใช้งาน: ใช้หาจุดที่แตกต่างกันระหว่างภาพ 2 ภาพได้อย่างรวดเร็ว
รูปประกอบ

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

เตรียมกล้องและ IDE ของน้องๆ ให้พร้อม! เรามาดูโค้ด C++ ในการสร้าง Mask สีดำ-ขาว แล้วนำมา “ไดคัท” ตัดเฉพาะวัตถุออกจากภาพด้วยฟังก์ชัน bitwise_and และการใช้ bitwise_not เพื่อกลับด้าน Mask กันครับ

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

using namespace cv;
using namespace std;

int main() {
    // 1. โหลดภาพสีต้นฉบับ (สมมติว่าเป็นภาพชิ้นส่วนในโรงงาน)
    Mat image = imread("factory_part.jpg", IMREAD_COLOR);
    if(image.empty()) return -1;

    // 2. สร้าง Mask สีดำสนิท (0) ขนาดต้อง "เท่ากับภาพต้นฉบับเป๊ะๆ" แต่เป็น 1 Channel (Grayscale)
    Mat mask = Mat::zeros(image.size(), CV_8UC1);

    // 3. วาดวงกลมสีขาว (255) ลงไปตรงกลาง เพื่อจำลองว่า AI ของเราเจอวัตถุแล้ว
    // (ในงานจริง พื้นที่สีขาวนี้มักจะได้มาจากการทำ Thresholding หรือ Contours)
    circle(mask, Point(image.cols/2, image.rows/2), 150, Scalar(255), FILLED);

    // 4. เตรียมตัวแปร Mat ไว้เก็บผลลัพธ์
    Mat extractedObject, invertedMask;

    // ==========================================
    // เวทมนตร์ที่ 1: bitwise_and ตัดเฉพาะส่วนที่ Mask เป็นสีขาว
    // ไวยากรณ์: bitwise_and(src1, src2, dst, mask)
    // ==========================================
    bitwise_and(image, image, extractedObject, mask);

    // ==========================================
    // เวทมนตร์ที่ 2: bitwise_not พลิกด้าน Mask ขาวเป็นดำ-ดำเป็นขาว
    // ==========================================
    bitwise_not(mask, invertedMask);

    // แสดงผลงานให้โลกเห็น
    imshow("1. Original Image", image);
    imshow("2. Mask (White = Keep, Black = Ignore)", mask);
    imshow("3. Extracted Object (Using bitwise_and)", extractedObject);
    imshow("4. Inverted Mask (Using bitwise_not)", invertedMask);

    waitKey(0);
    destroyAllWindows();
    return 0;
}

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

  • กฎเหล็กของ Mask (The Mask Rule): พารามิเตอร์ mask ในฟังก์ชันของ OpenCV เกือบทุกตัว (รวมถึง bitwise_and) บังคับ ว่าจะต้องเป็นภาพแบบ 1 Channel 8-bit (CV_8UC1) เท่านั้นนะครับ! ถ้าน้องๆ เผลอเอาภาพสี 3 Channels (BGR) มาทำเป็น Mask แล้วโยนเข้าไป โปรแกรมจะพ่น Error ประท้วงและแครชทันทีครับ!
  • เร็วทะลุนรก (Hardware Accelerated): ฟังก์ชัน Bitwise ใน OpenCV ไม่ได้ใช้ for loop ธรรมดาในการวนอ่านพิกเซลนะครับ แต่มันถูกเขียนมาให้ใช้ความสามารถของ CPU ในระดับ Hardware (เช่น คำสั่ง SIMD, SSE, AVX) ทำให้มันสแกนประมวลผลภาพระดับ Full HD ได้ในเวลาไม่ถึงมิลลิวินาที! ดังนั้นไม่ต้องกลัวเลยว่าจะทำให้ Vision Pipeline ของเราช้าลง
  • 0 และ 255 คือเพื่อนแท้: แม้ว่า Mask จะรับค่าตั้งแต่ 0-255 แต่เพื่อป้องกันบั๊กในการทำ Feature Extraction หรือ Object Detection หน้างาน พี่แนะนำให้ใช้ฟังก์ชันอย่าง cv::threshold ตัดค่าให้เด็ดขาดไปเลยว่า พิกเซลไหนจะเป็น 0 และพิกเซลไหนจะเป็น 255 (Binary) อย่าให้มีค่าสีเทาๆ ก้ำกึ่งอยู่ใน Mask ครับ

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

เป็นยังไงบ้างครับ? แค่เข้าใจตรรกะง่ายๆ อย่าง AND, OR, NOT เราก็สามารถสร้างเครื่องมือตัดต่อภาพ ลบพื้นหลัง หรือซ้อนภาพ (Overlay) ให้กับ AI ของเราได้อย่างทรงพลังแล้ว ทักษะเรื่อง Masking นี้คือหัวใจสำคัญที่สุดในการทำ Image Segmentation เลยนะครับ!

แต่สังเกตไหมครับว่า ถ้าเราใช้ Thresholding หาวัตถุในโรงงานจริงๆ ขอบของ Mask สีขาวมันอาจจะแหว่งๆ หรือมีจุดรบกวน (Noise) ยิบย่อยเต็มไปหมด ในตอนต่อไป พี่จะพาน้องๆ ไปรู้จักกับเวทมนตร์ทำความสะอาด Mask ที่ชื่อว่า “Morphological Operations (การกัดกร่อนและการพองตัว)” เพื่อเสกให้ขอบเขตวัตถุของเราเนียนกริบกันครับ รอติดตามได้เลย!


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