我正在为摄像机编写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的新手,所以无论解决我目前问题的具体方式如何,都可能有更好的方法来做其他事情。如果是这样的话请告诉我!
先谢谢
答案 0 :(得分:1)
你的问题源于你需要将控制权返回给Qt事件循环才能重绘图片。由于您在等待下一个图像获取时仍然处于UpdateWhileRec
回调状态,因此Qt永远不会有机会绘制图像。退出函数UpdateWhileRec
后,它才有机会。
我建议进行以下更改。
然后代替UpdateWhileRec
中的while循环,有一个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
,而且事情更加封装。
最后,您可能想要查看您的oror库是否支持在新图像可用时(回调)注册要调用的函数,这将节省您执行此常量轮询和/或获取线程中的图像和将它们发布回要绘制的GUI线程。但是一步一步!