How to combine OpenCV with PyQt to create a simple GUI?

28,740

Solution 1

Modified some code basing on your post, I didn't use the Opencv to render the image, instead using QPixmap to render it. then use KeyPressEvent to capture the user input .

# -*- coding: utf-8 -*-


import numpy
import cv2
from PyQt4.QtGui import *
from PyQt4.QtCore import *


class MyDialog(QDialog):
    def __init__(self, parent=None):
        super(MyDialog, self).__init__(parent)

        self.cvImage = cv2.imread(r'cat.jpg')
        height, width, byteValue = self.cvImage.shape
        byteValue = byteValue * width

        cv2.cvtColor(self.cvImage, cv2.COLOR_BGR2RGB, self.cvImage)

        self.mQImage = QImage(self.cvImage, width, height, byteValue, QImage.Format_RGB888)

    def paintEvent(self, QPaintEvent):
        painter = QPainter()
        painter.begin(self)
        painter.drawImage(0, 0, self.mQImage)
        painter.end()

    def keyPressEvent(self, QKeyEvent):
        super(MyDialog, self).keyPressEvent(QKeyEvent)
        if 's' == QKeyEvent.text():
            cv2.imwrite("cat2.png", self.cvImage)
        else:
            app.exit(1)


if __name__=="__main__":
    import sys
    app = QApplication(sys.argv)
    w = MyDialog()
    w.resize(600, 400)
    w.show()
    app.exec_()

Solution 2

You can create a QImage directly from the image data read by OpenCV, convert that to a QPixmap using QPixmap.fromImage and then use that to set the pixmap of a QLabel using the setPixmap method.

This page shows how to view a webcam feed by using PySide and OpenVC: https://gist.github.com/bsdnoobz/8464000. I made it work for videos as well, by commenting out these two lines

self.capture.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, self.video_size.width())
self.capture.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, self.video_size.height())

and instead using

resized_bgr_frame = cv2.resize(
    bgr_frame,
    (self.video_size.width(), self.video_size.height()),
    interpolation=cv2.INTER_CUBIC if self.video_size.width() > bgr_frame.shape[1] else cv2.INTER_AREA)

on the video frame (where bgr_frame is the frame that was obtained with self.capture.read()).

(Note that there is some different naming and namespace conventions for the OpenCV constants going on here, perhaps due to differing cv2 versions?)

Share:
28,740
Admin
Author by

Admin

Updated on June 21, 2020

Comments

  • Admin
    Admin about 4 years

    I need to perform lot of operations on an image. So I used OpenCV. OpenCV is very efficient in image processing, however it is not too good to present a suitable GUI. So I decided to use PyQt to draw a custom GUI and OpenCV to process my image.

    I created a very simple program you directly picked from the documentation. I simply read a jpg picture and save it in a png format by pressing the key s.

    My aim is to replace the key s with a button to press to perform the same action using PyQt. Also, I want the window displayed by PyQt to have the same behavior as OpenCV: mainly speaking, the function imshow() displays a window that fits to the image size.

    Here is my OpenCV simple code:

    import numpy 
    import cv2
    
    class LoadImage:
        def loadImage(self):
            img = cv2.imread('photo.jpg')
            cv2.imshow('Image on a window',img)
            k = cv2.waitKey(0)
            if k == 27:
                cv2.destroyAllWindows()
            elif k == ord('s'):
                cv2.imwrite('photopng.png',img)
                cv2.destroyAllWindows()
    
    if __name__=="__main__":
        LI=LoadImage()
        LI.loadImage()
    

    Output:

    enter image description here

    Here is a simple PyQt code to draw a simple window:

    import sys
    from PyQt4 import QtGui
    
    class DrawWindow:
        def drawWindow(self):
            app=QtGui.QApplication(sys.argv)
            w=QtGui.QWidget()
            #w.resize(250,250)
            w.move(300,300)
            w.setWindowTitle("Simple Window")
            w.show()
    
            sys.exit(app.exec_())
    
    if __name__=="__main__":
        DW=DrawWindow()
        DW.drawWindow()
    

    How can I mix the 2 codes to reach my goal?

  • Admin
    Admin over 9 years
    Thank you for trying. First, I really need to use OpenCV for image processing. Second, I got several errors when compiled your code. +1 however for the effort.
  • Mailerdaimon
    Mailerdaimon over 9 years
    This Code seems correct. The processing is in OpenCV (e.g. look at cv2.cvtColor) and only the displaying is handled using Qt (QPixmap) which is fine. I am doing the same in a lot off scripts. Be carefull though when converting your image from cv to qt (search the web for converters)!