จับโป๊ะคนแอบหลับ! สร้าง AI ตรวจจับคนสัปหงกด้วย Raspberry Pi AI Camera

Dozing off detection using Raspberry Pi AI Camera
เมื่อกล้อง AI สามารถจับผิดพฤติกรรมการแอบหลับได้อย่างแม่นยำ!

สวัสดีชาว Maker และนักพัฒนาสาย AI ทุกคนครับ! คุณเคยประสบปัญหาเวลานั่งเรียนหรือทำงานแล้วเผลอ "สัปหงก" แอบหลับกันบ้างไหมครับ? ในฐานะนักเรียนมันอาจจะดูตลกดี แต่ถ้าคุณเป็นอาจารย์หรือคนคุมสอบ การเห็นคนแอบหลับคงไม่ใช่เรื่องน่ายินดีเท่าไหร่นัก หรือแม้แต่ในร้านอาหารที่คนพลุกพล่าน การรู้ว่ามีใครกำลังหลับอยู่ก็ช่วยให้เราเข้าไปตรวจสอบหรือให้ความช่วยเหลือได้ง่ายขึ้น

วันนี้เรามีโปรเจกต์สนุกๆ ที่จะพาคุณมาสร้าง แอปพลิเคชันตรวจจับคนแอบหลับ (Dozing Detection) ด้วยอุปกรณ์สุดล้ำอย่าง Raspberry Pi AI Camera บอกเลยว่างานนี้ไม่ต้องใช้ความรู้ด้านโปรแกรมมิ่งหรือ AI ระดับเทพก็ทำตามได้ครับ ขอแค่มีพื้นฐาน Python กับ Git นิดหน่อย ก็ลุยกันได้เลย!

Step 1: เตรียมฮาร์ดแวร์และการตั้งค่า (Setup)

ก่อนอื่นเราต้องจัดการเตรียมอุปกรณ์ฮาร์ดแวร์และซอฟต์แวร์ให้พร้อมทำงานกันก่อนครับ โดยพระเอกของงานนี้คือตัวกล้องและบอร์ดประมวลผล

  • คุณสามารถอ่านคู่มือการตั้งค่ากล้องแบบละเอียดได้ที่ Raspberry Pi AI camera setup guide เพื่อเตรียม OS ให้พร้อม (แนะนำให้ใช้ระบบปฏิบัติการ Raspbian ที่อัปเดตล่าสุด)
  • สำหรับเครื่องมือจัดการแพ็กเกจ Python ในโปรเจกต์นี้เราจะใช้ uv ซึ่งสามารถดูวิธีติดตั้งได้ที่ UV documentation
  • เราจะใช้ไลบรารีสำเร็จรูปที่ชื่อว่า AITRIOS RPi Application Module Library เพื่อช่วยให้การดึงภาพและ AI ง่ายขึ้น สามารถเข้าไปดูคลังข้อมูลได้ที่ Modlib repo

💡 Maker's Tip: โปรเจกต์นี้จะทำงานได้อย่างลื่นไหลที่สุดเมื่อใช้ร่วมกับบอร์ดรุ่นใหม่อย่าง Raspberry Pi 5 คู่กับกล้อง Camera Module V2 หรือ AI Camera และถ้าอยากให้มีหน้าจอ Dashboard ดูค่าสถานะแบบเรียลไทม์ ก็จัด Raspberry Pi Touch Display เพิ่มไปอีกตัวได้เลย!

หากเพื่อนๆ คนไหนสนใจอยากลองเล่นหรือกำลังหาอุปกรณ์ฮาร์ดแวร์เหล่านี้ แวะมาช้อปปิ้งของแท้พร้อมส่งได้ที่ Globalbyte เลยครับ! ของดีของครบ พร้อมประกอบใช้งานทันที

Step 2: ให้ AI ช่วยวาดโครงกระดูก (Skeleton Estimation)

การจะรู้ว่าใครกำลัง "สัปหงก" หรือไม่ เราไม่ได้ดูจากการหลับตานะครับ แต่เราจะดูจากการที่ "ร่างกายหรือศีรษะอยู่นิ่งเป็นเวลานานเกินไป" หรือมีการก้มหน้าลง ซึ่งเทคโนโลยีที่จะเข้ามาช่วยเราตรงนี้เรียกว่า PoseNet (การประเมินโครงสร้างร่างกาย) ครับ

