人體動作捕捉格式之BVH


BVH簡介

BVH是BioVision公司推出的一種人體動作捕捉文件格式。這種文件以節點為核心元素,記錄連續數幀內人體骨架的運動。

BVH=?

研究一個東西的時候我比較喜歡先研究它的名字。BVH可以認為是BioVision Hierarchy的縮寫,因為這類文件對節點的組織是按照樹形結構來的,也就是層次化(hierarchical)的。關於這個名字還有另一種可能的解釋:如果你去查詢Blender的文檔,對BVH的介紹則將其等同於BioVision Motion Capture. 我傾向於前者,因為hierarchy這個詞其實揭示了BVH的本質。

把這類文件叫做BVH有一個最單純最直接的原因,那就是.bvh是所有這類文件的統一后綴|·ω·)

文件結構

文件分為兩大部分,層級結構運動信息。下面是BVH的一個示例:

HIERARCHY
ROOT Hips
{
    OFFSET  0.00    0.00    0.00
    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
    JOINT Chest
    {
        OFFSET   0.00    5.21    0.00
        CHANNELS 3 Zrotation Xrotation Yrotation
        JOINT Neck
        {
            OFFSET   0.00    18.65   0.00
            CHANNELS 3 Zrotation Xrotation Yrotation
            JOINT Head
            {
                OFFSET   0.00    5.45    0.00
                CHANNELS 3 Zrotation Xrotation Yrotation
                End Site 
                {
                    OFFSET   0.00    3.87    0.00
                }
            }
        }
        JOINT LeftCollar
        {
            ...
        }
	...
}

MOTION
Frames:    2
Frame Time: 0.033333
 8.03    35.01   88.36  -3.41    14.78  -164.35  13.09   40.30  -24.60   7.88    43.80   0.00   -3.61   -41.45   5.82    10.08   0.00    10.21   97.95  -23.53  -2.14   -101.86 -80.77  -98.91   0.69    0.03    0.00   -14.04   0.00   -10.50  -85.52  -13.72  -102.93  61.91  -61.18   65.18  -1.57    0.69    0.02    15.00   22.78  -5.92    14.93   49.99   6.60    0.00   -1.14    0.00   -16.58  -10.51  -3.11    15.38   52.66  -21.80   0.00   -23.95   0.00   
 7.81    35.10   86.47  -3.78    12.94  -166.97  12.64   42.57  -22.34   7.67    43.61   0.00   -4.23   -41.41   4.89    19.10   0.00    4.16    93.12  -9.69   -9.43    132.67 -81.86   136.80  0.70    0.37    0.00   -8.62    0.00   -21.82  -87.31  -27.57  -100.09  56.17  -61.56   58.72  -1.63    0.95    0.03    13.16   15.44  -3.56    7.97    59.29   4.97    0.00    1.64    0.00   -17.18  -10.02  -3.08    13.56   53.38  -18.07   0.00   -25.93   0.00  

該文件是刪減過的,為了顯示清楚格式。>點我< 看源文件。

層級結構

首先HIERARCHY標記了層級結構部分的開始。

可以跟着編譯器的思路來理解這一部分:

  • 現在開始讀這個文件啦,首先讀到的是ROOT,這表示第一個節點是根節點。第一個節點總是根節點;
  • 往下讀,讀到了Hips這個詞,結合上一條的信息,我們就知道了,根節點的名字是'Hips'。對於人體骨架來說,根節點一般都取在Hips也就是臀部。
  • 接着,出現了{,左括號開始了,必然有右括號}與之閉合,而括號之間的部分,既有節點,也有信息。我們可以理解為括號括起來的部分從屬於剛剛讀到的節點,這里是根節點Hips
  • 下面讀到一個關鍵字OFFSET。接下來會有三個數字,這里是0.00 0.00 0.00這表示該節點相對於父節點的偏移,也可以理解為從父節點到該節點連線所表征的向量。根節點沒有父節點,所以這里是0.
  • 再讀,讀到CHANNELS這個關鍵詞,那么這一行剩下的部分就是幾個表示自由度的關鍵字,Xrotation Yrotation Zrotation表示了三個旋轉自由度,Xposition Yposition Zposition 表示三個平移自由度。這一行表示剛才的根節點的自由度信息。
    • 一般來說,根節點有全部的6個自由度,而其余節點只有3個旋轉自由度。
    • 這些自由度的具體含義會放在后一節說明。
  • 接着往下,讀到了JOINT 這個關鍵字,這意味着這一行表示的是一個節點,后面的一個詞Chest則是這個節點的名字。這個節點和根節點唯一的區別就是標記是JOINT而不是ROOT
  • 下面又出現了{,同樣的,括號內的信息和子節點都從屬於該節點。
  • 直到End Site出現前的部分都不需要贅述。End Site是一個無名節點,表示樹形結構到這里就是葉節點啦,后面再也沒有子節點了。End Site沒有子節點,所有也就沒有自由度信息,只有相對父節點的偏移信息。
  • 接下來讀到了本文件第一個},表示一個節點的所有范圍終結。
  • 下面再出現JOINT標記的節點時,我們回去找它在誰的括號內,它就是誰的子節點,以此類推,直到MOTION結束,因為這是下一部分開始的標志。

運動信息

緊承前節,看到了MOTION這個關鍵字,就代表着運動信息的部分開始了。

這一部分的結構要簡單的多,就不像上一節那樣介紹了:

  • 第二行Frames: 2表示幀數,這里是2幀;
    • 這里的幀數必須與后面的幀數據行數相等,因為這個數字決定了要讀取多少行,如果少了會造成數據浪費,多了就會出bug
  • 第三行Frame Time: 0.033333 表示每一幀的持續時間,這里是\(\frac{1}{30}\text{s}\),也就是這個文件是30FPS
  • 后面有n行運動數據,每行為一幀。這些信息按照HIERARCHY部分的自由度出現的順序一一對應。其中角度的單位是度(°)

運動計算

這一部分主要解決的問題是:如何通過BVH復現運動情況。這種旋轉還是很抽象,要轉化就要轉化成人最方便理解的形式,那就是三維坐標。

自由度理解

首先要明確的是,這些參數的含義究竟是什么。

如果在根節點ROOT建立全局坐標系,把OFFSET都作為相對這個全局坐標系的向量,那么僅憑HIERARCHY的信息是可以畫出一個基本的骨架的。把這個骨架圖起個名字叫\(G_0\),后面還要再提到它。這種生成\(G_0\)的方法理論上沒有問題,但是不能這么理解。BVH中每個節點都有自己的局部坐標系,所有的變換都是在局部坐標系完成的。只不過在\(G_0\)中,這些坐標系全部平行,局部坐標就等於全局坐標。

注意,雖然這里我們畫出了\(G_0\),但這並不是初始的那一幀,只是一個基本的參考。運動信息部分中的每一幀都可以由這一幀的信息和\(G_0\)唯一地生成,沒有記憶性,也就是說每一幀都是獨立的。

BVH的每個節點都有3個或6個自由度,這些自由度都是相對於初始坐標系(暨全局坐標系)而言的。平移自由度很好理解,就是沿着三個軸的偏移量;而旋轉自由度則需要牽扯到3個點:當前節點O、子節點C、父節點P。如下圖

這里要第一次強調hierarchy的含義了:每個節點的旋轉,在自己的坐標系旋轉的同時,帶動所有子節點和相關骨骼的旋轉。可以理解為按照層級從根到葉先后執行旋轉,一個節點的局部坐標在旋轉之前,始終和其父節點的局部坐標保持平行。

按照這樣一個過程,我們來理解一下旋轉自由度的含義。在節點\(O\)旋轉前,其局部坐標系\(Oxyz\)是和\(Pxyz\)完全平行的。三個自由度的含義是先后繞局部的\(Oz\), \(Ox\), \(Oy\)旋轉的角度(這里以ZXY順序為例)。注意,這里的單位是度(°).

旋轉的結果不會體現在節點\(O\)上,而是體現在\(C\)及其后續節點的位移,即向量\(\vec{OC}\)的旋轉。

遞歸計算

這一部分主要討論如何利用BVH中給出的信息,計算出每一幀所有節點的三維坐標序列。其核心是坐標變換的遞歸。

這里要再一次強調hierarchy這個詞。遞歸計算的核心就是對層級結構的利用。

我們知道,如果一個坐標系\(p\)旋轉之后得到了坐標系\(q\),這一旋轉過程的旋轉矩陣可以表示為\(R_{pq}\),而在這個空間內有一定點\(A\),它在兩個坐標系下的坐標分別是\(A_p\)\(A_q\),那么有如下關系成立:

\[A_p = R_{pq}A_q \]

這就是坐標變換公式

這里就有問題了。BVH中的旋轉是向量在旋轉,這個公式中\(A\)點根本就是一個定點,怎么能用來計算呢?

其實在前一節,我們賦予了每個點一個單獨的局部坐標系,並規定這個坐標系內,直接后繼的坐標是不變的。這就是為了將坐標變換和向量旋轉等同。可以分幾步來理解這個計算過程(以父節點的坐標系為基准):

  1. 轉之前的橙色坐標系(\(\vec{OC}\)所在的坐標系)記為\(p\), 轉之后的紅色坐標系(\(\vec{OC^\prime}\))記為\(q\)

  2. 旋轉前,所有坐標系都與全局坐標系等同,這就使得\(\vec{OC^\prime_p}\)實質上是\(\vec{OC^\prime}\)在全局坐標系下的坐標,也就是我們直接可以從坐標序列得出的\(V_g\)。旋轉后的坐標系下,同一個向量\(\vec{OC^\prime}\)\(q\)下的坐標實質上是基准幀內該向量的坐標,即\(V\)

  3. 於是有了

    \[\boldsymbol{V}_g=R\boldsymbol{V} \]

我們再來理解遞歸的過程:在基准幀,當前節點以其父節點為基准執行旋轉,得到向量\(R_n\boldsymbol{V}\),這一向量的坐標是相對其父節點而言的;那么以父節點作為待處理的節點,繼續執行這個過程,有了\(R_{n-1}R_n\boldsymbol{V}\),以此類推。於是,某一節點的局部坐標到全局坐標的轉化矩陣就可以寫為

\[R=R_0R_1R_2\cdots R_n \]

為了不讓這個式子看起來太復雜,我沒在公式里顯式指明旋轉矩陣所在節點的從屬關系。但是他們之間的關系應為:\(R_{i+1}\)\(R_i\)的子節點。

有了這個關系,\(R_n\)就可以遞歸求解。即,當我們知道\(R_n\)節點所有祖先節點的旋轉矩陣,他們按照上面的順序乘在一起得到的結果是\(R_m\), 則成立以下式子:

\[\boldsymbol{V}_g=R_mR_n\boldsymbol{V} \]

式中只有\(R_n\)是未知的。

The End

最近在學習人體的動作捕捉,BVH的旋轉還是挺繞的,但是這種層級結構確實是一種解決人體運動描述的很有用的思想,還是值得深入解讀的。

當然,文章內容是基於我個人理解,如有錯誤,萬望指正:)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM