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

Computer vision

UAT 315 ปัญญาประดิษฐ์ การวิเคราะห์ข้อมูล และการมองเห็นด้วยคอมพิวเตอร์สำหรับระบบอากาศยานไร้คนขับ

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

บทเรียน

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

  1. อธิบายคอนโวลูชันและใช้ OpenCV แยกวัตถุด้วยสี นับ และหากรอบของวัตถุ
  2. อธิบายโครงสร้างของโครงข่ายประสาทแบบคอนโวลูชัน (CNN) และพัฒนาการตั้งแต่ LeNet ถึง ResNet
  3. แยกงานจำแนกภาพ ตรวจจับวัตถุ และแบ่งส่วนภาพ และอธิบายขั้นตอนตรวจจับรวมทั้ง NMS
  4. ติดตามวัตถุด้วยตัวกรองคาลมานอย่างง่าย และอธิบายการหลอมรวมข้อมูลเซนเซอร์

ความรู้พื้นฐานที่ควรมี: UAT 315 โมดูล 1–2

ทำไมต้องรู้

กล้องเป็นเซนเซอร์ที่ถูกและให้ข้อมูลมากที่สุดบนโดรน การมองเห็นด้วยคอมพิวเตอร์ (computer vision) ทำให้โดรนหาผู้ประสบภัย นับต้นไม้ ตรวจรอยร้าว หรือตามวัตถุได้ งานเหล่านี้มีตั้งแต่การประมวลผลภาพแบบดั้งเดิมที่อธิบายได้ทุกขั้น ไปจนถึงการเรียนรู้เชิงลึกที่แม่นกว่าแต่ต้องใช้ข้อมูลและการประเมินอย่างระมัดระวัง ผู้ใช้งานต้องรู้ว่าแต่ละวิธีทำอะไรได้และพลาดตรงไหน

คอนโวลูชันและการประมวลผลภาพ

คอนโวลูชัน (convolution) คือการเลื่อนตัวกรองขนาดเล็ก (kernel) ไปทั่วภาพ แล้วคูณและรวมค่าในแต่ละตำแหน่ง ตัวกรองต่างกันให้ผลต่างกัน เช่น เบลอภาพ หรือหาขอบ ตัวกรอง Sobel ในแนวนอนให้ค่าสูงตรงที่ความสว่างเปลี่ยนจากซ้ายไปขวา

import numpy as np

image = np.array([[10, 10, 10, 200, 200],
                  [10, 10, 10, 200, 200],
                  [10, 10, 10, 200, 200],
                  [10, 10, 10, 200, 200]], dtype=float)
sobel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], dtype=float)
out = np.zeros((image.shape[0] - 2, image.shape[1] - 2))
for i in range(out.shape[0]):
    for j in range(out.shape[1]):
        out[i, j] = np.sum(sobel_x * image[i:i + 3, j:j + 3])
print(out)
[[  0. 760. 760.]
 [  0. 760. 760.]]

ค่าเป็นศูนย์ในบริเวณที่ความสว่างคงที่ และสูงตรงรอยต่อระหว่าง 10 กับ 200 ซึ่งคือขอบของวัตถุ ใน CNN ตัวกรองแบบนี้ไม่ได้ออกแบบโดยคน แต่เรียนรู้จากข้อมูลเอง

ตัวอย่างที่ 1 หากล่องสีส้มบนพื้นหญ้าด้วย OpenCV

สร้างภาพสังเคราะห์ขนาด 120 × 160 พื้นสีเขียวมีสัญญาณรบกวน วางกล่องสีส้มสามกล่อง แล้วแยกสีส้มในปริภูมิสี HSV (สี ความอิ่มตัว ความสว่าง) ซึ่งแยกสีได้ง่ายกว่า BGR

import cv2

rng = np.random.default_rng(345)
frame = np.full((120, 160, 3), (60, 130, 70), np.uint8)
frame = np.clip(frame.astype(int) + rng.integers(-15, 16, frame.shape), 0, 255).astype(np.uint8)
truth = [(20, 30, 16, 12), (90, 70, 20, 14), (130, 20, 10, 10)]
for x, y, w, h in truth:
    frame[y:y + h, x:x + w] = (20, 120, 240)

hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, (5, 150, 150), (25, 255, 255))
count, labels, stats, centroids = cv2.connectedComponentsWithStats(mask)
found = sorted(tuple(int(v) for v in s[:4]) for s in stats[1:])
print("objects found:", count - 1)
print("boxes (x, y, w, h):", found)
objects found: 3
boxes (x, y, w, h): [(20, 30, 16, 12), (90, 70, 20, 14), (130, 20, 10, 10)]

วิธีนี้ง่ายและอธิบายได้ทุกขั้น แต่ใช้ได้เฉพาะเมื่อวัตถุมีสีเด่นและแสงคงที่ ถ้ามีเงา แสงเย็น หรือวัตถุสีคล้ายกัน ช่วงสีที่ตั้งไว้จะพลาดทันที งานจริงจึงใช้การเรียนรู้เชิงลึก

โครงข่ายประสาทแบบคอนโวลูชัน

CNN (convolutional neural network) ซ้อนชั้นคอนโวลูชันหลายชั้น ชั้นต้นเรียนจับขอบและสี ชั้นลึกเรียนจับรูปทรงและวัตถุ ชั้น pooling ย่อขนาดข้อมูล และชั้นเชื่อมเต็ม (fully connected) ตัดสินคลาส

ลำดับชั้นจากซ้ายไปขวา ภาพเข้า Conv กับ ReLU Pooling Conv กับ ReLU Pooling ชั้นเชื่อมเต็ม และคลาส ขนาดของกล่องเล็กลงเมื่อลึกขึ้น ด้านล่างเขียนว่าชั้นต้นจับขอบและสี ชั้นลึกจับรูปทรงและวัตถุ
ภาพที่ 1 โครงสร้างของโครงข่ายประสาทแบบคอนโวลูชัน
ปีงานจุดสำคัญ
1998LeNet (LeCun และคณะ)CNN อ่านตัวเลขเขียนมือ
2012AlexNet (Krizhevsky และคณะ)CNN ลึกบน GPU ชนะการแข่งขัน ImageNet อย่างขาดลอย
2016ResNet (He และคณะ)การเชื่อมข้ามชั้น (residual) ทำให้ฝึกเครือข่ายลึกมากได้
2016YOLO (Redmon และคณะ)ตรวจจับวัตถุทั้งภาพในการประมวลผลครั้งเดียว เร็วพอสำหรับเวลาจริง
2023Segment Anything (Kirillov และคณะ)แบบจำลองแบ่งส่วนภาพที่ใช้กับภาพหลากหลายโดยไม่ต้องฝึกใหม่

จำแนก ตรวจจับ และแบ่งส่วน

  • จำแนกภาพ (image classification) ตอบว่าทั้งภาพเป็นอะไร เช่น “มีพื้นที่น้ำท่วม”
  • ตรวจจับวัตถุ (object detection) ตอบว่ามีวัตถุอะไร อยู่ตรงไหน เป็นกรอบสี่เหลี่ยมพร้อมคะแนนความมั่นใจ
  • แบ่งส่วนภาพ (segmentation) ระบุคลาสของทุกพิกเซล เช่น น้ำ ถนน อาคาร

ตระกูล YOLO เป็นตัวตรวจจับที่นิยมบนโดรน รุ่นล่าสุดของ Ultralytics ขณะเขียนคือ YOLO26 (มกราคม 2026) ใบอนุญาต AGPL-3.0 ถ้าใช้ในผลิตภัณฑ์ที่ไม่เปิดโค้ดต้องซื้อใบอนุญาตแบบ Enterprise ตามที่หน่วยความรู้ “Computer Vision และการต่อยอดสู่ Edge AI” ของคลังความรู้โดรนเตือนไว้

ห้ากล่องเรียงกัน ภาพจากกล้อง แบบจำลองตรวจจับ กรอบจำนวนมากพร้อมความมั่นใจ ตัดด้วยจุดตัด และ NMS ด้านล่างซ้ายมีกรอบประสามกรอบซ้อนบนวัตถุเดียว ลูกศรชี้ไปทางขวาที่เหลือกรอบที่ดีที่สุดกรอบเดียว
ภาพที่ 2 ขั้นตอนตรวจจับวัตถุตั้งแต่ภาพจนได้กรอบ

ตัวตรวจจับมักให้กรอบหลายกรอบซ้อนบนวัตถุเดียว NMS (non-maximum suppression) เก็บกรอบที่คะแนนสูงสุด แล้วตัดกรอบอื่นที่ทับกับกรอบนั้นมากเกินเกณฑ์ ความทับวัดด้วย IoU คือพื้นที่ส่วนทับหารด้วยพื้นที่ส่วนรวม

def iou(a, b):
    ax, ay, aw, ah = a
    bx, by, bw, bh = b
    inter_w = max(0, min(ax + aw, bx + bw) - max(ax, bx))
    inter_h = max(0, min(ay + ah, by + bh) - max(ay, by))
    inter = inter_w * inter_h
    return inter / (aw * ah + bw * bh - inter)


def nms(boxes, scores, iou_threshold=0.5):
    order = sorted(range(len(boxes)), key=lambda i: scores[i], reverse=True)
    keep = []
    for i in order:
        if all(iou(boxes[i], boxes[k]) < iou_threshold for k in keep):
            keep.append(i)
    return keep


