基于Kinect的开发现在已经不是个什么新奇玩意儿了,记得在六月份时,微软向各大高校推出Kinect pioneer项目,鼓励同学们能够利用SDK for PC开发出各种对社会有重要意义和价值的的应用。作为今年最热卖的单品,我觉得Kinect对于以后进一步改变人类生活可能有很大潜力,所以想在大三先接触一下。
为此我们报名参加微软精英挑战赛,和两个同学一起组成“穗城木棉”队,穗城当然就是广州了,木棉也就是广州的市花,它的另一个名字叫做英雄花,寓意大家都懂得了吧~~因为比赛需要完善自己代表队的博客,我决定根据迭代开发的周期,每期做出一个能run的demo就写一篇博客记录我们开发所查阅的资料,参考的样例和在调试中遇到的问题和解决方法,希望对同样在探索kinect开发的同学有所帮助。
我们从上周正式开始,初步的创意是做一个图片展板软件,用途暂定学院楼下面的展板上。仅仅从这个功能上来讲是非常简单的,但界面效果必须炫,现在一般用户更看重的就是时尚炫丽的UI设计,不过这个得放在后面完善。到项目后期可能考虑采用图像处理算法,把用途拓展到更多的地方。整个开发周期为5周,采用迭代开发,每周完成一个可以运行的demo,添加新的功能和界面设计。
上周完成了项目的第一期demo,也就是软件最核心的功能:用Kinect跟踪左右手,翻动图片。需要完成的工作是,一个简单的读取图片的界面,和Kinect部分跟踪返回的信号。然后用得到的数据来调用图片的翻动就可以了。
因为刚刚起步,给我帮助最大的就是马宁的入门教程:
安装配置--> http://www.cnblogs.com/aawolf/archive/2011/06/17/2083249.html
http://www.cnblogs.com/aawolf/archive/2011/06/18/2084352.html
http://www.cnblogs.com/aawolf/archive/2011/06/21/2086139.html
http://www.cnblogs.com/aawolf/archive/2011/08/25/2153827.html
在按照他的教程配置完后,运行3个demo,基本对于怎样通过Kinect获取数据有了一定的了解。在网上能够搜索到的中文教程并不多,入门靠马宁的就可以了。下面就是看官方文档,我觉得其中programming guide有必要通览一遍,然后就是skeletalviewer-walkthrough比较重要,其它关于audio方面的资料暂时并不需要。
但是只运行那4个demo有些简单,想要了解更多的,我找到这个官方的入门网站,里面有几个视频和代码非常经典。可以作为参考。http://channel9.msdn.com/Series/KinectSDKQuickstarts#tab_sortBy_sequential
其实马宁的博客教程也是参考了channel9里面的Quickstarts的视频做出来的。
除此之外,在http://channel9.msdn.com/coding4fun/kinect?page=2里面还有非常多的项目,都是各种大牛利用Kinect开发出来的应用,公布了源代码,可能里面有很多非常有帮助的哦。
好了,说了这么多怎么学习,说回我们这周的工作。思路非常简单,主要用到了骨骼追踪的内容,用canvas画3个椭圆球,分别跟踪头和左右手,算法就是如果左手与头的距离大于45厘米,则图片翻到前一张,如果是右手,则翻到后一张。然后把小球在界面上隐藏,把控制翻页的按钮隐藏,就得到图片和骨骼追踪的videoStream。在界面WPF那部分,主要是一个open图片的操作,和向前翻向后翻的操作,因为才接触C#和.NET表示非常不熟悉,下一步要攻克界面部分了。
private void Open_Click(object sender, RoutedEventArgs e)
{
bitmapImageList.Clear();
openFileDialog.Multiselect = true;
if (openFileDialog.ShowDialog() == true)
{
if (openFileDialog.FileNames != null)
{
for (int i = 0; i < openFileDialog.FileNames.Length; i++)
{
BitmapImage bitmapImg = new BitmapImage();
bitmapImg.BeginInit();
bitmapImg.UriSource = new Uri(@openFileDialog.FileNames[i]);
bitmapImg.EndInit();
bitmapImageList.Add(bitmapImg);
}
}
else
{
BitmapImage bitmapImg = new BitmapImage();
bitmapImg.BeginInit();
bitmapImg.UriSource = new Uri(@openFileDialog.FileName);
bitmapImg.EndInit();
bitmapImageList.Add(bitmapImg);
}
}
image1.Source = bitmapImageList[0];
}
private void Next_Click(object sender, RoutedEventArgs e)
{
Next_img();
}
private void Next_img()
{
currentImage = (currentImage + 1) % bitmapImageList.Count;
image1.Source = bitmapImageList[currentImage];
}
private void Pre_Click(object sender, RoutedEventArgs e)
{
pre_img();
}
private void pre_img()
{
if (currentImage == 0)
{
currentImage = bitmapImageList.Count - 1;
}
else
{
currentImage -= 1;
}
image1.Source = bitmapImageList[currentImage];
}
上面是打开图片和翻动图片的操作,因为是直接在界面上拖入button控件,对应的函数public void Pre_Click(object sender,RoutedEventArgs e)里面要传两个参数,在ProcessForwardBackGesture(Joint head, Joint rightHand, Joint leftHand)函数里要调用它时,我不知道sender和e到底要传什么,感觉什么都不用传,但不会解决,所以用了一个很笨的办法,就是把它用另一个没有参数的函数调用。如果有博友能够解决麻烦赐教,确实没有接触过WPF。
其余kinect获取数据的代码请参考马宁的第三个教程。
在调试中遇到的3个问题,希望对同样遇到的有所帮助:
1、马宁的教程用的是beta1的SDK,在现在的beta2中,runtime不应该像Runtime nui = new Runtime()这样初始化。而应该是Runtime runtime = Runtime.Kinect[0];
2、最初我给videoStream的分辨率是320*240,然后调试时会出现Failed in native DLL. HRESULT=0x80070057这个是因为kinect只支持NUI_IMAGE_RESOLUTION_1280x1024 和NUI_IMAGE_RESOLUTION_640x480的分辨率,所以改成640*480就对了。
3、在debug时,对SkeletonData data = (from s in skeletonSet.Skeletons
where s.TrackingState == SkeletonTrackingState.Tracked
select s).FirstOrDefault();
这一句它始终get不到data,但是直接运行程序又没有错。最后发现人站起来到kinect 2米外就OK了~也就是调试的时候也要找个人对着kinect,挺麻烦的吧。
因为这第一次的demo比较简单,也就不上传项目了,也不截图了,下面会继续加油。希望有好的心得都可以拿出来分享一下,也都是很好的学习。