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.
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