Skip to content

DetectManager

j32u4ukh edited this page Jun 9, 2020 · 4 revisions

提供動作比對的核心演算法,透過 delegate 讓外部腳本根據自身需求,定義比對的動作、以及額外正確率的傳入。

detectManager

實際在迴圈中進行偵測的函式是 detectManager ,DetectManager 當中提供實際的 Player 給函式來進行比對

setDetectDelegate

透過 setDetectDelegate 將 detectManager 指向外部定義的函式

detectRaiseTwoHands

detectRaiseTwoHands 以 Player 為參數,取得要比對的動作(Pose)後進行客製化的比對

同時也提供了關節數據紀錄,只需告訴 DetectManager 何時開始記錄,何時結束即可。

偵測原理

將一個動作視為多個分解動作,進行多次的姿勢配對。

圖片代替文字

姿勢配對

由深度感測器所捕捉到的關節點位置(以下稱玩家關節點),會透過 Kinect 的工具轉換成模型的關節點位置,利用這些關節點和事先決定好的關節點(以下稱比對標準關節點)進行比較。

圖片代替文字

事先決定好的關節點可以是從調整過姿勢的模型取得,也可以將關節點的位置數據儲存,需要的時候再讀取進來。

比較方式

分別從玩家關節點和比對標準關節點各取兩個關節點(玩家 2 個,比對標準 2 個),各自形成一條三維的向量(x, y, z),須轉換為單位向量。

圖片代替文字

透過計算兩個向量的內積,進一步取得兩向量之間的夾角。夾角越小,表示兩個向量越接近。

圖片代替文字

這裡沿用 Kinect 原始的姿勢比對的定義,將角度轉換為 0 ~ 1 的數值,差異最大為 90 度,因此超過 90 度都換轉換為 1。 又,我們需要的是正確率,因此會再用 1 減掉該數值。

第一點和第二點形成一條向量,第二點和第三點形成一條向量,以此類推,而最後一點會和第一點再形成一條向量。

Flag

為提供外部腳本在使用偵測函式上有更大的彈性(例如:開始 3 秒後再開始使用動態門檻值),提供了以下幾種 Flag。

public enum Flag { 
    None,       // 配對(X), 修改門檻值(X)
    Matching,   // 配對(O), 修改門檻值(X)
    Modify      // 配對(O), 修改門檻值(O)
}

// 定義修改 Flag 的函式架構
public delegate Flag FlagDelegate(float flag);

// 修改 Flag 的函式指針(指向實際的函式內容)
public FlagDelegate modifyThresholdFlag = null;

透過 modifyThresholdFlag 指向自行定義的函式,來修改 Flag 進而在定義的數組 Flag 之間切換。

// 可根據需求,對何時開始更新門檻值這件事做設定
// 累計時間超過 3 秒 Flag 改為 Flag.Modify -> 開始偵測
Flag modifingFlag(float f)
{
    if (f > 3f)
    {
        return Flag.Modify;
    }

    return Flag.Matching;
}

modifyThresholdFlag = modifingFlag;

/////////
public DetectManager dm;
accumulate_time += Time.deltaTime;

// 透過 updateFlag 將 accumulate_time 傳給 modifingFlag,進而修改 Flag 的狀態
dm.updateFlag(accumulate_time);

數據載入

DetectManager 負責載入在動作比對過程中,不會因人而異的部分,如各個動作要比對的關節,以及比對的標準

要比對的關節

前面提到要兩兩一組,形成向量的關節點。

要比對的關節自行獨立為一個檔案,且大小較小,因此採用一次將所有數據一起讀入的方式。

比對的標準

每個分解動作的關節點位置。

比對的標準根據事前準備的數量,各個動作有所不同,檔案大小也較大,因此採需要前再載入。

Clone this wiki locally