สร้าง AI ตรวจจับอุบัติเหตุในฟิตเนส ด้วย Raspberry Pi AI Camera

Gym Injury Detection with Raspberry Pi AI Camera

ป้องกันอันตรายในยิมด้วยเทคโนโลยี AI

เดี๋ยวนี้ใครๆ ก็ฮิตไปเข้าฟิตเนสกันใช่ไหมครับ! แม้ว่าการดูแลสุขภาพจะเป็นเรื่องดี แต่ "ความปลอดภัย" ในยิมก็เป็นเรื่องใหญ่ที่มองข้ามไม่ได้เลย เพราะอุบัติเหตุหรือปัญหาสุขภาพกะทันหันสามารถเกิดขึ้นได้ตลอดเวลาระหว่างออกกำลังกาย และความรวดเร็วในการเข้าช่วยเหลือคือสิ่งที่สำคัญที่สุด

ในบทความนี้ เราจะมาสร้างแอปพลิเคชันที่สามารถตรวจจับ "คนที่อาจจะได้รับบาดเจ็บ" โดยเฉพาะคนที่หยุดเคลื่อนไหวหรือนอนนิ่งอยู่ใกล้ๆ กับเครื่องออกกำลังกายครับ เราจะใช้ Raspberry Pi AI Camera ซึ่งเป็นโมดูลกล้อง Edge AI สำหรับ Raspberry Pi ที่ขับเคลื่อนด้วยขุมพลังเซ็นเซอร์อัจฉริยะ IMX500 จาก Sony นั่นเอง!

View more (ดูวิดีโอสาธิตการทำงานของ AI)

อุปกรณ์ที่ต้องใช้ (Hardware Components)

ของที่ต้องเตรียมสำหรับโปรเจกต์นี้มีดังนี้ครับ:

  • บอร์ด Raspberry Pi (ในบทความนี้ใช้ Raspberry Pi 5)
  • microSD card ที่ลงระบบปฏิบัติการ Raspberry Pi OS (64-bit) เรียบร้อยแล้ว
    ข้อควรระวัง: แอปพลิเคชันนี้ทำงานได้เฉพาะบนเวอร์ชัน Bookworm เท่านั้นนะครับ!
  • อแดปเตอร์จ่ายไฟ (AC adapter)
  • โมดูลกล้อง Raspberry Pi AI Camera (1 ตัว)
  • อุปกรณ์พื้นฐานอื่นๆ: จอมอนิเตอร์, คีย์บอร์ด, เมาส์, สาย HDMI ฯลฯ

💡 ทริคเพิ่มเติม: หากคุณกำลังมองหาสถานที่สั่งซื้อบอร์ด Raspberry Pi 5 หรือ AI Camera รวมไปถึงอุปกรณ์เสริมต่างๆ ในไทย สามารถเข้าไปดูสินค้าและสั่งซื้อได้ง่ายๆ ที่ https://openlink.co/globalbyte เลยครับ!

ขั้นตอนการทำโปรเจกต์ (Procedure)

1. เตรียมฮาร์ดแวร์ให้พร้อม
ประกอบบอร์ด Raspberry Pi เสียบสายต่างๆ และเตรียมระบบปฏิบัติการ Bookworm ให้เรียบร้อย

2. ตั้งค่ากล้อง Raspberry Pi AI Camera
ทำการตั้งค่าการสื่อสารระหว่างบอร์ดกับกล้อง AI Camera โดยสามารถทำตามขั้นตอนใน the official documentation (คู่มืออย่างเป็นทางการ) ได้เลยครับ

3. ติดตั้ง Application Module Library
ไลบรารีตัวนี้ (Application Module Library) เป็น SDK จาก Sony Semiconductor Solutions ที่มีเครื่องมือสำหรับการแสดงผลข้อมูล (Data visualization) และการพัฒนาแอปพลิเคชันมาให้ครบถ้วน

ให้ทำตามคำแนะนำในไฟล์ Application Module Library README file บน GitHub เพื่อติดตั้ง SDK ให้เรียบร้อย

View more (ดูโค้ดทดสอบกล้อง และรูปภาพผลลัพธ์)

เมื่อติดตั้งเสร็จแล้ว ลองทดสอบด้วยการรันสคริปต์ตัวอย่างที่มีมาให้ใน Repository ครับ:

# Activate the virtual environment where the Application Module Library (modlib) is installed cd aitrios-rpi-application-module-library python3 examples/aicam/posenet.py

ถ้ามีหน้าต่างเด้งขึ้นมา และสามารถแสดงผลการแทร็กโครงกระดูกมนุษย์ (Skeletal tracking) ได้อย่างถูกต้อง ก็แปลว่าสภาพแวดล้อมของคุณพร้อมลุยแล้ว!

PoseNet Sample Skeleton Tracking

