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,因此根本沒法到達要求的幀率,實際總時長將大於理論時長,也就沒法與音頻同步!