OpenNI/Kinect 的手部追蹤、處理

OpenNI 搭配 NITE 雖然提供了全身的骨架追蹤功能,但是他並沒有提供針對手部的細部處理,緊緊有提供手部的位置追蹤、以及幾組預設的手勢辨識的能力(參考)。而由於手部動作的分析、尤其是去抓出手指、或是判斷手是否握著,在互動操作上也是相當實用的功能,所以實際上也有不少人在往這方面做研究~

像下面這段影片,就是透過 model-based 的 3D 物件追蹤,來時做出來的手指追蹤,看起來效果算是相當地好!

這個研究的官方網頁是:http://cvrlcode.ics.forth.gr/handtracking/,在上面除了有相當多的影片可以參考系統運作的狀況外;一隻手有 26 個自由度(dergee of freedom)、不需要任何特殊的標誌或手套,也不需要 NITE 提供的追蹤功能。而為了計算效能,需要有支援 nVIDIA CUDA 的顯示卡來做計算;在 Intel Core i7 950 搭配 GeForce GTX 580 的情況下,處理的效能大約可以到達 20FPS。

而雖然沒有提供原始碼,不過也有提供 64 位元版本的展示程式,可以讓使用者下載測試。但是很遺憾的是,Heresy 下載後沒辦法正確執行就是了(錯誤似乎是在 CUDA 程式的部分)


上面的方法,基本上算是去完整地去找出整個手的架構、進行手指的辨識以及追蹤,算是難度比較高的方法。而相較之下,雖然沒有那麼完整,但是還有一些比較簡易的方法,也可以做到一定程度的效果;像是在網路上,其實就可以找到不少人,把 OpenCV 拿來搭配 OpenNI 的深度資料(參考),進行簡單的手部的處理~像下面這兩段影片,都是類似的概念:

第一段影片是由 Robert Walter 這位網友所提供的,他在說明的地方,有提供 DropBox 的下載連結(ZIP 檔),可以下載原始碼來做測試;而後者則是由 Brandt Westing 這位網友提供的,他有將程式放在 github 上(連結),讓大家可以下載~

不過,Heresy 自己測試的時候,Robert Walter 的程式碼要能正確地在 Visual C 編譯、執行,是需要適度地修改的;而 Brandt Westing 的範例,則是不知道為什麼,可以在 Kinect for Xbox 360 上使用,而不能在 ASUS Xtion Pro Live 上執行…不過基本上,只要可以跑起來,都算可以做簡單的測試的~

實際上,這兩位所提供的範例,都是類似的作法。他們的處理流程,基本上都是:

  1. 使用 User Generator 的 Skeleton Capabiliy 來追蹤人體骨架,並藉此判斷手部的位置。
  2. 根據手部的位置,取鄰近的深度值,抓出手的區域。
  3. 把抓到的手部區域,透過 OpenCV 來找出手的輪廓(contour、文件) ,並簡化輪廓(文件)。
  4. 去找手的輪廓的在幾何上的「凸包」(convex hull、維基百科OpenCV 文件)、以及凹進去的點(convexity defects、OpenCV 文件)。(不過 Robert Walter 似乎沒有直接用 OpenCV 去找 convexity defects)
  5. 接下來,就可以針對找到的這些點,來做進一步的分析,藉此來判斷手是張開、還是握著了~
    而這兩位基本上都是使用區域面積的比例,來做判斷的。

大致上大概就是這樣了~詳細的實作方法,可以直接參考這兩位所提供的原始碼。

Heresy 自己也有寫類似的程式,不過還沒弄完;等寫好了,再拿來分享吧~現在是希望能不能在更進一步,去分析各隻手指的位置,進而做到更細的控制;不過,還不確定能做到什麼程度就是了。


`

12 thoughts on “OpenNI/Kinect 的手部追蹤、處理”

  1. 你好,你提供的Robert Walter源码下载链接不能连接哦···希望你能发我邮箱分享下···lemonlwb@yahoo.cn十分感谢!

  2. to lemonlwb
    DropBox 的連結應該是可以用的。
    如果是被擋掉的話,麻煩請自行翻牆。

  3. 最近也打算做openNI kinect的手部的跟踪和识别,希望有机会可以和作者交流一下。期待您的最新文章!向您学习了~

  4. 您好,我想问下,做Brandt Westing 写的程序的测试时,人体和Kinect的距离有什么限制吗?因为我觉得我测试完的结果有些不对,请指导一下,谢谢啦!

  5. to xiaomaohaizhu
    不知道你是怎樣「不對」?
    基本上,這部分的原始碼並不複雜,個人會建議可以試著自己下去看看他怎麼寫的,或許可以判斷出問題是出在哪。

  6. 谢谢您的及时回复,我所说的“不对”就是运行之后并不能找到每个指尖的位置,而且左右手的结果是一样的。

  7. to xiaomaohaizhu

    他所使用的演算法,本來就只是去試著找凸出的端點。
    所以如果手指太過靠近,或者不夠凸出,就會無法找到指尖。

  8. 请问博主Robert Walter中的代码,在Vs2010里总是报 unsigned short near = depth – 100; // near clipping plane
    unsigned short far = depth 100; // far clipping plane
    error C2513: “unsigned short”: 在“=”前没有声明变量,
    还有mask = mask & depthMat > near & depthMat < far; error C2678: 二进制“>”: 没有找到接受“const cv::Mat”类型的左操作数的运算符(或没有可接受的转换)

    怎么样修改才好呢?

  9. 博主,上一个问题解决了,整个代码没有错了,但是系统报出inline XnStatus SetMapOutputMode(const XnMapOutputMode& OutputMode)
    {
    return xnSetMapOutputMode(GetHandle(), &OutputMode);
    }

    [下面的框架可能不正确和/或缺失,没有为 OpenNI.dll 加载符号]

    是不是因为版本的原因?

  10. to DK
    抱歉,不確定這段簡體中文的錯誤訊息代表什麼意思。
    不過,這個問題是在執行時發生的?如果是的話,建議確定一下 OpenNI 和 Sensor Module 之間的版本是否一致。

  11. 博主再次打扰了,现在弄好了,原因是我的设备一直指定的是kinect for windows,但是却一直显示的是DepthImage,没有视频中的效果。

  12. 我跟楼上是一样的问题,求问是怎么解决的啊~谢谢~

發佈回覆給「xiaomaohaizhu」的留言 取消回覆

發佈留言必須填寫的電子郵件地址不會公開。