4. การสร้างแอปพลิเคชันตรวจจับผู้บาดเจ็บ
หมายเหตุ: โค้ดฉบับเต็มของแอปพลิเคชันที่เราจะพูดถึงในส่วนนี้ สามารถเข้าไปดูได้ที่ Sony Semiconductor Solutions on GitHub เลยครับ แนะนำให้เข้าไปดูโครงสร้างและรายละเอียดการเขียนโค้ดแบบเต็มๆ ได้ที่นั่น

เจาะลึก: นิยามของ "คนเจ็บ" ในฟิตเนส

ก่อนจะเขียนโค้ด เราต้องนิยามให้ AI เข้าใจก่อนว่าแบบไหนถึงเรียกว่าคนเจ็บ? ในแอปนี้เรากำหนดเงื่อนไขไว้ 2 ข้อครับ:

  • A. ไม่มีการขยับแขนขาเป็นระยะเวลาหนึ่ง: การดูแค่จุดศูนย์กลางลำตัวมันบอกไม่ได้ครับว่าเขากำลังเล่นกล้ามอยู่หรือเปล่า เราเลยต้องโฟกัสไปที่ "การเคลื่อนไหวของแขนและขา" แทน
  • B. อยู่ใกล้กับเครื่องออกกำลังกาย: ถ้าเขาไปนอนพักในโซนนั่งพักไกลๆ เครื่องเล่น เราจะไม่นับว่าเขาเป็นคนเจ็บครับ
Injured Person Detection Concept

ฟีเจอร์หลักในการเขียนแอปพลิเคชัน

แอปนี้มีฟีเจอร์เด่นๆ 4 อย่าง ซึ่งผมได้ตัดโค้ดบางส่วนมาอธิบายให้ดูครับ (สามารถกดดูโค้ดได้ในปุ่ม View more)

View more (ดู Code Snippet การทำงานทั้ง 4 ฟีเจอร์)

1. การใช้ PoseNet เป็น AI Model
เราใช้โมเดล PoseNet (โมเดลประเมินโครงร่างมนุษย์) ในการจับการเคลื่อนไหวของแขนขา โค้ดการตั้งค่ากล้องและโมเดลมีดังนี้:

# Camera and model initialization function def initialize_camera(): device = AiCamera() model = Posenet() device.deploy(model) return device, Annotator() device, annotator = initialize_camera()

2. การกำหนดพื้นที่เฝ้าระวัง (Monitoring Area)
ในไฟล์ app.py เราจะกำหนดพื้นที่ตรวจสอบเป็นหน่วยพิกเซล (จอรวมขนาด 640x480) จากนั้นหาจุดศูนย์กลางลำตัวจากอาร์เรย์ Keypoints (จุดสังเกตโครงกระดูกที่ PoseNet ให้มา) เพื่อเช็คว่าคนๆ นั้นอยู่ในโซนเครื่องเล่นหรือไม่

monitoring_area = {'x': 100, 'y': 100, 'width': 300, 'height': 300} # Function to calculate the center point of a person def get_center_point(keypoints): valid_points = [kp for kp in keypoints if kp['x'] > 0.0 and kp['y'] > 0.0] if not valid_points: return None sum_x = sum(kp['x'] for kp in valid_points) sum_y = sum(kp['y'] for kp in valid_points) return {'x': sum_x / len(valid_points), 'y': sum_y / len(valid_points)} # Function to check if a point is in the monitoring area def is_point_in_area(point, area): if not point: return False return (point['x'] >= area['x'] and point['x'] <= area['x'] + area['width'] and point['y'] >= area['y'] and point['y'] <= area['y'] + area['height'])

3. การประมวลผลข้อมูลตามเวลา (Time-series Processing)
เราจะเปรียบเทียบเฟรมภาพที่เก่าที่สุดกับใหม่ที่สุดในช่วงเวลาหนึ่ง เพื่อดูว่าแขนขามีการขยับหรือไม่ โดยโฟกัสไปที่ Keypoints อย่าง "ข้อมือและหัวเข่า" ซึ่งขยับบ่อยตอนออกกำลังกาย หากระยะการขยับน้อยกว่าเกณฑ์ที่ตั้งไว้ (Threshold) ระบบจะสั่งเปิดแจ้งเตือน (Alert) ทันที

