1

I have a custom QLabel class which is called ImageLabel to show images and video stream. I want to update the image with the setPixmap() method but it doesn't update the image correctly.

Note: StreamThread method is related to the video stream and I don't use it to update the image for now.

Here is the distorted image: enter image description here

Main class:

import sys

from PyQt5.QtCore import Qt, pyqtSlot
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QPushButton, QHBoxLayout


from ImageLabel import ImageLabel
from Stream_Thread import Stream_Thread

import cv2

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.init_UI()


    def init_UI(self):
        self.setFixedSize(690, 530)
        self.image_lbl = ImageLabel()

        # start the video stream of selected camera
        th = Stream_Thread()
        th.set_index(1)
        th.changePixmap.connect(self.setImage, Qt.QueuedConnection)
        th.start()


        btn_cnt = QPushButton("Continue")
        btn_pa = QPushButton("Pause")

        hbox = QHBoxLayout()
        hbox.addWidget(btn_cnt)
        hbox.addWidget(btn_pa)

        vbox = QVBoxLayout()
        vbox.addWidget(self.image_lbl)
        vbox.addLayout(hbox)

        self.setLayout(vbox)

        btn_pa.clicked.connect(lambda: self.btn_pa_clicked(th))

        self.show()


    @pyqtSlot(QImage)
    def setImage(self, image):
       self.image_lbl.pixmap = QPixmap.fromImage(image).scaled(720, 540)
       self.image_lbl.setPixmap(QPixmap.fromImage(image).scaled(720, 540))

    def btn_pa_clicked(self, th):
        th.terminate()                                                    # terminates the video stream

        image = cv2.imread("img/49.jpg", cv2.COLOR_BGR2RGB)  # self.image_lbl.pixmap
        # image = image.toImage()
        if image is not None:
            (h, w, c) = image.shape
            qimage = QImage(image.data, h, w, 3 * h, QImage.Format_RGB888)
            self.image_lbl.pixmap = QPixmap.fromImage(qimage)
            #self.image_lbl.setPixmap(QPixmap.fromImage(qimage))
            self.image_lbl.repaint()


def main():
    app = QApplication(sys.argv)
    main_form = MainWindow()
    sys.exit(app.exec_())



if __name__ == '__main__':
    main()

StreamThread class:

import cv2
from PyQt5.QtCore import QThread, pyqtSignal, Qt
from PyQt5.QtGui import QImage

#https://stackoverflow.com/a/44404713/13080899
class Stream_Thread(QThread):
    changePixmap = pyqtSignal(QImage)

    def __init__(self):
        super(Stream_Thread, self).__init__()
        self.ref = False        #refresh flag

    def set_index(self, index = 0):
        self.index = int(index)

    def refresh(self):
        self.ref = True
        self.capt.open(self.index)


    def run(self):
        self.capt = cv2.VideoCapture(self.index, cv2.CAP_DSHOW)

        while(True):
            ret, frame = self.capt.read()

            if ret:
                rbgImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                h, w, ch = rbgImage.shape
                bytesPerLine = ch*w
                convertToQtFormat = QImage(rbgImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
                p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
                self.changePixmap.emit(p)

ImageLabel class:

from PyQt5 import QtGui, QtCore
from PyQt5.QtCore import Qt, QSize, pyqtSignal, QObject, QPoint, pyqtSlot
from PyQt5.QtWidgets import QLabel

class Communicate(QObject):
    cor_update = pyqtSignal()
    cor_curr = pyqtSignal()

class ImageLabel(QLabel):
    def __init__(self, width=720, height=540):
        super(ImageLabel, self).__init__()
        self.setMouseTracking(True)
        self.pixmap = QtGui.QPixmap("img/im.jpg")

        #### initialize coordinates ####
        self.x1 = 0
        self.y1 = 0

        self.x_curr = 0
        self.y_curr = 0

        self.x2 = 0
        self.y2 = 0

        ##### enable state to allow user for drawing
        self.enable_labelling = False

        ##### enable state to track coordinates for drawing
        self.enable_cor = False

        ################################
        self.source = Communicate()

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.drawPixmap(self.rect(), self.pixmap)
        if self.enable_labelling == True:
            self.paintRect(event, qp)
            qp.end()

    def paintRect(self, event, qp):
        br = QtGui.QBrush(QtGui.QColor(50, 255, 255, 40))
        qp.setBrush(br)

        if self.enable_cor == True:
            qp.drawRect(QtCore.QRect(QPoint(self.x1, self.y1), QSize(self.x_curr - self.x1, self.y_curr - self.y1)))
        else:
            qp.drawRect(QtCore.QRect(QPoint(self.x1, self.y1), QSize(self.x2 - self.x1, self.y2 - self.y1)))

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton and self.enable_labelling == True:
            self.x1 = event.x()
            self.y1 = event.y()

            self.enable_cor = True

            self.source.cor_update.emit()

    def mouseMoveEvent(self, event):
        self.x_curr = event.x()
        self.y_curr = event.y()

        self.source.cor_curr.emit()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton and self.enable_labelling == True:
            self.x2 = event.x()
            self.y2 = event.y()

            self.source.cor_update.emit()

            self.enable_cor = False
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Ugurcan
  • 366
  • 1
  • 4
  • 17

1 Answers1

1

Instead of opening image by Imread and convert it to QImage, open it by QImage and convert the format that should solve your problem. Use of:

image = QImage("img/49.jpg");
image = image.convertToFormat(QImage.Format_RGB888);

this is psudo code and not tested, maybe some modification are needed.

Farshid616
  • 1,404
  • 1
  • 14
  • 26
  • That worked but I actually have NumPy images. So the problem is converting part. How can I convert image numpy to QImage correctly? – Ugurcan Dec 08 '20 at 14:54
  • which part of the code is that converting section? – Farshid616 Dec 08 '20 at 17:47
  • `(h, w, c) = image.shape qimage = QImage(image.data, h, w, 3 * h, QImage.Format_RGB888)` The part is in the main class but it is working now. Thank you. – Ugurcan Dec 11 '20 at 07:03