candidates = [(88, 69, 22, 15), (90, 70, 20, 14), (92, 72, 19, 13), (20, 30, 16, 12)]
scores = [0.81, 0.93, 0.66, 0.88]
print("IoU of box 0 and box 1:", round(iou(candidates[0], candidates[1]), 3))
print("kept after NMS:", [(candidates[i], scores[i]) for i in nms(candidates, scores)])
IoU of box 0 and box 1: 0.848
kept after NMS: [((90, 70, 20, 14), 0.93), ((20, 30, 16, 12), 0.88)]

สามกรอบแรกทับวัตถุเดียวกัน NMS เก็บเฉพาะกรอบคะแนน 0.93 และเก็บกรอบที่อยู่วัตถุอื่นไว้ เกณฑ์ IoU ของ NMS ต้องเลือกให้เหมาะ ถ้าต่ำเกินไป วัตถุสองชิ้นที่อยู่ติดกันจะถูกตัดเหลือชิ้นเดียว

ติดตามวัตถุและหลอมรวมข้อมูล

การตรวจจับทีละเฟรมไม่รู้ว่ากรอบในเฟรมนี้กับเฟรมก่อนเป็นวัตถุเดียวกันหรือไม่ การติดตาม (tracking) เชื่อมผลข้ามเฟรม และใช้แบบจำลองการเคลื่อนที่ช่วยลดสัญญาณรบกวน ตัวกรองคาลมาน (Kalman filter) ที่ Kalman เสนอในปี 1960 ผสานการทำนายจากแบบจำลองกับค่าที่วัดได้ โดยให้น้ำหนักตามความไม่แน่นอนของแต่ละฝั่ง หลักเดียวกันนี้ใช้ หลอมรวมข้อมูลเซนเซอร์ (sensor fusion) เช่น รวม GNSS กับ IMU ในตัวควบคุมการบิน

ตัวอย่างที่ 2 ติดตามตำแหน่งวัตถุที่เคลื่อนที่

วัตถุเคลื่อนที่ 2 m ต่อเฟรม ตำแหน่งที่วัดได้จากภาพมีความคลาดเคลื่อนส่วนเบี่ยงเบนมาตรฐาน 1.5 m ใช้ตัวกรองคาลมานแบบความเร็วคงที่ในหนึ่งมิติ

steps, speed, meas_sd = 30, 2.0, 1.5
truth_pos = speed * np.arange(steps)
measured = truth_pos + rng.normal(0, meas_sd, steps)

F = np.array([[1.0, 1.0], [0.0, 1.0]])
H = np.array([[1.0, 0.0]])
Q = np.diag([0.01, 0.01])
R = np.array([[meas_sd ** 2]])
x = np.array([measured[0], 0.0])
P = np.diag([R[0, 0], 4.0])
estimates = []
for z in measured:
    x = F @ x
    P = F @ P @ F.T + Q
    K = P @ H.T @ np.linalg.inv(H @ P @ H.T + R)
    x = x + (K @ (np.array([z]) - H @ x)).ravel()
    P = (np.eye(2) - K @ H) @ P
    estimates.append(x[0])
estimates = np.array(estimates)

rmse = lambda e: np.sqrt(np.mean(e ** 2))
print(f"RMSE of raw measurements (last 20 frames) {rmse(measured[10:] - truth_pos[10:]):.2f} m")
print(f"RMSE of Kalman estimates (last 20 frames) {rmse(estimates[10:] - truth_pos[10:]):.2f} m")
print(f"estimated speed {x[1]:.2f} m per frame")
RMSE of raw measurements (last 20 frames) 1.61 m
RMSE of Kalman estimates (last 20 frames) 0.68 m
estimated speed 1.97 m per frame

หลังผ่านไปไม่กี่เฟรม ตัวกรองให้ตำแหน่งที่คลาดเคลื่อนน้อยกว่าค่าวัดดิบมาก และยังประมาณความเร็วได้ด้วย ซึ่งไม่มีในข้อมูลที่วัด ค่าเริ่มต้นช่วงแรกยังไม่นิ่ง จึงเทียบทั้งสองแบบในช่วง 20 เฟรมหลังเหมือนกัน

กิจกรรมในชั้นเรียน

