Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
How to wait for an image to be drawn in Qt / Which signal to connect to?
For a lab application I am required to project images using a projector and recording the projected images with a camera afterwards. In this case it is important to be sure that the frame is projected before we record with the camera. However, as we have to do this for a large number of images we don't want to have a long delay between subsequent frames. How do I create a function that draws an image and only returns once the frame has been drawn onto the screen?
I have a python example code shown below.
import PyQt5 from PyQt5 import QtGui, QtCore, QtWidgets import numpy as np class ShowLiveImage(QtWidgets.QWidget): def __init__(self): """ Create a tiny window in which a frame can be displayed using show_image. """ super().__init__() self.imageLabel = QtWidgets.QLabel() self.layout = QtWidgets.QVBoxLayout() self.setLayout(self.layout) self.layout.addWidget(self.imageLabel) self.window().setMinimumSize(512,512) self.win = self.window() self.show() def show_image(self, image_array, wait_for_drawing=True): """ Shows an image given as a numpy array and (should) wait for the frame to be drawn onto the monitor before returning. """ N = image_array.shape self.im = QtGui.QImage(image_array, N, N, QtGui.QImage.Format_Grayscale8) qpm = QtGui.QPixmap(self.im) self.imageLabel.setPixmap(qpm) if wait_for_drawing: # These do not help, what do I do here? self.imageLabel.repaint() QtGui.QGuiApplication.postEvent(self, QtCore.QEvent(QtCore.QEvent.UpdateRequest)) QtGui.QGuiApplication.processEvents()
However, when I keep updating images using this code, the frame rate is way too high, around 400 fps on my computer, which I tested in the following way:
from PyQt5.Qt import QApplication import time app = QApplication() viewer = ShowLiveImage() t0 = time.time() for i in range(1000): random_image = np.random.randint(0,255,(512,512), np.uint8) viewer.show_image(random_image) t1 = time.time() print(' FPS: ', 1000./(t1-t0))
How to I make sure that show_image only returns when the frame has been projected?
Hi and welcome to devnet,
For a lab ? Are you asking for help of an exercice of your scholar cursus ?
@SGaist No, it's not a course, this is for an actual research lab. The device I'm controlling is called a spatial light modulator, and it acts as a second screen.
That's the kind of details that is good to provide directly :)
Can you give a bit more details about the hardware you have at your disposition to do that task ?
@SGaist I'm not sure which specs you require exactly, but this is a typical device:
The driver installs the device as an additional screen with a update rate of 204 Hz at 512x512 pixels. The PC I'm using is a high-end windows machine of a few years ago, with an NVIDIA GTX 780 graphics card, and an i7 intel processor, I'm not sure about the exact specs. I'm developing on my (linux mint) laptop. The patterns that I require can be generated beforehand so generating the images should not be an issue.
Any other specs you require?
I was wondering when you say
- recording the projected images with a camera afterwards
Does it means it will take still images or record as video ?
Also, how fast can the camera record ?
Dirk B. last edited by Dirk B.
@mrjj the camera supports up to 400 fps, but ideally I will use 205 fps to match the slm. I'm recording still images at 200 hz which is working fine art the moment.
So you would need to have your recorder synced on the VSync signal of the video card ?
Yes, I think that's it!
@SGaist any ideas how to do that exactly? I thought the repaint would perform that job.