2017-10-09 24 views
0

我有一个非常简单的应用程序写在QT中,我想通过使用QMediaPlayer来显示电影,但在显示任何帧之前我想检测它的一些对象并标记它们通过在其上画一个矩形。修改和显示在QAbstractVideoSoSface中获取的QVideoFrame

我读过http://doc.qt.io/qt-5/videooverview.html,我可以访问每个框架的子类QAbstractVideoSurface,所以我决定。

class VideoSurface : public QAbstractVideoSurface { 
    Q_OBJECT 

    bool present(const QVideoFrame &frame) override { 
     if (surfaceFormat().pixelFormat() != frame.pixelFormat() 
       || surfaceFormat().frameSize() != frame.size()) { 
      setError(IncorrectFormatError); 
      stop(); 

      return false; 
     } else { 
      currentFrame = frame; 

      return true; 
     } 
    } 

    ... 
} 

现在,我在该成员函数正在接收帧,我想通过借鉴它在哪里检测到的物体的地方矩形修改,然后,我想在屏幕上显示它们(优选在某些插件) 。

我该怎么做?

  1. 如果我VideoSurface类包含QWidget成为会员?或者我应该子类QWidget其中将包含VideoSurface

  2. 在这两种情况下,我怎样才能显示这个框架?我应该先将它转换为QImage然后再显示(这对我来说很方便,因为我的检测系统与QImage一起工作,但效率会如何)?我知道我不能在绘画事件之外绘画,所以我不能在present函数中绘画,那么究竟应该在哪里绘制这个绘画函数,以及我可以如何调用它?

  3. 我应该在哪里检测这些对象并修改框架?在present函数中,还是在绘图函数中?

回答

0
  1. 这是给你的,取决于你喜欢如何构建类。我宁愿有一个单独的小部件,其中包含指向VideoSurface的指针,并绘制由VideoSurface的某个成员函数返回的数据(取决于您在2中的解决方案)。

  2. a)QImage对于某些目的,如果你已经在你的检测代码中使用它,那么你已经拥有了内存中的所有东西,并且可以处理它。与所有与性能有关的担忧一样:测试并确定性能是否足够适合您。如果不是,您可能还必须考虑以不同的方式进行检测。我曾参与过一个项目,我们在移动设备的相机流上处理从类似VideoSurface转换而来的QImage(对于分辨率相对较低的图像),并且性能足够好,以至于我们还没有打算使用其他技术。该项目中的VideoSurface类的源代码(Neuronify)is hosted here。 b)您的present()函数可能会发出一个信号,您可以从其他对象连接到的信号,从VideoSurface获取最新数据并保存它,直到它们的绘制函数被调用。或者,您可以将数据直接应用于某些接受图像数据的小部件。有关这方面的示例,请参见Use of QAbstractVideoSurface。但是,如果您需要在某个时候提高性能,您可能希望在不同的线程上执行该操作,以防止在处理数据时锁定GUI。如果你这样做,你需要决定是否必须处理每一帧,或者如果某些帧可以跳过处理来改善播放的FPS。在后一种情况下,你可能不应该在present()函数中这样做,因为这可能会使媒体播放器无法在处理旧帧时为您提供更多帧。