โมดูล 1/5 · สัปดาห์ 1–3 · 27 ชม.

ภาพดิจิทัลและกล้อง

UAT 307 การมองเห็นด้วยคอมพิวเตอร์และเทคโนโลยีการรับรู้

เวลาเรียนประมาณ 85 นาทีร่าง รอตรวจปรับปรุงล่าสุด 28 กันยายน 2569

บทเรียน

เมื่อเรียนจบโมดูลนี้ ผู้เรียนจะสามารถ

  1. อธิบายภาพดิจิทัลเป็นอาร์เรย์ของค่าความสว่าง และผลของการควอนไทซ์
  2. เขียนตัวกรอง Sobel หาขอบภาพด้วยคอนโวลูชันเอง
  3. เขียนวิธีของ Otsu เลือกค่าขีดแบ่งจากฮิสโตแกรม
  4. เลือกขั้นตอนประมวลผลภาพก่อนใช้ AI ให้ตรงกับงาน

ความรู้พื้นฐานที่ควรมี: UAT 205 โมดูล 4 (กล้องและการสอบเทียบ) · UAT 315 โมดูล 3 (การมองเห็นด้วยคอมพิวเตอร์)

ทำไมต้องรู้

UAT 315 ใช้ OpenCV หาวัตถุด้วยสีและติดตามตำแหน่ง ส่วน UAT 205 สอนแบบจำลองกล้องรูเข็มและการสอบเทียบ วิชานี้ลงลึกที่ อัลกอริทึมเบื้องหลัง ฟังก์ชันที่เรียกใช้กันบ่อย เพื่อให้เลือกและปรับได้เมื่อภาพจริงจากโดรนไม่เหมือนภาพตัวอย่าง หน่วยความรู้เรื่อง Computer Vision และการต่อยอดสู่ Edge AI ของคลังความรู้โดรนปูพื้นฐานเรื่องนี้ และหน่วยความรู้เรื่อง OpenCV สาธิตการทำสี threshold และหาขอบ ตำราของ Szeliski และ Corke อธิบายอัลกอริทึมเหล่านี้ละเอียด ตัวอย่างในวิชานี้ใช้ข้อมูลจำลองเพื่อให้ตรวจคำตอบได้

ภาพคืออาร์เรย์ของตัวเลข

ภาพระดับเทา 8 บิตคืออาร์เรย์สองมิติของค่า 0–255 ภาพสีมีสามช่อง ภาพความร้อนแบบเรดิโอเมตริกเก็บค่าที่แปลงเป็นอุณหภูมิได้ การควอนไทซ์เป็น 8 บิตทำให้รายละเอียดในส่วนมืดหรือสว่างจัดหายไป และการบีบอัดภาพแบบสูญเสียข้อมูลสร้างสัญญาณรบกวนเป็นบล็อก ขั้นตอนประมวลผลภาพทุกขั้นจึงต้องรู้ว่าข้อมูลต้นทางเป็นแบบใด

หาขอบด้วย Sobel

ขอบภาพคือบริเวณที่ความสว่างเปลี่ยนเร็ว ตัวกรอง Sobel เป็นเคอร์เนล 3×3 ที่ประมาณอนุพันธ์ตามแนวนอน และแนวตั้ง แล้วรวมเป็นขนาดเกรเดียนต์ ใช้ในงานโดรนเช่น หาขอบของรอยร้าว แนวถนน หรือขอบหลังคา OpenCV มีฟังก์ชัน cv2.Sobel ตัวอย่างนี้เขียนคอนโวลูชันเองเพื่อเห็นการคำนวณ

ตัวอย่างที่ 1 ขอบระหว่างพื้นมืดกับพื้นสว่าง และจุดรบกวน

ภาพจำลอง 12×12 ครึ่งซ้ายค่า 60 ครึ่งขวาค่า 180 และมีจุดรบกวนหนึ่งพิกเซลค่า 200

import numpy as np

img = np.full((12, 12), 60.0)
img[:, 6:] = 180.0
img[3, 2] = 200.0                               # จุดรบกวน
kx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
ky = kx.T

def conv(a, k):
    out = np.zeros((a.shape[0] - 2, a.shape[1] - 2))
    for i in range(out.shape[0]):
        for j in range(out.shape[1]):
            out[i, j] = (a[i:i + 3, j:j + 3] * k).sum()
    return out

