1

我正在为摄像机编写一个 GUI,它基本上可以在两种模式下运行,我称之为 liveview 和 recordview。唯一的区别是我在后者中录制而只在前者中观看。

在实时取景模式下,图像会正确更新。我设置了一个触发记录视图的按钮,但在此采集过程中,GUI 变得无响应并且图像没有得到更新。让我向您展示代码的相关部分:

import numpy as np
from PyQt4 import QtGui, QtCore
import pyqtgraph as pg
from lantz.drivers.andor.ccd import CCD

app = QtGui.QApplication([])

def updateview():     # <-- this works OK
    global img, andor
    img.setImage(andor.most_recent_image16(andor.detector_shape),
                 autoLevels=False)

def liveview():
    """ Image live view when not recording
    """
    global andor, img, viewtimer

    andor.acquisition_mode = 'Run till abort'
    andor.start_acquisition()
    viewtimer.start(0)

def UpdateWhileRec():
    global stack, andor, img, n, ishape

    j = 0
    while j < n:
        if andor.n_images_acquired > j:

            # Data saving    <-- this part (and the whole while-loop) works OK
            i, j = andor.new_images_index
            stack[i - 1:j] = andor.images16(i, j, ishape, 1, n)

            # Image updating <-- this doesn't work
            img.setImage(stack[j - 1], autoLevels=False)

    liveview()   # After recording, it goes back to liveview mode

def record(n):
    """ Record an n-frames acquisition
    """
    global andor, ishape, viewtimer, img, stack, rectimer

    andor.acquisition_mode = 'Kinetics'
    andor.set_n_kinetics(n)
    andor.start_acquisition()

    # Stop the QTimer that updates the image with incoming data from the
    # 'Run till abort' acquisition mode.
    viewtimer.stop()
    QtCore.QTimer.singleShot(1, UpdateWhileRec)

if __name__ == '__main__':

    with CCD() as andor:

        win = QtGui.QWidget()
        rec = QtGui.QPushButton('REC')
        imagewidget = pg.GraphicsLayoutWidget()
        p1 = imagewidget.addPlot()
        img = pg.ImageItem()
        p1.addItem(img)

        layout = QtGui.QGridLayout()
        win.setLayout(layout)
        layout.addWidget(rec, 2, 0)
        layout.addWidget(imagewidget, 1, 2, 3, 1)

        win.show()

        viewtimer = QtCore.QTimer()
        viewtimer.timeout.connect(updateview)

        # Record routine
        n = 100
        newimage = np.zeros(ishape)
        stack = np.zeros((n, ishape[0], ishape[1]))
        rec.pressed.connect(lambda: record(n))

        liveview()

        app.exec_()
        viewtimer.stop()

如您所见UpdateWhileRec,每次采集只运行一次,而updateview运行直到viewtimer.stop()被调用。

我是 PyQt 和 PyQtGraph 的新手,所以无论解决我当前问题的特定方式如何,都可能有更好的方法来做其他所有事情。如果是这样,请告诉我!

先谢谢了

4

1 回答 1

1

您的问题源于您需要将控制权返回给 Qt 事件循环以重绘图片。UpdateWhileRec由于您在等待获取下一张图像时仍处于回调中,因此 Qt 永远没有机会绘制图像。只有退出该功能后它才有机会UpdateWhileRec

我建议进行以下更改。

然后,而不是你的 while 循环UpdateWhileRec,有一个 QTimer 定期调用你当前的 while 循环的内容(我可能会建议一个单次计时器)。这确保了控制权将返回给 Qt,因此它可以在检查新图像之前绘制图像。

所以像:

def UpdateWhileRec():
    # Note, j should be initialised to 0 in the record function now
    global stack, andor, img, n, j, ishape 


    if andor.n_images_acquired > j:    
        # Data saving    <-- this part (and the whole while-loop) works OK
        i, j = andor.new_images_index
        stack[i - 1:j] = andor.images16(i, j, ishape, 1, n)

        # Image updating <-- this should now work
        img.setImage(stack[j - 1], autoLevels=False)

    if j < n:
        QTimer.singleShot(0, UpdateWhileRec)
    else:
        liveview()   # After recording, it goes back to liveview mode

请注意,您可能应该将函数和变量放在一个类中,并创建该类的一个实例(一个对象)。这样你就不必global到处打电话了,事情就更加封装了。

最终,您可能想查看您的 andor 库是否支持注册一个在新图像可用时调用的函数(回调),这将节省您执行此持续轮询和/或获取线程中的图像并将它们发回到要绘制的 GUI 线程。但是一步一个脚印!

于 2014-06-26T09:58:39.070 回答