Source code for holypipette.gui.livefeed

from __future__ import print_function
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt

import traceback
import numpy as np


__all__ = ['LiveFeedQt']


[docs]class LiveFeedQt(QtWidgets.QLabel): def __init__(self, camera, image_edit=None, display_edit=None, mouse_handler=None, parent=None): super(LiveFeedQt, self).__init__(parent=parent) # The image_edit function (does nothing by default) gets the raw # unscaled image (i.e. a numpy array), while the display_edit # function gets a QPixmap and is meant to draw GUI elements in # "display space" (by default, a red cross in the middle of the # screen). if image_edit is None: image_edit = lambda frame: frame self.image_edit = image_edit if display_edit is None: display_edit = lambda img: img self.display_edit = display_edit self.mouse_handler = mouse_handler self.camera = camera self.width, self.height = self.camera.width, self.camera.height self.setMinimumSize(640, 480) self.setAlignment(Qt.AlignCenter) # Remember the last frame that we displayed, to not unnecessarily # process/show the same frame for slow input sources self._last_frameno = None self._last_edited_frame = None self.update_image() timer = QtCore.QTimer(self) timer.timeout.connect(self.update_image) timer.start(50) #20 Hz
[docs] def mousePressEvent(self, event): # Ignore clicks that are not on the image xs = event.x() - self.size().width()/2.0 ys = event.y() - self.size().height()/2.0 pixmap = self.pixmap() if abs(xs) > pixmap.width()/2.0 or abs(ys) > pixmap.height()/2.0: self.setFocus() return if self.mouse_handler is not None: self.mouse_handler(event)
[docs] @QtCore.pyqtSlot() def update_image(self): try: # get last frame from camera frameno, frame = self.camera.last_frame() if frame is None: return # Frame acquisition thread has stopped if self._last_frameno is None or self._last_frameno != frameno: # No need to preprocess a frame again if it has not changed frame = self.image_edit(frame) self._last_edited_frame = frame self._last_frameno = frameno else: frame = self._last_edited_frame if len(frame.shape) == 2: # Grayscale image via MicroManager if frame.dtype == np.dtype('uint32'): bytesPerLine = self.width*4 format = QtGui.QImage.Format_RGB32 else: bytesPerLine = self.width format = QtGui.QImage.Format_Indexed8 else: # Color image via OpenCV bytesPerLine = 3*self.width format = QtGui.QImage.Format_RGB888 q_image = QtGui.QImage(frame.data, self.width, self.height, bytesPerLine, format) if format == QtGui.QImage.Format_RGB888: # OpenCV returns images as 24bit BGR (and not RGB), but there is no # direct support for this format in QImage q_image = q_image.rgbSwapped() pixmap = QtGui.QPixmap.fromImage(q_image) size = self.size() width, height = size.width(), size.height() scaled_pixmap = pixmap.scaled(width, height, Qt.KeepAspectRatio, Qt.SmoothTransformation) if self.display_edit is not None: self.display_edit(scaled_pixmap) self.setPixmap(scaled_pixmap) except Exception: print(traceback.format_exc())