mag = np.hypot(conv(img, kx), conv(img, ky))
print(f"largest gradient {mag.max():.0f} at output columns {sorted(set(np.argwhere(mag == mag.max())[:, 1]))}")
strong = mag > 200
print(f"pixels above 200: {strong.sum()} (edge columns {sorted(set(np.argwhere(strong)[:, 1]))})")
largest gradient 480 at output columns [np.int64(4), np.int64(5)]
pixels above 200: 24 (edge columns [np.int64(0), np.int64(1), np.int64(2), np.int64(4), np.int64(5)])

ขอบจริงให้ค่าเกรเดียนต์สูงสุดสองคอลัมน์ตลอดความสูงภาพ แต่จุดรบกวนพิกเซลเดียวก็สร้างค่าสูงเกินขีดแบ่งได้หลายพิกเซล ในภาพจริงจึงมักทำให้ภาพเรียบก่อน (เช่น Gaussian blur) แล้วจึงหาขอบ หรือใช้วิธีอย่าง Canny ที่มีขั้นลดสัญญาณรบกวนและเชื่อมเส้นขอบ

สองตาราง ซ้ายคือภาพจำลองครึ่งซ้ายมืดครึ่งขวาสว่างและจุดสว่างหนึ่งจุด ขวาคือขนาดเกรเดียนต์ที่แสดงค่ามากเป็นสีเข้ม แถบเข้มแนวตั้งตรงขอบ และกลุ่มพิกเซลเข้มรอบจุดรบกวน
ภาพที่ 1 ภาพจำลองและขนาดเกรเดียนต์จาก Sobel

เลือกขีดแบ่งด้วยวิธีของ Otsu

การแยกวัตถุกับพื้นหลังด้วยขีดแบ่งเดียวต้องเลือกค่าให้ดี วิธีของ Otsu (1979) ลองทุกค่าขีดแบ่ง แล้วเลือกค่าที่ทำให้ ความแปรปรวนระหว่างกลุ่ม สูงสุด ซึ่งเท่ากับทำให้ความแปรปรวนภายในกลุ่มแบบถ่วงน้ำหนักต่ำสุดตามที่บทสอนของ OpenCV อธิบาย OpenCV เรียกใช้ด้วย cv2.threshold กับธง THRESH_OTSU

ตัวอย่างที่ 2 แยกหลังคาสว่างจากพื้นมืด

ภาพ 10,000 พิกเซล พื้นเฉลี่ย 70 และหลังคาเฉลี่ย 170 (ข้อมูลจำลอง)

import numpy as np

rng = np.random.default_rng(3)
pix = np.r_[rng.normal(70, 15, 7000), rng.normal(170, 20, 3000)].clip(0, 255).astype(int)
p = np.bincount(pix, minlength=256) / pix.size
best_var, best_t = 0.0, 0
for t in range(1, 256):
    w0, w1 = p[:t].sum(), p[t:].sum()
    if w0 == 0 or w1 == 0:
        continue
    m0 = (np.arange(t) * p[:t]).sum() / w0
    m1 = (np.arange(t, 256) * p[t:]).sum() / w1
    var_b = w0 * w1 * (m0 - m1) ** 2
    if var_b > best_var:
        best_var, best_t = var_b, t
print(f"Otsu threshold {best_t}, bright fraction {(pix >= best_t).mean():.1%} (true roof fraction 30%)")
Otsu threshold 120, bright fraction 29.9% (true roof fraction 30%)

ขีดแบ่งที่ได้อยู่ระหว่างสองยอดของฮิสโตแกรม และสัดส่วนพิกเซลสว่างใกล้ค่าจริง วิธีนี้ทำงานดีเมื่อฮิสโตแกรมมีสองยอดชัด ถ้าแสงไม่สม่ำเสมอ เช่น มีเงาเมฆครึ่งภาพ ขีดแบ่งเดียวทั้งภาพจะใช้ไม่ได้ ต้องใช้ขีดแบ่งเฉพาะที่ (adaptive threshold) แทน

ฮิสโตแกรมค่าความสว่าง 0 ถึง 255 มีสองยอดที่ราว 70 และ 170 เส้นประสีชมพูแนวตั้งคือขีดแบ่งของ Otsu ที่ราว 120 ระหว่างสองยอด
ภาพที่ 2 ฮิสโตแกรมและขีดแบ่งของ Otsu

ปฏิบัติการประจำโมดูล

