下載Kinect for Windows SDK 1.5 (update 2012.5.21)
Kinect Developer Toolkit
Audio
NearMode
Color
RGB
YUV
Depth
Near Range
Skeleton
Default
Seated
Chooser:
Default
Closest1Player
Closest2Player
Sticky1Player
Sticky2Player
MostActive1Player
MostActive2Player
Face Tracking
Tilt Angle (-27/+27)
Console
首先先試最簡單的Color Stream
開啟了 ColorBasics-WPF 專案
它Reference了 Microsoft.Kinect
最重要的是
private KinectSensor sensor;一個KinectSensor物件
UI介面也很簡單 就是一個Image接收Color Stream傳來的資料, 和一個可以儲存目前畫面的button
sensor的ColorFrameReady event有一個Handler, 隨時更新Color的資料給Image
結果如下:
其實就是像一個WebCam的功能一樣
- DepthBasics-WPF
this.sensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);一開始會Enable DepthStream, 並指定格式
同樣的也為DepthFrameReady event加了一個Handler
this.sensor.DepthFrameReady += this.SensorDepthFrameReady;
結果如下:
DepthStream有兩種Range, 所以在介面上按下Near Mode選項, 這麼做
if (this.checkBoxNearMode.IsChecked.GetValueOrDefault())
{
this.sensor.DepthStream.Range = DepthRange.Near;
}
else
{
this.sensor.DepthStream.Range = DepthRange.Default;
}
從文件裏得知:Default range from [800mm - 4000mm] inclusive.
Near range from [400mm - 3000mm] inclusive.
打開Near Mode的結果:
初步觀察:
- depth進來的數值為-1~4095 相當於 2的14次方如果我們把它除以16分佈到藍色和綠色的話, 可以得到這樣的影像:
- 場景中黑色物體 (如頭髮, 隔間牆的下擺) 因為會吸光 所以容易造成誤判
- 因為距離應該是用反射方式獲得, 所以每個東西會有類似影子的死角, 也就是如果有物件前後重疊時, 後面那個東西的偵測範圍會被前面的東西多擋到一些, 如圖中人的旁邊多了一片黑色的區域, 這個區域的大小會依據前後物件的距離成正比. 也就是如果兩個物件貼近時, 黑色區域會縮小甚至消失, 如果距離很大(例如人和牆的距離), 黑色區域也會變大.
- D3D範例
在D3D中開啟Stream的方法和WPF中不太一樣
WPF:
newSensor.DepthStream.Enable(DepthImageFormat.Resolution320x240Fps30);
D3D:
hr = m_pNuiSensor->NuiImageStreamOpenD3D正在用一套奇怪的Nui(Natural User Interface)程式庫, 感覺跟Kinect又有一點不直覺
static const int _MaxPlayerIndices = 8;在ProcessDepth中
int player = depth & NUI_IMAGE_PLAYER_INDEX_MASK;Kinect引擎自動將取到的玩家分開給深度值, 然後再用Shader去畫出不同顏色的玩家
static const float4 playerColorCoefficients[8] =
{
float4(1.0, 1.0, 1.0, 1.0),
float4(1.4, 0.8, 0.8, 1.0),
float4(0.8, 1.4, 0.8, 1.0),
float4(0.8, 0.8, 1.4, 1.0),
float4(0.6, 1.2, 1.2, 1.0),
float4(1.2, 0.6, 1.2, 1.0),
float4(1.2, 1.2, 0.6, 1.0),
float4(1.3, 0.9, 0.8, 1.0)
};
(注意這裏的Color Format有點奇怪, 是BGRA, 也就是藍色為先, 所以以玩家1來說是偏紫色)
這裏學到了兩個東西
m_hNextDepthFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);它讓我們在 RenderFrame的時候 去等
if ( WAIT_OBJECT_0 == WaitForSingleObject(m_hNextDepthFrameEvent, 0) )
{
ProcessDepth();
}
另一個東西是ID3DBlob* pBlob它是DX10之後用來compile和create pixel shader和 vertex shader
低階的D3D程式細節很多, 有很長一段時間沒有接觸, 在此先針對Kinect的部份了解
- 臉部辨視:
程式一開始並沒有自動出現人臉辨視, 推斷原因為距離Camera太近導致. 將身體往後靠之後即出現辨視後的人臉, 就算移回原先的距離也能持續偵測得到, 可以斷定深度偵測只用在一開始的追綜.
人臉辨視呈現的打光偏暗, 面向會隨著擺動, 嘴巴如果張開, 臉部模型也會跟著變化
程式解析:
本專案連結了另外兩個Reference, 一個是位於
D:\KinectSDK\Microsoft.Kinect.Toolkit\
產生 D:\KinectSDK\Microsoft.Kinect.Toolkit\obj\Debug\Microsoft.Kinect.Toolkit.dll
另一個是
D:\KinectSDK\Microsoft.Kinect.Toolkit.FaceTracking\
產生D:\KinectSDK\Microsoft.Kinect.Toolkit.FaceTracking\obj\Win32\Debug\Microsoft.Kinect.Toolkit.FaceTracking.dll
這個WPF用了練家子的一連串Data Binding和Event Handling來初始化物件, 不費點功夫還搞不清楚它的來龍去脈
一開始在MainWindow的constructor
var kinectSensorBinding = new Binding("Kinect") { Source = this.sensorChooser};
this.faceTrackingVisualizer.SetBinding(TexturedFaceMeshViewer.KinectProperty, kinectSensorBinding); this.sensorChooser.KinectChanged += this.SensorChooserOnKinectChanged;
newSensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30); newSensor.DepthStream.Enable(DepthImageFormat.Resolution320x240Fps30);
newSensor.DepthStream.Range = DepthRange.Near; newSensor.SkeletonStream.EnableTrackingInNearRange = true;
newSensor.SkeletonStream.TrackingMode = SkeletonTrackingMode.Seated; newSensor.SkeletonStream.Enable();
其中DepthStream和SkeletonStream都要設成Near模式(如果只設一個會怎麼樣?)
在Microsoft.Kinect.Toolkit.FaceTracking的Utils.cs中 Feature Point有71個(0~108跳號)
比如:
TopSkull = 0,
TopRightForehead = 1,
MiddleTopDipUpperLip = 7,
AboveChin = 9,
BottomOfChin = 10,
RightOfRightEyebrow = 15,
MiddleTopOfRightEyebrow = 16,
LeftOfRightEyebrow = 17,
MiddleBottomOfRightEyebrow = 18,
AboveMidUpperRightEyelid = 19,
OuterCornerOfRightEye = 20,
...
它在WPF程式中是以WPF的3D呈現臉部模型, 打光等設定也是在WPF中, 我把方向光和環境光的顏色改一下變成這樣:























