Project 03 · Skeleton Fall Detection · Co-Design

Model-Hardware Co-Design for
Skeleton-based Fall Detection on
Resource-Constrained Edge Platforms

Using a single camera to extract human skeletons, a tiny temporal convolutional network classifies fall vs. normal activity. The same model was deployed on PC, Jetson Nano, and FPGA (PYNQ-Z2) to validate feasibility, real-time performance, and accuracy on edge devices.

  • 95.65%固定測試集準確率
  • 0.42 ms單次模型推論
  • 92.39%FPGA 上板準確率
  • ~60 FPSFPGA 推論吞吐
  • 1D-CNN
  • MediaPipe Pose
  • PyTorch / ONNX
  • INT8 量化
  • Vitis HLS
  • PYNQ-Z2

為什麼要做這個題目?

這個題目的起點,其實來自專題二(DST-FallNet 多模態跌倒偵測)的實戰經驗……

這不只是學生專題才會踩到的問題……

因此專題三想換一個問法……

研究定位:貢獻在架構,不在準確率排行榜

專題三刻意與「把分類準確率刷到 SOTA」分道揚鑣……

這不代表準確率可以忽略……

相對地,主要貢獻落在架構與方法……

  • 主要貢獻:端到端管線……
  • 門檻指標:固定測試集上的 Accuracy……
  • 不是重點:在 URFD 小資料集上……
  • 與專題二互補……

研究目標與驗證範圍

  • 建立從 URFD 影像到骨架序列、再到 1D-CNN 分類的完整軟體管線
  • 在固定測試集上量測學術指標(Accuracy / Precision / Recall / F1)與 INT8 量化影響
  • 比較 PC、Jetson Nano 2GB、PYNQ-Z2 三平台的延遲、吞吐與部署特性
  • 以 Vitis HLS 實作可上板的 1D-CNN 加速器,並驗證 FPGA 準確率與 PC 參考一致率

核心命題

設計一個「硬體友善」的跌倒偵測模型……

從想法到上板:這條路是怎麼走出來的

專題一開始的直覺很單純:在邊緣硬體上做跌倒偵測,最好還能「上 FPGA」證明硬體價值。但真正動手後才發現,難點很少是某一個公式,而是每一步都要決定先驗什麼、後驗什麼——先讓軟體閉環可重現,再談跨平台比較;先確認模型能被量化與匯出,再談硬體加速;當 DPU 在 PYNQ-Z2 上走不通時,願意把問題改寫成「訂製加速器能證明什麼」,而不是硬撐一條黑盒路線。

因此這個專題的敘事不是「一開始就設計完美系統」,而是沿時間推進的策略調整:每個階段都留下可對照的產物(固定測試集、ONNX、CSV、bitstream),讓後面的結論能回頭被檢驗。下面依實際開發順序整理心路與策略,對應到後文各章節的技術細節。

依時間推進的開發策略

整體策略可以概括為「先軟後硬、先基準後對照、先誠實量測後下結論」。不一次把所有平台做完,而是每完成一階段就凍結產出,避免後面的實驗無法回頭比對。

階段一 · 問題定義

選擇「骨架 + 輕量模型」,而不是直接啃影像

在 URFD 跌倒場景下,先排除穿戴式與大型 CNN 兩條極端路線,改以 MediaPipe 抽骨架、用 1D-CNN 看時間變化。這一步的關鍵不是追 SOTA,而是預留 FPGA 可實作性:輸入固定、運算規律、參數量可控。模型從訓練第一天就採 ReLU6、無 Dropout、無 Conv bias,等於同時為軟體準確率與硬體綜合鋪路。

階段二 · 軟體閉環

先把「可重現」做出來,再談部署

完成抽骨架 → 訓練 → 固定 20% 測試集(seed=42)→ 匯出 deploy ONNX → INT8 量化(Delta = 0)。在進 Jetson 或 FPGA 之前,PC 端先跑通消融(跳幀 Stride 1–16)與瓶頸剖析。策略重點:任何跨平台數字都必須指向同一份模型與同一份測試集,否則比較沒有意義。

階段三 · 邊緣基準

用 Jetson 當「真實邊緣」對照組