motion_settings = {'time_window': 6, 'movement_threshold': 10000, 'check_interval': 1} # Periodically check motion current_time = time.time() if current_time - person_tracker.last_check_time >= motion_setting['check_interval']: check_movement() person_tracker.last_check_time = current_time # Function to check motion def check_movement(): global person_tracker, alert_active # Do not check if no person is in the area if not person_tracker.in_area or len(person_tracker.positions) < 2: return current_time = time.time() # Get data within a certain time window cutoff_time = current_time - motion_settings['time_window'] valid_positions = [p for p in person_tracker.positions if p['timestamp'] >= cutoff_time] # Check if there is enough data if len(valid_positions) >= 2: # Calculate the amount of motion movement_amount = calculate_movement_specific_keypoints(valid_positions) person_tracker.last_movement = movement_amount # Trigger alert if below the threshold if movement_amount < motion_settings['movement_threshold']: alert_active = True print("No Motion Detected:", movement_amount, "<", motion_settings['movement_threshold']) else: # Clear alert if there is enough motion alert_active = False print("Motion Detected :", movement_amount, ">", motion_settings['movement_threshold']) MOTION_CHECK_KEYPOINTS = [9, 10, 13, 14] # leftWrist, rightWrist, leftKnee, rightKnee # Function to calculate motion for specific keypoints (both wrists and both knees) def calculate_movement_specific_keypoints(positions): # Get the oldest and newest positions oldest = positions[0] newest = positions[-1] # Get frame size w, h = oldest['frame_size'] total_distance = 0 valid_keypoint_count = 0 # Check only specific keypoints (both wrists and both knees) for keypoint_idx in MOTION_CHECK_KEYPOINTS: # Find corresponding keypoints in the old and new frames old_kp = next((kp for kp in oldest['keypoints'] if kp['id'] == keypoint_idx), None) new_kp = next((kp for kp in newest['keypoints'] if kp['id'] == keypoint_idx), None) # If keypoints are detected in both frames if old_kp and new_kp: # Convert to pixel coordinates x0 = int(old_kp['x'] * w) y0 = int(old_kp['y'] * h) x1 = int(new_kp['x'] * w) y1 = int(new_kp['y'] * h) # Calculate squared distance (Euclidean distance squared) distance = (x1 - x0)**2 + (y1 - y0)**2 total_distance += np.sqrt(distance) # Take square root for actual distance valid_keypoint_count += 1 # Return average distance if there are valid keypoints, otherwise 0 if valid_keypoint_count > 0: return total_distance / valid_keypoint_count else: return 0

4. การแสดงผลแบบ Web Application
ผลการประมวลผลทั้งหมดจะถูกเก็บไว้ในตัวแปร frame_buffer แล้วส่งออกไปเป็นวิดีโอสตรีมแบบ MJPEG ให้เราดูผ่านเว็บบราวเซอร์ได้แบบเรียลไทม์เลยครับ

def generate_frames(): global frame_buffer while True: # Wait until the frame buffer is available if frame_buffer is not None: with frame_lock: yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame_buffer + b'\r\n') # Short wait time time.sleep(0.03) # Video stream endpoint @app.route('/video_feed') def video_feed(): return Response(generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')

สำหรับข้อมูลเพิ่มเติมและไฟล์ Static สำหรับทำ Web App สามารถเข้าไปดูที่ Sony Semiconductor Solutions repository on GitHub ได้เลยครับ

การรันแอปพลิเคชัน (Running the Application)

สั่งรันแอปด้วยคำสั่ง python3 app.py ในเทอร์มินัล จากนั้นเปิดเว็บบราวเซอร์แล้วเข้าไปที่ http://localhost:5000 คุณก็จะเห็นภาพจากกล้องพร้อมระบบ AI ที่กำลังตรวจจับคนในยิมทำงานอยู่ทันทีครับ!

เจอปัญหาทำยังไงดี? & บทสรุป

ถ้าคุณเจอปัญหาตอนทำตามบทความนี้ สามารถเข้าไปตั้งกระทู้ถามใน Raspberry Pi Forums ได้เลยครับ สังคมนักพัฒนายินดีช่วยเหลือเสมอ

สรุปทิ้งท้าย: เราได้สร้างแอปพลิเคชันตรวจจับผู้ได้รับบาดเจ็บในฟิตเนสสำเร็จแล้ว! และที่น่าตื่นเต้นคือ ฟีเจอร์ที่เรานำมาใช้ ไม่ว่าจะเป็นการจับโครงกระดูกด้วย PoseNet, การกำหนดพื้นที่เฝ้าระวัง, การประมวลผลเทียบเวลา และการแสดงผลบน Web App สิ่งเหล่านี้สามารถนำไปดัดแปลงใช้กับสถานการณ์อื่นๆ ได้อีกนับไม่ถ้วนเลยครับ... พร้อมจะสร้างสรรค์ผลงานของคุณเองหรือยัง? ลุยเลย!

พร้อมสร้างโปรเจกต์ AI ของคุณเองหรือยัง?

หากสนใจบอร์ด Raspberry Pi 5 และอุปกรณ์เสริมต่างๆ สำหรับทำโปรเจกต์ AI แบบนี้ แวะมาหาเราได้เลยครับ!

คำเตือน: เนื้อหานี้เป็นการสรุปและเรียบเรียงจากบทความต้นฉบับภาษาอังกฤษ ข้อมูลฉบับภาษาไทยอาจมีความคลาดเคลื่อนบางประการจากการตีความหรือย่อเนื้อหา โปรดอ้างอิงและตรวจสอบโครงสร้างโค้ดโดยละเอียดจากต้นฉบับ
อ้างอิงจาก (References):

แท็ก


Blog posts

เข้าสู่ระบบ

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

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