กิจกรรม: เลือกวิธีมองเห็นให้ตรงงาน

  1. สำหรับสามงาน คือ นับต้นปาล์ม ประเมินพื้นที่น้ำท่วม และหาผู้ประสบภัยกลางคืน เลือกว่าเป็นงานจำแนก ตรวจจับ หรือแบ่งส่วน และควรใช้กล้องชนิดใด
  2. ในโค้ดตัวอย่างที่ 1 เพิ่มเงาโดยลดความสว่างของกล่องหนึ่งลงครึ่งหนึ่ง แล้วดูว่าการแยกสีพลาดอย่างไร อภิปรายว่า CNN แก้ปัญหานี้ได้เพราะอะไร
  3. ลดเกณฑ์ IoU ของ NMS เป็น 0.1 กับกรอบของวัตถุสองชิ้นที่อยู่ติดกัน แล้วอธิบายผลที่ได้
  4. อ่านหน่วยความรู้ “AI คัดกรองภาพและความเสียหาย” แล้วสรุปว่าทำไมผลจากแบบจำลองควรเป็นรายการช่วยตรวจ ไม่ใช่คำตัดสิน

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

ระวัง

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

สรุป

  • คอนโวลูชันเลื่อนตัวกรองไปทั่วภาพ การประมวลผลภาพแบบดั้งเดิมอธิบายได้แต่เปราะต่อแสง
  • CNN เรียนตัวกรองจากข้อมูลเอง พัฒนาจาก LeNet ถึง ResNet และตัวตรวจจับเช่น YOLO
  • จำแนก ตรวจจับ และแบ่งส่วนตอบคำถามต่างกัน ตัวตรวจจับต้องใช้จุดตัดความมั่นใจและ NMS
  • ตัวกรองคาลมานผสานการทำนายกับค่าวัด ใช้ติดตามวัตถุและหลอมรวมข้อมูลเซนเซอร์

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

  1. งาน “ระบุว่าแต่ละพิกเซลเป็นน้ำหรือไม่” คืองานชนิดใด
  2. กรอบสองกรอบพื้นที่ 50 พิกเซล² เท่ากัน ทับกัน 25 พิกเซล² มี IoU เท่าใด
  3. ทำไมจึงแยกสีในปริภูมิ HSV แทน BGR
  4. NMS ทำหน้าที่อะไร
  5. ตัวกรองคาลมานให้น้ำหนักกับค่าวัดมากขึ้นเมื่อใด
เฉลย
  1. แบ่งส่วนภาพ (semantic segmentation)
  2. ส่วนรวม ได้ IoU
  3. HSV แยกสี (hue) ออกจากความสว่าง จึงกำหนดช่วงสีได้ง่ายกว่าและทนต่อการเปลี่ยนความสว่างมากกว่า
  4. ตัดกรอบที่ซ้อนกันบนวัตถุเดียว เหลือกรอบที่คะแนนสูงสุด
  5. เมื่อความไม่แน่นอนของค่าวัด น้อยเมื่อเทียบกับความไม่แน่นอนของการทำนาย ทำให้ค่า ใกล้ 1

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

คอนโวลูชันสองมิติ (แบบที่ใช้ใน CNN)
Intersection over Union
ตัวกรองคาลมาน ขั้นปรับปรุง

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

  1. Szeliski, R. (2022). Computer vision: Algorithms and applications (2nd ed.). Springer. link
  2. OpenCV. OpenCV documentation. link
  3. LeCun, Y., Bottou, L., Bengio, Y., & Haffner, P. (1998). Gradient-based learning applied to document recognition. Proceedings of the IEEE, 86(11), 2278–2324. link
  4. Krizhevsky, A., Sutskever, I., & Hinton, G. E. (2012). ImageNet classification with deep convolutional neural networks. Advances in Neural Information Processing Systems 25. link
  5. He, K., Zhang, X., Ren, S., & Sun, J. (2016). Deep residual learning for image recognition. In Proceedings of CVPR 2016 (pp. 770–778). link
  6. Redmon, J., Divvala, S., Girshick, R., & Farhadi, A. (2016). You only look once: Unified, real-time object detection. In Proceedings of CVPR 2016 (pp. 779–788). link
  7. Ultralytics. Models supported by Ultralytics (YOLO11, YOLO26). Ultralytics documentation. link
  8. Kirillov, A., et al. (2023). Segment anything. In Proceedings of ICCV 2023 (pp. 3992–4003). link
  9. Kalman, R. E. (1960). A new approach to linear filtering and prediction problems. Journal of Basic Engineering, 82(1), 35–45. link
  10. Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep learning. MIT Press. link

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

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

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

บรรยาย อภิปรายกรณีศึกษา และแก้โจทย์ในชั้นเรียน

หลักฐานการเรียนรู้: ผล quiz และแบบฝึกหัดที่ส่ง

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

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

โดเมนความรู้: ปัญญาประดิษฐ์และคอมพิวเตอร์วิทัศน์ · การสำรวจ ทำแผนที่ และภูมิสารสนเทศ · ความปลอดภัยสาธารณะและภัยพิบัติ