How do I pass an image array to PyQt5 as a video stream?

677 Views Asked by At

I am working on trying to collect the video from a Basler GigE camera using PyPylon and converting it to an array. I want to be able to take this image array that is constantly updating and show it on a PyQt5 gui. I am unsure what I am doing wrong. Below is the code, any help would be greatly appreciated!

from PyQt5 import QtGui
from PyQt5.QtWidgets import QWidget, QApplication, QLabel, QVBoxLayout
from PyQt5.QtGui import QPixmap
import sys
import cv2
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QThread
import numpy as np
from pypylon import pylon

class BaslerVideo():
    def _videoGrab(self):
        camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateFirstDevice())
        
        camera.StartGrabbing(pylon.GrabStrategy_LatestImageOnly)
        converter = pylon.ImageFormatConverter()
        
        converter.OutputPixelFormat = pylon.PixelType_BGR8packed
        converter.OutputBitAlignment = pylon.OutputBitAlignment_MsbAligned
        
        while camera.IsGrabbing():
            grabResult = camera.RetrieveResult(5000, pylon.TimeoutHandling_ThrowException)
            
            if grabResult.GrabSucceeded():
                image = converter.Convert(grabResult)
                img = image.GetArray()
        return img




class VideoThread(QThread, BaslerVideo):
    change_pixmap_signal = pyqtSignal(np.ndarray)

    def run(self):
        # capture from web cam
        cap = BaslerVideo()
        while True:
            cv_img = cap._videoGrab()
            self.change_pixmap_signal.emit(cv_img)
            
class App(QWidget):
    def __inti__(self):
        super().__init__()
        self.setWindowTitle("GigE Cam Test")
        self.display_width = 640
        self.display_height = 480
        #Create the label that holds the image 
        self.image_label = QLabel(self)
        self.image_label.resize(self.display_width,self.display_height)
        #Create a text label 
        self.textLabel = QLabel("GigE Cam")
        
        #Create the box that will hold the image 
        vbox = QVBoxLayout()
        vbox.addWidget(self.image_label)
        vbox.addWidget(self.textLabel)
        #Set the layout 
        self.setLayout(vbox)
        
        #create the video capture thread 
        self.thread = VideoThread()
        #connect its signal to the update_image slot
        self.thread.change_pixmap_signal.connect(self.update_image)
        #Start the thread
        self.thread.start()
        
        @pyqtSlot(np.ndarray)
        def update_image(self, cv_img):
            """Updates the image_label with a new opencv image"""
            qt_img = self.convert_cv_qt(cv_img)
            self.image_label.setPixmap(qt_img)
            
        def convert_cv_qt(self, cv_img):
            """Convert from a numpy array img to a Qpixmap"""
            rgb_image = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
            h, w, ch = rgb_image.shape
            bytes_per_line = ch * w
            convert_to_Qt_format = QtGui.QImage(rgb_image.data, w, h, bytes_per_line,QtGui.QImage.Format_RGB888)
            p = convert_to_Qt_format.scaled(self.display_width,self.display_height, Qt.KeepAspectRatio)
            return QPixmap().fromImage(p)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    a = App()
    a.show()
    sys.exit(app.exec_())
0

There are 0 best solutions below