ด้วยไลบรารี Modlib ที่เราเพิ่งโคลนมา มันมีตัวอย่างโค้ดที่สามารถวาดเส้นโครงร่างร่างกาย (Keypoints) ให้เราได้เลยทันที ไม่ต้องมานั่งเขียน AI คำนวณเองให้ปวดหัว แค่รันคำสั่งตัวอย่าง คุณก็จะเห็นจุดสีๆ ตามข้อต่อของร่างกายโผล่ขึ้นมาบนหน้าจอแล้วครับ แม้ว่าจะใส่แมสก์หรือก้มหน้าอยู่ AI ก็ยังจับได้แม่นยำมาก!

PoseNet Keypoint Detection
การทำงานของ PoseNet ที่สามารถพล็อตจุด Keypoints บนร่างกายได้อย่างแม่นยำ
Terminal Output and UV setup
ผลลัพธ์การเรียกใช้งานสคริปต์ผ่าน Terminal ด้วยคำสั่ง uv run

Step 3: เขียนลอจิกจับผิดคนหลับ (The Logic)

ทีนี้มาถึงหัวใจหลักของโปรแกรมครับ เราจะเขียนลอจิกให้ AI ตัดสินว่าคนนี้กำลังหลับอยู่หรือไม่ โดยอาศัยหลักการเปรียบเทียบ "ระยะทาง" ของจุด Keypoints ระหว่างเฟรมภาพก่อนหน้า กับ เฟรมภาพปัจจุบันครับ โฟลว์การทำงานจะเป็นแบบนี้:

  1. Save skeleton data: บันทึกค่าจุดพิกัด (X, Y) ของร่างกายเก็บไว้ในลิสต์ poses_record
  2. Compute KeyPoint distance: เอาพิกัดเฟรมล่าสุด มาลบกับเฟรมก่อนหน้า เพื่อดูว่ามีการขยับตัวไหม
  3. Check Distance > threshold?: ถ้าระยะการขยับ "น้อยกว่า" ค่าที่ตั้งไว้ (แทบไม่ขยับเลย) ให้บวกคะแนนความนิ่ง (motionless_count++) แต่ถ้าขยับตัวแรงๆ ให้รีเซ็ตคะแนนเป็น 0
  4. Evaluate motionless_count: ถ้าคะแนนความนิ่งสะสมเกินค่าที่ตั้งไว้ (SLEEP_THRESHOLD) ระบบจะฟันธงว่า "หลับชัวร์!"
  5. UI Display: ใช้ไลบรารี OpenCV เพื่อสั่งพิมพ์ตัวอักษรสีแดงคำว่า "SLEEP" ตัวใหญ่ๆ ทับลงไปบนวิดีโอเลย

เราสามารถนำโค้ดด้านล่างนี้ไปเซฟเป็นไฟล์ SleepDetection.py แล้วใช้คำสั่ง uv run SleepDetection.py เพื่อให้ระบบเริ่มจับภาพได้เลยครับ

SleepDetection.py
import time
import numpy as np
from modlib.apps import Annotator
from modlib.devices import AiCamera
from modlib.models.zoo import Posenet
import cv2

# Definition of const
KEYPOINT_NAME = [
    "nose",             #0
    "leftEye",          #1
    "rightEye",         #2
    "leftEar",          #3
    "rightEar",         #4
    "leftShoulder",     #5
    "rightShoulder",    #6
    "leftElbow",        #7
    "rightElbow",       #8
    "leftWrist",        #9
    "rightWrist",       #10
    "leftHip",          #11
    "rightHip",         #12
    "leftKnee",         #13
    "rightKnee",        #14
    "leftAnkle",        #15
    "rightAnkle"        #16
]

KEYPOINT_THRESHOLD = 5
DISTANCE_THRESHOLD = 100
KEYPOINT_SCORE_THRESHOLD = 0.5
SLEEP_THRESHOLD = 10
PAUSE_AFTER_DETECTION = 0.5  # (seconds)
TEXT = "SLEEP"

