首页 > 解决方案 > OpenCV 图像处理后 QLabel 不更新图像

问题描述

我一直在尝试创建一个交互式 OpenCV 图像查看器,我将能够在操作后立即查看图像。就像说,我正在对图像应用二进制阈值操作并从 PyQt 滑块更改阈值。现在,我想在图像查看器中查看每个阈值图像。

为此,我使用 python OpenCV 和 PyQT5 lib 创建了一个非常基本的程序。但是,图像没有在 QLabel 中更新。

下面是我的代码:

import sys
import cv2
import numpy as np
import imutils
from PyQt5 import QtCore
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout, QLCDNumber, QSlider, QLabel, QCheckBox
from PyQt5.QtGui import QPixmap, QImage


class MyWindow(QWidget):

def __init__(self):
    super().__init__()
    self.imglabel = QLabel(self)
    self.imglabel.setFixedSize(1200, 900)
    ori_img = cv2.imread("../resources/omr-1-ans-ori.png", cv2.IMREAD_COLOR)
    ori_img = imutils.resize(ori_img, height=960)
    self.gray_img = cv2.cvtColor(ori_img, cv2.COLOR_BGR2GRAY)
    self.gray_img_c = ori_img

    self.thresh = False
    self.thresh_karnel_size = 11

    self.init_ui()

def init_ui(self):
    # lcd = QLCDNumber(self)
    hbox1 = QHBoxLayout()
    cb_thresh = QCheckBox('thresh', self)
    cb_thresh.setChecked(False)

    cb_thresh.stateChanged.connect(self.changeTitleThresh)
    hbox1.addWidget(cb_thresh)

    thresh_slider = QSlider(Qt.Horizontal, self)
    thresh_slider.setFocusPolicy(Qt.StrongFocus)
    thresh_slider.setTickPosition(QSlider.TicksBothSides)
    thresh_slider.setTickInterval(1)
    thresh_slider.setSingleStep(1)
    thresh_slider.setPageStep(1)
    thresh_slider.setMinimum(1)
    thresh_slider.setMaximum(127)
    thresh_slider.valueChanged[int].connect(self.threshSliderChangeValue)

    vbox = QVBoxLayout()
    vbox.addLayout(hbox1)
    vbox.addWidget(thresh_slider)
    vbox.addWidget(self.imglabel)
    self.setLayout(vbox)

    self.setGeometry(50, 50, 1200, 768)
    self.setWindowTitle('Learning PyQT5')
    self.updateImage()
    self.show()

def changeTitleThresh(self, state):
    # print("thresh checkbox: ", state, Qt.Checked)
    if state == Qt.Checked:
        self.thresh = True
    else:
        self.thresh = False

def threshSliderChangeValue(self, value):

    ksize = (value * 2) + 1
    print("ksize: ", ksize)
    if ksize > 1 and ksize % 2 != 0 and self.thresh:
        self.thresh_karnel_size = ksize
        self.gray_img = cv2.threshold(self.gray_img, self.thresh_karnel_size, 255, cv2.THRESH_BINARY)[1]
        self.gray_img_c = cv2.cvtColor(self.gray_img.copy(), cv2.COLOR_GRAY2BGR)
        self.updateImage()

def updateImage(self):

    height, width, channel = self.gray_img_c.shape
    bytesPerLine = 3 * width
    qImg = QImage(self.gray_img_c.data, width, height, bytesPerLine, QImage.Format_RGB888)
    pixMap = QPixmap.fromImage(qImg)
    pixMap = pixMap.scaled(700, 500, Qt.KeepAspectRatio)
    self.imglabel.setPixmap(pixMap)
    self.imglabel.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyWindow()
    sys.exit(app.exec_())

我已经尝试了通过谷歌搜索找到的所有解决方案。但是,无法修复它。任何帮助或提示将不胜感激。

标签: pythonopencvpyqtpyqt5python-3.7

解决方案


原始图像必须保持不变,但您每次都在应用过滤器并对其进行修改,在下面的示例中,我展示了正确的方法

import sys
import cv2
import imutils
from PyQt5 import QtCore, QtGui, QtWidgets


class MyWindow(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        ori_img = cv2.imread("../resources/omr-1-ans-ori.png", cv2.IMREAD_COLOR)
        self.original_image_color = imutils.resize(ori_img, height=960)
        self.original_image_gray = cv2.cvtColor(self.original_image_color, cv2.COLOR_BGR2GRAY)

        self.thresh = False
        self.thresh_karnel_size = 11

        self.init_ui()

    def init_ui(self):
        self.imglabel = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
        self.imglabel.setFixedSize(1200, 900)

        cb_thresh = QtWidgets.QCheckBox('thresh', checked=False)
        cb_thresh.stateChanged.connect(self.changeTitleThresh)

        self.thresh_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal, 
            focusPolicy=QtCore.Qt.StrongFocus,
            tickPosition=QtWidgets.QSlider.TicksBothSides,
            tickInterval=1,
            singleStep=1,
            pageStep=1,
            minimum=1,
            maximum=127)
        self.thresh_slider.valueChanged[int].connect(self.threshSliderChangeValue)

        vbox = QtWidgets.QVBoxLayout(self)
        vbox.addWidget(cb_thresh)
        vbox.addWidget(self.thresh_slider)
        vbox.addWidget(self.imglabel)
        self.threshSliderChangeValue(self.thresh_slider.value())
        self.setGeometry(50, 50, 1200, 768)
        self.setWindowTitle('Learning PyQT5')
        self.show()

    @QtCore.pyqtSlot(int)
    def changeTitleThresh(self, state):
        self.thresh = state == QtCore.Qt.Checked
        self.threshSliderChangeValue(self.thresh_slider.value())

    @QtCore.pyqtSlot(int)
    def threshSliderChangeValue(self, value):
        ksize = (value * 2) + 1
        if ksize > 1 and ksize % 2 != 0 and self.thresh:
            self.thresh_karnel_size = ksize
            _, gray_img = cv2.threshold(self.original_image_gray, self.thresh_karnel_size, 255, cv2.THRESH_BINARY)
            gray_img_c = cv2.cvtColor(gray_img.copy(), cv2.COLOR_GRAY2BGR)
            self.updateImage(gray_img_c)
        else:
            self.updateImage(self.original_image_color)

    def updateImage(self, image):
        height, width, channel = image.shape
        bytesPerLine = 3 * width
        qImg = QtGui.QImage(image.data, width, height, bytesPerLine, QtGui.QImage.Format_RGB888)
        pixMap = QtGui.QPixmap.fromImage(qImg).scaled(700, 500, QtCore.Qt.KeepAspectRatio)
        self.imglabel.setPixmap(pixMap)


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    ex = MyWindow()
    sys.exit(app.exec_())

推荐阅读