QLabel не обновляет изображение после манипулирования изображениями OpenCV - PullRequest
0 голосов
/ 19 января 2019

Я пытался создать интерактивный просмотрщик изображений 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_())

Я пробовал каждое решение, найденное через поиск в Google. Но, не мог это исправить. Любая помощь или подсказка будет высоко ценится.

1 Ответ

0 голосов
/ 19 января 2019

Исходное изображение должно оставаться неповрежденным, но вы применяете фильтр и изменяете его каждый раз, в следующем примере я показываю правильный способ сделать это

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_())
...