將 ONNX Runtime 部署到 Jetson Nano 2GB,量測端到端 FPS 與 jitter。這一階段踩到 MediaPipe 裝不起來、CRLF 腳本、影片輸出異常等整合問題——解法改為 PC 離線抽骨架、Jetson 只跑推論。心路轉折:邊緣 AI 的時間常花在環境與資料格式,而非模型本身;這也預告了後續 profiler 的發現:pose_extract 佔約 96.71%。

階段四 · 路線轉彎

DPU 行不通時,改寫 FPGA 要回答的問題

原本規劃 Vitis AI + DPU,但 Zynq-7020 資源撐不住完整 IP。與其降規硬塞黑盒加速器,策略改為訂製 HLS 1D-CNN IP:只加速最關鍵的卷積、用 AXI-DMA 串接、權重從同一份 deploy ONNX 萃取。這是專題最重要的協同設計決策——模型結構為硬體而簡化,硬體任務也為模型而縮小,而非通用 AI 加速器套用。

階段五 · 上板定案

用實驗回答「FPGA 到底贏在哪」

PYNQ-Z2 上依序完成準確率(92.39%)、吞吐量(~60 FPS)、延遲抖動(Std ≈ 0.028 ms)量測,並誠實揭露 DMA 佔 16.62 ms 中的絕大部分、IP 計算僅 ~0.41 ms。開發策略收尾:不宣稱 FPGA 讓端到端變快 10 倍,而是論證其在確定性、低抖動與可預測延遲上的價值——這與 Jetson 軟體推論形成互補對照,而非單純數字競賽。

研究心路的底線

這份專題在現階段仍有大量顯而易見的系統問題與架構缺陷……

整體流程:從影像到警報

整個系統是一條清楚的資料流……

開發與驗證流程

從資料準備到硬體上板,專題依序完成下列階段。每一階段的產出都保留成可重現的檔案(.npy.onnxweights.h、實驗 CSV),目的是保證實驗的可重複性……

  1. 資料與訓練:URFD 解壓 → MediaPipe 抽骨架 → PyTorch 訓練 1D-CNN → 固定 20% 測試集(seed=42)
  2. 軟體部署與消融:匯出 ONNX(FP32 / INT8)→ PC / Jetson 推論與效能基準 → 跳幀消融、瓶頸剖析、失效樣本視覺化
  3. 硬體協同設計:從 deploy ONNX 萃取 INT8 權重 → Vitis HLS 綜合 IP → Vivado 整合 → PYNQ-Z2 上板準確率與延遲量測
端到端流程與三階段平台驗證
輸入是骨架關鍵點座標隨時間堆疊的序列

資料與輸入規格

資料來源為 URFD 公開跌倒資料集……

  • 36 維:18 個關鍵點的 (x, y) 座標
  • 50 幀:以滑動視窗取的時間長度
  • 座標已正規化到 0~1,偵測不到的點補 0
  • 測試集 92 筆,採 20% 切分、固定 seed=42
  • 訓練完成後另備 128 筆校準資料 供 INT8 量化使用
  • Fall 為正類;混淆矩陣、FNR 等學術指標皆在固定測試集上計算

資料集處理流程

本專題的模型從未直接吃原始像素……

  1. URFD 下載與整理:自官方頁面下載並解壓……
  2. MediaPipe 骨架擷取:逐幀送入 MediaPipe Pose,擷取 18 個關鍵點的 (x, y) 座標(共 36 維)。可見度低於門檻的關節點填 0;座標為影像正規化值(約 0~1),不保留原始畫面像素。
  3. 滑動視窗切樣本:以長度 50 幀、stride 25的滑動視窗,從連續骨架幀切出時間序列樣本,每筆形狀為 (36, 50)。過短序列可捨棄或以零填充,確保輸入尺寸固定——這對後續 ONNX 匯出與 FPGA 硬體配置至關重要。
  4. 彙整與固定測試集:合併為 x_data.npy(約 460 筆 × 36 × 50)與 y_labels.npy。以 seed=42 隨機切出 20% 固定測試集 → test_data.npy / test_labels.npy(92 筆),後續 PC、Jetson、FPGA 準確率實驗全部共用這 92 筆,避免各平台各切一份導致數字不可比。
  5. 量化校準集:訓練階段另產出 calibration_data.npy(128 筆),供 ONNX Runtime INT8 量化校準。實測量化後準確率與 FP32 相比 Delta = 0,證明資料前處理與模型設計對量化友善。
  6. 下游平台沿用:Jetson 無法安裝 MediaPipe 時,改讀 PC 離線產生的 .npy 做純推論;FPGA 上板則將測試集轉為 INT8 的 test_data_int8.npy,並以 pc_reference.csv 比對預測一致率——資料格式從訓練到硬體一路對齊。

