danchy
danchy

Reputation: 447

Trying to display opencv video in QGraphicsScene and QGraphicsView but Nothing shows up

I have a GUI app that I wrote in Python and I'm trying to display video in Qt app.

It uses a QGraphicsScene and QGraphicsView to display images but now I have to display a video. When I try to display a video here is what I do:

First, I create VideoCapture from cv2 package. After that I run loop and read frame in every iteration which is then casted into QPixmap (this is done correctly, I checked on a single frame). I return that QPixmap object to the Class which holds QGraphicsScene and QGraphicsView and try to add it to the scene.

Thing is, only when the video ends, the last frame is displayed, throughout video playing time I'm welcomed with this sighting

A blank non responsive screen

The loop that I mentioned earlier looks like this:

    self.imageViewer.start_capturing()
    self.timer = QtCore.QTimer()
    self.fps = 24

    while True:
        retVal = self.imageViewer.read_frame()
        if not retVal:
            self.timer.stop()
            break
        self.timer.start(1000./self.fps)
    self.imageViewer.stop_capturing()

self.ImageViewer is a component which holds the QGraphicsScene and QGraphicsView I also put timer here so that it displays proper ammount of fps but it doesn't help.

The GUI app itself shows QGraphicsView with some buttons

middleLayout.addWidget(self.imageViewer.view)

This is what I mean. So it doesn't show imageViewer but it shows a subclass of QGraphicsView

Here is the code from read_frame method in ImageViewer class.

def read_frame(self):
    """
    Reads a frame from the video, if video ended, then False is returned.
    If there is a successful reading then True is returned
    :return: True if video is read successfully, False otherwise.
    """
    retVal, self.current_frame = self.capture.getFrame()
    if not retVal:
        return False
    else:
        self.pixmap = retVal
        self.scene.addPixmap(self.pixmap)
        return True

The method self.capture.getFrame() just returns QPixmap item and CV::mat item.

This whole process is done correctly because I tried manually reading frame by frame and everything worked OK, but when I try to display video the app freezed like shown in image above. So I manually tried to do the whole described process by manually clicking a button which loads me frame and puts it onto the QGraphicsScene so I assume that the core of the app works correctly (and I even tried to get roughly 5-7 fps by clicking fast :D )

I hope I made my problem clear and included all code that is needed.

Upvotes: 1

Views: 1547

Answers (1)

nayana
nayana

Reputation: 3932

I think your timing logic is wrong.. you do not use the timer correctly.. you could either use connect or you can use sleep.

I would do something like this:

def grabFrame
    retVal = self.imageViewer.read_frame()
    if not retVal:
        self.timer.stop()
        self.imageViewer.stop_capturing()

And somewhere in your main logic or some init function of your class:

yourObject.connect(timer,SIGNAL("timeout()"),yourObject,SLOT("grabFrame()"))
timer.start(1000./self.fps)       

Or you can use some kind of sleep of time module after

import time
...
while True:
    retVal = self.imageViewer.read_frame()
    if not retVal:
        break
    time.sleep(1./self.fps)//in fraction of second
self.imageViewer.stop_capturing()

Upvotes: 1

Related Questions