ปฏิบัติการ: จากสูตรสู่ OpenCV

  1. รันตัวอย่างที่ 1 แล้วเทียบผลกับ cv2.Sobel บนภาพเดียวกัน
  2. ใช้ Gaussian blur ก่อนหาขอบ สังเกตผลต่อจุดรบกวน
  3. รันตัวอย่างที่ 2 แล้วเทียบค่ากับ cv2.threshold(..., cv2.THRESH_OTSU)
  4. ลองกับภาพหลังคาจากโดรนจริงที่มีเงาเมฆ เทียบขีดแบ่งเดียวกับ adaptive threshold
  5. เขียนสรุปว่างานใดควรใช้การประมวลผลภาพแบบดั้งเดิม และงานใดควรใช้ AI

ข้อผิดพลาดที่พบบ่อย

ระวัง

  • หาขอบบนภาพที่มีสัญญาณรบกวนโดยไม่ทำให้เรียบก่อน
  • ใช้ขีดแบ่งเดียวทั้งภาพ เมื่อแสงไม่สม่ำเสมอ
  • ประมวลผลภาพ JPEG ที่บีบอัดมาก แล้วคาดหวังรายละเอียดเล็ก
  • ให้ความหมายกับค่าสีของภาพความร้อนที่ไม่ใช่เรดิโอเมตริก
  • เรียกฟังก์ชันโดยไม่รู้พารามิเตอร์ เช่น ขนาดเคอร์เนล

สรุป

  • ภาพดิจิทัลคืออาร์เรย์ของตัวเลข รู้ชนิดข้อมูลต้นทางก่อนประมวลผล
  • Sobel ประมาณอนุพันธ์ของความสว่าง ขนาดเกรเดียนต์สูงคือขอบ แต่ไวต่อสัญญาณรบกวน
  • Otsu เลือกขีดแบ่งที่ทำให้ความแปรปรวนระหว่างกลุ่มสูงสุด เหมาะกับฮิสโตแกรมสองยอด
  • แสงไม่สม่ำเสมอต้องใช้วิธีเฉพาะที่

แบบฝึกตรวจความเข้าใจ

  1. ภาพ 8 บิตมีค่าได้กี่ระดับ
  2. พื้นค่า 60 ขอบค่า 180 ตัวกรอง Sobel แนวนอนให้ค่าสูงสุดเท่าใดที่ขอบตรงแนวตั้ง
  3. ทำไมจุดรบกวนพิกเซลเดียวจึงสร้างขอบหลายพิกเซล
  4. วิธีของ Otsu เลือกขีดแบ่งจากเกณฑ์ใด
  5. ถ้าครึ่งภาพมีเงาเมฆ ควรเลือกขีดแบ่งแบบใด
เฉลย
  1. 256 ระดับ (0–255)
  2. เคอร์เนล 3×3 ที่เลื่อนผ่านจุดนั้นทุกตำแหน่งรอบ ๆ เห็นความต่างสูง
  3. ความแปรปรวนระหว่างกลุ่มสูงสุด
  4. ขีดแบ่งเฉพาะที่ (adaptive threshold)

สรุปสูตรสำคัญ

ขนาดเกรเดียนต์จาก Sobel
เกณฑ์ของ Otsu

แหล่งอ้างอิงหลัก

  1. Szeliski, R. (2022). Computer vision: Algorithms and applications (2nd ed.). Springer. link
  2. Corke, P. (2023). Robotics, vision and control: Fundamental algorithms in Python. Springer. link
  3. Otsu, N. (1979). A threshold selection method from gray-level histograms. IEEE Transactions on Systems, Man, and Cybernetics, 9(1), 62–66. link
  4. OpenCV. Image thresholding (Otsu's binarization). OpenCV 4.x tutorials. link
  5. OpenCV. OpenCV documentation. link

อ่านเพิ่มเติม

ศึกษาหน่วยความรู้ที่กำหนดล่วงหน้า ดูสื่อประกอบ และทำ quiz ประจำโมดูล

ในชั้นเรียน / ภาคสนาม

ปฏิบัติการในห้องแล็บหรือภาคสนามตามใบงาน พร้อม checklist ความปลอดภัย

หลักฐานการเรียนรู้: ใบงานที่ผ่านการตรวจและผล quiz

แบบทดสอบประจำโมดูล

แบบทดสอบนี้ใช้ตรวจความเข้าใจ (formative) ไม่ใช่การสอบเก็บคะแนน

โดเมนความรู้: ปัญญาประดิษฐ์และคอมพิวเตอร์วิทัศน์