關鍵資料檔案

  • x_data.npy / y_labels.npy — 全量骨架樣本與標籤
  • test_data.npy / test_labels.npy — 固定測試集(92 筆)
  • calibration_data.npy — INT8 量化校準(128 筆)
  • test_data_int8.npy — FPGA 上板推論輸入
  • pc_reference.csv — PC ONNX 參考預測,供 FPGA 一致率比對

為什麼堅持離線處理資料?

三個理由:隱私(不保存原始影像,只留骨架座標)、可重現(同一批 .npy 可反覆訓練與量測)、跨平台(Jetson 裝不起 MediaPipe 時仍能驗證模型推論)。代價是端到端 FPS 會被前處理主導——這也是後文瓶頸分析的重要前提。

三平台各自扮演的角色

PC (CPU)

開發基準:訓練、ONNX 匯出、消融實驗與瓶頸剖析的參考平台,提供最高吞吐的對照組。

Jetson Nano 2GB

邊緣軟體部署:在資源受限的 ARM + GPU 環境驗證 ONNX Runtime 推論,觀察 OS 排程對即時性的影響。

FPGA (PYNQ-Z2)

硬體加速器驗證:以 Zynq-7020 實作訂製 1D-CNN IP,強調確定性延遲、低功耗與可預測的推論行為。

刻意「為硬體著想」的 1D-CNN

模型本身刻意保持簡單……

輕量化 1D-CNN 架構

硬體友善的關鍵取捨

  • 用 ReLU6 取代 ReLU:輸出有上界……
  • 移除 Dropout:推論期無作用……
  • Conv 不含 bias:減少參數……
  • 固定輸入尺寸:(36, 50)……

為什麼選 1D-CNN?

跌倒的關鍵資訊在於「骨架隨時間的變化」……

訓練與部署管線

模型以 PyTorch 實作,輸入形狀 (N, 36, 50),輸出二分類 logits。訓練完成後匯出 fall_model_float32.onnx 作為所有平台的統一部署基準;再以 128 筆校準樣本做 INT8 量化,產生 fall_model_int8.onnx 供邊緣推論與 FPGA 權重萃取使用。

  • Block 1:Conv1d(36→64, k=3) + BN + ReLU6 + MaxPool → 時間維度減半
  • Block 2:Conv1d(64→128, k=3) + BN + ReLU6 + MaxPool → 再減半
  • 分類頭:AdaptiveAvgPool1d(1) + Linear(128→2),輸出 Fall / Non-Fall

訓練設定與 Early Stopping

訓練以驗證損失(val_loss)為早停依據……

訓練/驗證曲線……
  • 早停準則:監看 val_loss,patience=10,保留最佳模型
  • 觸發時機:約第 27 epoch(最大 50)提前停止
  • 用意:抑制小資料集過擬合,確保泛化可接受

最重要的決定:放棄 DPU,改做訂製加速器

專題中段遇到一個關鍵岔路……

原方案:DPU + Vitis AI

  • 黑盒式通用加速器
  • IP 體積大,Z2 資源不足
  • 偏向「使用工具」

採用:訂製 HLS 加速器

  • 模型結構為硬體而優化
  • 只加速最關鍵的卷積
  • AXI-DMA + AXI-Stream
軟硬體切分
Vivado Block Design……

HLS 加速器說明(design_1 Block Design)

這張圖是 PYNQ-Z2……

為什麼用 HLS 自研 IP?

做法 取捨
通用 DPU IP指令解碼、排程開銷大,對極輕量 1D-CNN 不划算
純 CPU(Jetson)延遲抖動較大,不利硬即時場景
HLS 客製 IP針對 (1, 36, 50) → (1, 2) 量身設計,資源與延遲可控

Block Design 各模組職責

processing_system7_0(Zynq PS)

