做者自轉,原文連接http://blog.csdn.net/nmlh7448...算法
上一篇文章簡單說了一些關於Kinect彩色圖像和深度圖像的處理。直接處理彩色數據流和深度數據流來寫一些應用是比較困難的,因此微軟在SDK中已經封裝好了骨骼識別模塊。雖然說是骨骼識別,其實識別出來的是關節,骨骼能夠看成兩關節的連線。經過該模塊,咱們能夠輕易獲取關於人體各個關節的3D位置及其座標,藉此能夠輕鬆開發出一些須要體感識別的應用。
其實骨骼識別更加簡單,經過微軟的SDK,咱們僅僅要作的就是調用。微軟這麼作的好處就是開發者能夠減小花費在底層、圖像處理等方面的時間,專一於本身的應用邏輯,快速開發出有趣或實用的應用。
爲了學習骨骼識別,我寫了一個僅獲取頭部位置的一個Demo。爲了標記出識別出的頭的位置,須要在該座標位置畫點什麼,在這裏我用了一張滑稽。上一篇顯示骨骼圖像的colorImage是Image控件,它自己也能夠繪圖,但效率略低。因此本篇利用Canvas控件。沒錯,和HTML5中的Canvas畫布控件是相似的,咱們能夠在該畫布上繪製彩色圖像和滑稽。在窗體上加入畫布控件後,爲畫布加上Image和Ellipse子控件。至於爲何用Ellipse,由於滑稽是圓的……修改事後的代碼以下。數組
<Canvas HorizontalAlignment="Left" Height="480" VerticalAlignment="Top" Width="640"> <Image x:Name="colorImage" HorizontalAlignment="Left" Height="480" VerticalAlignment="Top" Width="640"/> <Ellipse x:Name="ellipse" Height="48" Canvas.Left="10" Canvas.Top="10" Width="48"/> </Canvas>
.cs 文件中,首先要聲明一個 Skeleton[] 類,是一個 Skeleton 的數組。Skeleton是骨骼類,該類封裝了識別出的一我的的全部骨骼信息。因爲視野中可能有多我的,每個人的骨骼信息被保存在了一個Skeleton中,因此此處聲明爲數組。Kinect及其SDK已經把相關的識別和區分算法作好了。app
_kinect.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(KinectSkeletonFrameReady);
private void KinectSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) { bool isSkeletonDataReady = false; using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame()) { if (skeletonFrame != null) { skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength]; skeletonFrame.CopySkeletonDataTo(skeletons); isSkeletonDataReady = true; } } if (isSkeletonDataReady) { Skeleton currentSkeleton = (from s in skeletons where s.TrackingState == SkeletonTrackingState.Tracked select s).FirstOrDefault(); if (currentSkeleton != null) { var brush = new ImageBrush(); //定義圖片畫刷 var converter = new ImageSourceConverter(); brush.ImageSource = (ImageSource)converter.ConvertFromString("Images/huaji.jpg"); ellipse.Fill = brush; //待優化 LockHeadWithRedSpot(currentSkeleton); } else { ellipse.Fill = null; } } }
using塊中,將全部的骨骼信息複製到skeletons數組中。因爲在Kinect視野中不必定是一我的,數量是不肯定的,此處爲變長數組,因此選擇每一幀從新初始化。在currentSkeleton中,咱們使用linq語句查詢正在被跟蹤的第一我的,全部人是按距離從近到遠排序的。確保Kinect正在跟蹤至少一我的,而後能夠定義畫刷,我使用的滑稽圖片做爲源,用該畫刷填充ellipse。我使用了一個新的方法LockHeadWithRedSpot(Skeleton) 來跟蹤頭部。學習
private void LockHeadWithRedSpot(Skeleton s) { Joint head = s.Joints[JointType.Head]; //將頭部的骨骼點座標映射到彩色視頻流中 ColorImagePoint colorImagePoint = _kinect.CoordinateMapper.MapSkeletonPointToColorPoint(head.Position, _kinect.ColorStream.Format); Point p = new Point((int)(colorImage.Width * colorImagePoint.X / _kinect.ColorStream.FrameWidth), (int)(colorImage.Height * colorImagePoint.Y / _kinect.ColorStream.FrameHeight)); Canvas.SetLeft(ellipse, p.X - 24); Canvas.SetTop(ellipse, p.Y - 24); }
因爲本篇及上篇使用的全部方法只能得到頭部位置數據,並不能得到頭部大小的數據,因此滑稽的大小要靠本身掌控。代碼中24是我本身試出來的半徑大小,可根據實際應用調整。優化