1、项目需求ide
AR播放器:将一系列带透明通道的图片以必定的帧率连续显示,叠加载摄像头采集的画面之上,并播放声音。性能
此为最初级的AR技术,由于画面是事先渲染好的,固定不变的,因此实际上并不能实现“互动”,固然,配合画面摆出几个动做拍个照片仍是能够。动画
2、解决方案this
一、WinForm仍是WPF?spa
关于摄像头操做,WinForm有不少开源类库能够选择,好比AForge,OpenCV等等;WPF则可使用WPFMediaKit(也能够经过WindowsFormsHost来使用WinForm的控件,可是效率确定不如WinForm高,另外在此不得不高度评价下WPFMediaKit,用金老师的话来讲,完美!)。线程
另外,对于透明通道的支持,WinForm简直让人无语啊,为何会自动以父级的背景做为背景?当你把Picture控件叠加在摄像头控件上,你会惊喜的发现,这是什么鬼!固然,你可使用强大的GDI来解决,不过那么多的毛边和刺刺是肿么回事!而后不得再也不次感叹,WPF,完美!code
虽然不少人拿WPF的效率说事,可是,在土豪客户面前,这些都不是事儿嘛!CPU上I7,内存搞个16G,显卡来个GTX9xx系列!能用钱解决的事情,那都不是事儿,固然,对咱们这个初级的AR播放器来讲,2GHz以上,4核的CPU就够用了;内存2G有点压力,4G应该足以应付,显卡嘛,集成显卡应该也没问题。orm
二、动画blog
2-一、Thread/Task/BackgroundWorker/Timer事件
使用WinForm的童鞋,首先想到的应该是这几个玩意儿了,不过除了BackgroundWorker之外,须要跨线程操做UI,简单介绍两种方法:
Control.CheckForIllegalCrossThreadCalls=false;//不检查线程冲突,虽然能够操做UI了,可是可能会产生难以预料的后果
Control.Invoke(委托,参数)//使用委托,须要刷新的控件Invoke一下
固然,WPF也可使用,不过UI操做是酱紫滴:
Dispatcher.BeginInvoke(()=>{//作你该作的事情!});
2-二、DispatcherTimer/CompositionTarget
不得不说,WPF有许多好用的玩意儿,用起来可比WinForm舒服的多!
简单上一段代码:
1 var timer=new DispatcherTimer(); 2 timer.Interval=TimeSpan.FromMilliseconds(1000/25);// fps:25/s 3 var sources=new List<BitmapImage>();//加载序列帧图片,省略代码 4 var index=0; 5 6 timer.Tick+=(s,e)=> 7 { 8 image.Source=sources[index++];//Image控件,叠加在摄像头控件之上 9 10 if(index>sources.Count-1) 11 { 12 index=0; 13 } 14 }; 15 16 timer.Start(); 17 //使用MediaPlayer播放音乐
其中:timer.Interval = TimeSpan.FromMilliseconds(1000 / 25);
由于渲染图片须要必定时间,图片大小不一样,耗时不一样,因此实际上达不到25帧每秒,很难与声音同步!
至于CompositionTarget.Rendering,是UI线程的回调,帧率固定为60/s(Silverlight却是能够设置帧率),有可能阻塞UI线程,致使画面卡顿,仍是不用为妙,固然,这玩意儿在某些场景仍是很好用的!
2-三、Animation
终于到了Animation出场的时候,上代码:
var ani=new Int32Anitiation(0,images.Count,TimeSpan.FromMilliseconds(images.Count * 1000.0 / fps)); //设置帧率 Timeline.SetDesiredFrameRate(ani, fps); ani.CurrentTimeInvalidated +=(s,e)=> { //更新图片 img.Source=new BitmapImage(new Uri(images[ImageIndex])); }; this.BeginAnimation(ImageIndexProperty, ani);
使用Animation会出现掉帧、跳帧的状况,例如由1直接变为3,又或者连续几个3,这样保证了总的时长不变,帧率也就相对稳定,也就能够与音频同步。
而使用DispatcherTimer,好比有600帧,但愿的帧率为30(也就是一秒30张图片),理论总时长为600/30=20 (s),音频文件按此时长来制做,Interval=1000/30 -常量(Tick事件的耗时),在耗时较大状况下(图片文件较大,设备性能不行等缘由),此值接近0甚至小于0,因此根本没法到达要求的帧率,实际总时长将大于理论时长,也就没法与音频同步!