載入 bitstream、準備輸入、啟動 DMA、讀回結果;透過 M_AXI_GP0 存取 PL 端 IP。

axi_dma_0(AXI DMA)

MM2S 把 DDR 中的 36×50 特徵送到 HLS IP;S2MM 把 2 維 logit 寫回 DDR。Stream 寬度 8 bit,與 ap_fixed<8,4> 對齊。

fall_detection_0(HLS IP)

核心加速器:s_axi_control 控制、AXI-Stream 輸入/輸出(輸出帶 TLAST)、m_axi_gmem0~5 從 DDR Burst Read 權重至 BRAM。

ps7_0_axi_periph(AXI Interconnect)

匯流排交換器,連接 PS、DMA 控制埠與 HLS 的 6 條 m_axi,共享 HP0_DDR_LOWOCM 存取 DDR。

rst_ps7_0_50M(Processor System Reset)

由 PS 的 FCLK_CLK0(50 MHz)產生 PL 同步重置。

一次推論的資料流

  1. PYNQ Python 將骨架特徵 (36×50) 放入 DDR buffer
  2. DMA MM2S 以 AXI-Stream 送入 input_stream_V(1800 bytes)
  3. HLS IP 透過 m_axi 載入權重至 BRAM,執行 1D-CNN
  4. 2 bytes 結果經 output_stream(TLAST=1)送回 DMA
  5. DMA S2MM 寫回 DDR,Python 讀取並 argmax 判斷 Fall / Non-Fall

DDR 輸入 buffer ──MM2S──► fall_detection_0 ──S2MM──► DDR 輸出 buffer;權重經 m_axi 從 DDR 讀入。硬體計算 ~0.41 ms,端對端 ~16.62 ms 多半花在 DMA 搬移。

FPGA 上板流程(PYNQ-Z2)

FPGA 端不重新訓練模型,而是沿用 PC 上匯出的 deploy ONNX,確保軟硬體比對有單一真實來源(Single Source of Truth)。完整流程如下:

  1. 權重萃取:從 fall_model_float32.onnx 產生 weights.h(INT8 定點權重)
  2. PC 參考:以 ONNX Runtime 對固定測試集推論,輸出 pc_reference.csv 作為一致率基準
  3. 硬體整合:Vitis HLS 綜合 1D-CNN IP → Vivado 建立 Block Design(PS + DMA + Accelerator)→ 產生 bitstream
  4. 上板驗證:上傳 bit / hwh / 測試資料至 PYNQ,執行準確率腳本,比對 FPGA 預測與 PC 參考

軟體端(PS)負責影像 I/O 與 MediaPipe 骨架擷取,屬於非確定性、OS 排程主導的路徑;硬體端(PL)只負責收到 INT8 骨架序列後的 1D-CNN 推論,提供固定延遲、可重複的計算行為——這正是本專題在邊緣場景想驗證的價值。

HLS C++ 實作重點

頂層函式 fall_detection()(Vitis HLS)刻意對應 PyTorch / ONNX 的每一層,讓硬體資源用在刀口上。

  • INT8 定點運算:以 ap_fixed<8,4> 取代浮點,對應軟體端 INT8 量化。
  • DATAFLOW + PIPELINE II=1:層間以 hls::stream 串接,內層迴圈每週期啟動一次。
  • memcpy + BRAM:權重一次性 Burst 載入 BRAM,避免計算中頻繁讀 DDR。
  • AXI-Stream + TLAST:與 DMA 正確握手,S2MM 能辨識傳輸結束。
  • ap_ctrl_none:無需 CPU 反覆 start/stop,stream 驅動即自動運算。
  • 通道數對齊並行度:36→64→128,DSP 用滿屬於針對此模型的 Right-Sizing。

權重與 m_axi 對應

Bundle 內容
gmem0Conv1 權重
gmem1Conv1 偏置
gmem2Conv2 權重
gmem3Conv2 偏置
gmem4FC 權重
gmem5FC 偏置

權重由 extract_weights_from_deploy_onnx.py 從 deploy ONNX 導出,編入 weights.h

FPGA 資源使用(Zynq-7020)

資源 使用率 說明
DSP48100%(220/220)卷積乘加主要由 DSP 承擔
BRAM~28%(39/140)權重 buffer、特徵圖暫存
LUT綜合偏高實作後 opt_design 通常會下降
FF~49%暫存器

