• AR播放器


    一、项目需求

    AR播放器:将一系列带透明通道的图片以一定的帧率连续显示,叠加载摄像头采集的画面之上,并播放声音。

    此为最初级的AR技术,因为画面是事先渲染好的,固定不变的,所以实际上并不能实现“互动”,当然,配合画面摆出几个动作拍个照片还是可以。

    二、解决方案

    1、WinForm还是WPF?

    关于摄像头操作,WinForm有很多开源类库可以选择,比如AForge,OpenCV等等;WPF则可以使用WPFMediaKit(也可以通过WindowsFormsHost来使用WinForm的控件,但是效率肯定不如WinForm高,另外在此不得不高度评价下WPFMediaKit,用金老师的话来说,完美!)。

    另外,对于透明通道的支持,WinForm简直让人无语啊,为什么会自动以父级的背景作为背景?当你把Picture控件叠加在摄像头控件上,你会惊喜的发现,这是什么鬼!当然,你可以使用强大的GDI来解决,不过那么多的毛边和刺刺是肿么回事!然后不得不再次感叹,WPF,完美!

    虽然很多人拿WPF的效率说事,但是,在土豪客户面前,这些都不是事儿嘛!CPU上I7,内存搞个16G,显卡来个GTX9xx系列!能用钱解决的事情,那都不是事儿,当然,对我们这个初级的AR播放器来说,2GHz以上,4核的CPU就够用了;内存2G有点压力,4G应该足以应付,显卡嘛,集成显卡应该也没问题。

    2、动画

    2-1、Thread/Task/BackgroundWorker/Timer

    使用WinForm的童鞋,首先想到的应该是这几个玩意儿了,不过除了BackgroundWorker以外,需要跨线程操作UI,简单介绍两种方法:

    Control.CheckForIllegalCrossThreadCalls=false;//不检查线程冲突,虽然可以操作UI了,但是可能会产生难以预料的后果

    Control.Invoke(委托,参数)//使用委托,需要刷新的控件Invoke一下

    当然,WPF也可以使用,不过UI操作是酱紫滴:

    Dispatcher.BeginInvoke(()=>{//做你该做的事情!});

    2-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播放音乐
    View Code

    其中:timer.Interval = TimeSpan.FromMilliseconds(1000 / 25);

    因为渲染图片需要一定时间,图片大小不同,耗时不同,所以实际上达不到25帧每秒,很难与声音同步!


    至于CompositionTarget.Rendering,是UI线程的回调,帧率固定为60/s(Silverlight倒是可以设置帧率),有可能阻塞UI线程,导致画面卡顿,还是不用为妙,当然,这玩意儿在某些场景还是很好用的!

    2-3、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);
    View Code

    使用Animation会出现掉帧、跳帧的情况,例如由1直接变为3,又或者连续几个3,这样保证了总的时长不变,帧率也就相对稳定,也就可以与音频同步。

    而使用DispatcherTimer,比如有600帧,希望的帧率为30(也就是一秒30张图片),理论总时长为600/30=20 (s),音频文件按此时长来制作,Interval=1000/30 -常量(Tick事件的耗时),在耗时较大情况下(图片文件较大,设备性能不行等原因),此值接近0甚至小于0,所以根本无法到达要求的帧率,实际总时长将大于理论时长,也就无法与音频同步!

  • 相关阅读:
    windows加固
    linux加固
    加密与编码
    XSS笔记
    hackbar功能简介
    机器学习 | 从加法模型讲到GBDT算法
    把时间还给洞察,且看PPT调研报告自动生成攻略
    树莓派3折腾笔记
    看数学老师是如何一键搞定报告和试卷的
    博客笔记(blog notebook)
  • 原文地址:https://www.cnblogs.com/LCHL/p/4608178.html
Copyright © 2020-2023  润新知