# Track motionless
def track_motionless(w, h, poses_record, motionless_count):
    keypoint_count = 0
    # Calculate the coordinate difference between the previous frame and the current frame
    for keypoint_idx in range(len(KEYPOINT_NAME)):
        if (poses_record[0].keypoint_scores[0][keypoint_idx] >= KEYPOINT_SCORE_THRESHOLD and 
            poses_record[1].keypoint_scores[0][keypoint_idx] >= KEYPOINT_SCORE_THRESHOLD):
            x0 = int(poses_record[0].keypoints[0][keypoint_idx][0] * w)
            y0 = int(poses_record[0].keypoints[0][keypoint_idx][1] * h)
            x1 = int(poses_record[1].keypoints[0][keypoint_idx][0] * w)
            y1 = int(poses_record[1].keypoints[0][keypoint_idx][1] * h)
            print(f"{KEYPOINT_NAME[keypoint_idx]}   x:{x0}, y:{y0}")
            
            distance = (x1 - x0)**2 + (y1 - y0)**2
            if distance < DISTANCE_THRESHOLD:
                keypoint_count += 1
    
    if keypoint_count >= KEYPOINT_THRESHOLD:
        print("[INFO] Detected 5 or more KeyPoints.")
        motionless_count += 1
    else:
        motionless_count = 0
    
    return motionless_count

# Display Text
def display_text(image):
    print("[INFO] Display Text")
    cv2.putText(image,
            text=TEXT,
            org=(100, 50),
            fontFace=cv2.FONT_HERSHEY_SIMPLEX,
            fontScale=2.0,
            color=(0, 0, 255),
            thickness=3) 

# Detection by modlib
def detect_sleep():
    print("[INFO] Starting sleep detection.")
    device = AiCamera()
    model = Posenet()
    device.deploy(model)

    annotator = Annotator()

    last_detection_time = 0
    motionless_count = 0
    poses_record = []

    with device as stream:
        for frame in stream:
            current_time = time.time()
            if current_time - last_detection_time > PAUSE_AFTER_DETECTION:
                last_detection_time = time.time()

                h, w, _ = frame.image.shape

                poses = frame.detections
                poses_record.append(poses)
                if len(poses_record) > 2:
                    poses_record.pop(0)
                    motionless_count = track_motionless(w, h, poses_record, motionless_count)

                print(f"Motionless Count: {motionless_count}")
                if motionless_count > SLEEP_THRESHOLD:
                    print("[INFO] Detect Sleep")
                    display_text(frame.image)

                annotator.annotate_keypoints(frame, frame.detections)
                frame.display()

# Main
if __name__ == "__main__":
    detect_sleep()

บทสรุปและการต่อยอด (Conclusion)

เป็นยังไงกันบ้างครับ? การใช้บอร์ดและกล้อง AI สมัยนี้ทำให้เราเขียนโปรแกรมดึงเอาความสามารถระดับ Deep Learning มาใช้งานได้แบบง่ายๆ ด้วยโค้ดไม่กี่บรรทัด

บางคนอาจจะมองว่าการซื้อกล้อง AI มาเพื่อจับคนหลับอย่างเดียวอาจจะดูสิ้นเปลืองไปนิด แต่จริงๆ แล้ว Raspberry Pi AI Camera เป็นแพลตฟอร์มที่อเนกประสงค์มากๆ ครับ คุณสามารถดัดแปลงโค้ดชุดนี้ไปทำโปรเจกต์ Computer Vision อื่นๆ ได้อีกเพียบ ไม่ว่าจะเป็นการนับจำนวนคน, การตรวจจับท่าทางออกกำลังกาย หรือทำระบบกันขโมย ก็ลุยได้หมดเลยครับ!

อ้างอิงและเรียบเรียงข้อมูลจาก: Globalbyteshop Blog

แหล่งที่มาบทความต้นฉบับ: Hackster.io - I've Found Someone Dozing Off with Raspberry Pi AI Camera (by Patrick Johnson)

*คำเตือน: เนื้อหานี้เป็นการสรุปและเรียบเรียงแนวคิดจากโปรเจกต์บทความต้นฉบับภาษาอังกฤษ โค้ดที่นำเสนอถูกออกแบบมาเพื่อการศึกษาเรียนรู้ (Educational purposes) การตั้งค่าขีดจำกัดความแม่นยำ (Threshold) อาจแตกต่างกันไปตามสภาพแวดล้อมและแสงสว่าง หากต้องการศึกษาเอกสารเชิงลึกเกี่ยวกับการติดตั้ง uv และ modlib โปรดอ้างอิงและตรวจสอบการอัปเดตไลบรารีจาก เว็บไซต์ต้นฉบับ ก่อนลงมือทำ

 

แท็ก


Blog posts

เข้าสู่ระบบ

ลืมรหัสผ่านใช่ไหม?

ยังไม่มีบัญชีใช่ไหม?
สร้างบัญชี