與整體專題的關係

階段一(軟體):訓練硬體友善 1D-CNN · ReLU6 · INT8 量化 → 階段二(Jetson):邊緣基準 · 瓶頸分析(骨架擷取 ~97%)→ 階段三(FPGA):design_1 = HLS IP + DMA + Zynq 整合。實測上板準確率 92.39%,Jitter Std 0.028 ms,驗證協同設計在邊緣平台上的可行性——詳見 06 實驗結果

實作過程踩過的坑

把一個模型從 PC 一路推到 FPGA……

PYNQ-Z2 跑不動 DPU

板子資源不足以承載完整 DPU IP……

Jetson 裝不了 MediaPipe

Jetson 環境無法安裝 mediapipe……

Bash 腳本的 CRLF 問題

Windows 換行讓 Jetson 出現錯誤……

輸出影片歪斜、過快

畫面被拉伸、播放速度異常……

PC / Jetson 比較資料不足

比較腳本找不到對應設定的資料……

瓶頸不在模型而在前處理

剖析後發現骨架擷取佔了端到端 96% 的時間……

FPGA 延遲主要來自 DMA

上板後發現單次推論 16.62 ms 中,S2MM 傳輸約佔 16.11 ms,IP 計算僅 ~0.41 ms。這說明記憶體 I/O 才是 FPGA 端的真正瓶頸,而非卷積本身。

失效樣本難以用單一規則解釋

FN / FP 多發生在遮擋、蹲坐與跌倒動作相似、或骨架關鍵點缺失的片段。需要結合視覺化疊圖與 GIF 才能向論文讀者清楚說明錯誤原因。

數據怎麼說

實驗一覽

整個專題由六組獨立實驗構成,分別量測 Jetson 與 FPGA 的吞吐、抖動與準確率。它們共用同一份模型與固定測試集,因此數字可以互相對照。

實驗 平台 量測 關鍵結果
E1Jetson Nano宏觀吞吐~18 FPS
E2Jetson Nano延遲抖動Std ~0.28 ms
E3Jetson Nano準確率95.65%
E4FPGA PYNQ-Z2吞吐量~60 FPS
E5FPGA PYNQ-Z2延遲抖動Std ~0.028 ms
E6FPGA PYNQ-Z2準確率92.39%
E7Jetson Nano僅推論吞吐~1010 FPS

E7 特別說明問題核心:模型本身每秒可跑上千次,但端到端只有 ~18 FPS——慢的是前處理而非模型,這也是下方瓶頸分析的伏筆(Amdahl 定律)。

先講清楚:FPGA 實驗在驗證什麼

很容易誤會「PC > Jetson > FPGA」是效能排名。其實 PC 與 Jetson 量的是完整端到端(解碼 → MediaPipe → 推論),而 FPGA 量的是固定骨架測試集的推論正確性與延遲,刻意跳過前處理。所以 FPGA 的目的不是解決 96% 的骨架擷取瓶頸,而是驗證協同設計的正確性與硬體的確定性——它與 Jetson 是互補關係,不是同一把尺。

可行性驗證:準確率與量化

以下準確率與量化數字在專題三中的角色是可行性驗證……

固定測試集混淆矩陣(92 筆)
指標數值
Accuracy95.65%
Precision93.33%
Recall93.33%
F1-score93.33%

INT8 量化後準確率維持 95.65%……

以 Fall 為正類,固定測試集(92 筆)上的 FNR 為 0.0667,代表多數跌倒事件能被正確捕捉。FPGA 上板準確率為 92.39%(85/92),與 PC ONNX 參考之間的落差主要來自定點量化與 DMA 傳輸鏈路的累積誤差,仍在可接受範圍內。

跳幀消融:準確率 vs. 速度

跳幀步長對準確率與 FPS 的影響

透過「跳幀」可以用準確率換取速度……

  • Stride 1:93% / 20.97 FPS
  • Stride 4:89% / 46.13 FPS
  • Stride 8:84% / 76.18 FPS
  • Stride 16:75% / 84.25 FPS

系統瓶頸分析

端到端各階段耗時占比

把端到端流程拆成五個階段後……

