2017-10-09 3 views
0

J'ai très simplement une application écrite en QT dans laquelle je veux afficher un film en utilisant QMediaPlayer, mais avant d'afficher un cadre je voudrais y détecter quelques objets et les marquer en dessinant un rectangle dessus. J'ai lu dans http://doc.qt.io/qt-5/videooverview.html que je peux accéder à chaque image en sous-classes QAbstractVideoSurface et ainsi je l'ai dit.Modifier et afficher QVideoFrames obtenu dans 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; 
     } 
    } 

    ... 
} 

Maintenant, je reçois dans cette fonction membre trames que je veux modifier en dessinant dessus des rectangles dans des endroits où je Détecté des objets et je voudrais les afficher sur l'écran (de préférence sur certains widget de) .

Comment est-ce que je peux faire ceci?

  1. Si ma VideoSurface classe contiennent QWidget en tant que membre? ou devrais-je sous-classe QWidget qui contiendra VideoSurface?

  2. Dans les deux cas, comment puis-je afficher cette image? Dois-je d'abord le convertir en QImage et ensuite afficher (ce serait convinien pour moi, parce que mon système de détection fonctionne avec QImage, mais serait-il efficace)? Je sais que je ne peux pas peindre à l'extérieur d'un événement de peinture, donc je ne peux pas peindre dans la fonction present, alors où exactement devrait être cette fonction de peinture et comment je peux l'appeler?

  3. Où dois-je détecter ces objets et modifier la trame? En present fonction, ou dans la fonction de dessin?

Répondre

0
  1. C'est à vous et dépend de la façon dont vous préférez structurer vos classes. Je préférerais avoir un widget séparé qui contient un pointeur vers votre VideoSurface et dessine les données qui sont renvoyées par une fonction membre de VideoSurface (dépend de votre solution dans 2.)

  2. a) QImage est assez efficace pour certains Si vous l'utilisez déjà dans votre code de détection, vous avez déjà tout en mémoire et vous pouvez y travailler. Comme pour tous les soucis liés à la performance: Testez et voyez si la performance est assez bonne pour vous. Si ce n'est pas le cas, vous devrez probablement envisager de faire la détection différemment. J'ai travaillé sur un projet où nous avons traité des QImages convertis depuis une VideoSurface similaire sur un flux de caméra sur des appareils mobiles (pour des images relativement basse résolution), et les performances étaient assez bonnes pour que nous n'ayons pas encore pris d'autres techniques. Le code source de la classe VideoSurface dans ce projet (Neuronify) is hosted here. b) Votre fonction present() peut émettre un signal auquel vous pouvez vous connecter à partir d'autres objets qui extraient les dernières données de la surface vidéo et la conserve jusqu'à ce que leur fonction de peinture soit appelée. Vous pouvez également appliquer les données directement à un widget qui accepte les données d'image. Voir Use of QAbstractVideoSurface pour un exemple de cela. Encore une fois, c'est à vous de décider :) Cependant, si vous avez besoin d'améliorer les performances à un moment donné, vous pouvez travailler sur un thread différent pour éviter que votre interface graphique ne se bloque pendant que vous traitez les données. Et si vous faites cela, vous devez décider si vous devez traiter chaque image ou si certaines images peuvent sauter le traitement pour améliorer le FPS de la lecture. Dans ce dernier cas, vous ne devriez probablement pas le faire dans la fonction present(), car cela empêchera probablement le lecteur multimédia de vous fournir plus d'images pendant le traitement des anciennes images.