階段 平均耗時 占比
read_decode0.69 ms2.02%
pose_extract33.06 ms96.71%
preprocess0.016 ms0.05%
inference0.42 ms1.22%
postprocess_draw<0.001 ms~0%

這個發現很重要……

前 100 幀 FPS 穩定性:約第 50 幀後因系統負載與 I/O 波動而下降

跨平台效能比較

PC 與 Jetson Nano 2GB 的端到端 FPS
FPGA 推論延遲分佈
平台 模型推論延遲 推論 FPS 特性 / 優勢
PC (CPU) ~0.42 ms ~191 (端到端) 高吞吐,但高功耗、延遲不確定
Jetson Nano 2GB ~0.42 ms ~18 (端到端) 易開發,受 OS 排程影響
FPGA (PYNQ-Z2) 0.41 ms(IP)/ 16.62 ms(含 DMA) ~60.25 確定性延遲、低功耗、即時性

值得注意的是,FPGA 上 16.62 ms 的延遲中……

PC 在 Stride=1、No-Draw 設定下端到端 FPS 約 190.61,Jetson 約 18.11——差距主要來自骨架擷取與解碼在嵌入式 CPU 上的負擔,而非 1D-CNN 本身(兩者模型推論皆約 0.42 ms)。這也呼應了前述瓶頸分析:若要提升實際體感速度,應優先優化 MediaPipe 或改為預先離線抽骨架,而非一味加大模型加速器。

延遲量測範圍:別把三種「速度」混在一起

不同平台的延遲數字其實量的是不同東西,直接比絕對值會誤導。真正反映架構差異的不是延遲大小,而是延遲的穩定度(Jitter)

指標 Jetson FPGA 量的是什麼
核心推論延遲~1.3 ms~0.41 ms(IP)算一次 forward 要多久
系統單幀延遲1–4 ms 波動~16.6 ms 穩定一幀完整走完推論
抖動(Jitter, Std)~0.28 ms~0.028 ms延遲的穩定度

以下圖表在同一模型、同一固定骨架測試集、純推論路徑下……

跨平台抖動對照……

關鍵結論:FPGA 單幀延遲含 DMA 看似較大,但抖動只有 Jetson 的約 1/11……

失效樣本分析

檢視模型判斷錯誤的案例……

在 92 筆測試樣本中,共標記 4 筆具代表性的錯誤案例……

把四筆錯誤歸納起來,其實對應到跌倒偵測領域的三種典型成因,而且大多不是分類器本身的缺陷

FN

標籤雜訊 · FN #54

該片段多為站立姿態……

疊圖
FN #54 多幀骨架疊圖……
動畫
FN #54 逐幀動畫……
FN

前處理失敗 · FN #60

幾乎抽不到關鍵點……

疊圖
骨架疊圖幾乎空白……
時序
Mean Y 時序……
動畫
逐幀動畫……
FP

坐–跌混淆 · FP #26 / #83

兩筆都是「準備坐下」的動作……

#26
FP #26……
#83
FP #83……

總結與收穫

這個專題完整走過了全流程……

  • 輕量 1D-CNN 在固定測試集達 95.65% 準確率……
  • 同一模型成功部署到 PC、Jetson、FPGA 三平台……
  • FPGA 上板準確率 92.39%……
  • 剖析證實瓶頸在骨架擷取……
  • 從 DPU 轉向訂製加速器……

最大的收穫

學到的不只是「怎麼把模型變小」……

未來可延伸方向

  • 優化 DMA 與資料搬移策略,縮短 FPGA 端 S2MM 佔比,逼近 IP 本身的 0.41 ms 計算下限
  • 將 MediaPipe 替換為更輕量的姿態估計器,或改以專用感測器提供骨架,解決端到端 96% 前處理瓶頸
  • 在更大 FPGA 或異質 SoC 上探索更多層的硬體 offload,並與 INT8 量化流程深度整合
  • 把完整端到端搬上 FPGA:影像 → 骨架 → PL 推論,量測真實場景的端到端確定性
  • 以 Host–Device 架構運作:智慧攝影機前端抽骨架,透過 Ethernet / Socket 把特徵送進 FPGA 推論
  • 擴充資料集與負樣本(坐下、彎腰等),針對坐–跌混淆強化時序與情境特徵
← 返回專案列表 回首頁