Python 如何结合 OpenCV 和 PyQt 来创建一个简单的 GUI?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28282434/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 03:03:07  来源:igfitidea点击:

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

pythonpython-2.7opencvpyqt4

提问by

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.

我需要对图像执行大量操作。所以我使用了 OpenCV。OpenCV 在图像处理方面非常高效,但是呈现合适的 GUI 并不太好。所以我决定使用 PyQt 绘制自定义 GUI 和 OpenCV 来处理我的图像。

I created a very simple program you directly picked from the documentation. I simply read a jpgpicture and save it in a pngformat by pressing the key s.

我创建了一个非常简单的程序,您可以直接从文档中选择。我只需读取一张jpg图片png并按 键将其保存为某种格式s

My aim is to replace the key swith 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.

我的目标是s使用 PyQt将按键替换为按下以执行相同操作的按钮。另外,我希望 PyQt 显示的窗口具有与 OpenCV 相同的行为:主要是该函数imshow()显示一个适合图像大小的窗口。

Here is my OpenCV simple code:

这是我的 OpenCV 简单代码:

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:

这是一个简单的 PyQt 代码来绘制一个简单的窗口:

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?

我怎样才能混合这两个代码来达到我的目标?

回答by Cui Heng

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 .

根据你的帖子修改了一些代码,我没有使用Opencv来渲染图像,而是使用QPixmap来渲染它。然后使用 KeyPressEvent 来捕获用户输入。

# -*- 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_()

回答by HelloGoodbye

You can create a QImagedirectly from the image data read by OpenCV, convert that to a QPixmapusing QPixmap.fromImageand then use that to set the pixmap of a QLabelusing the setPixmapmethod.

您可以QImage直接从 OpenCV 读取的图像数据中创建一个,将其转换为QPixmapusing QPixmap.fromImage,然后使用它来设置QLabelusingsetPixmap方法的像素图。

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

此页面显示了如何使用 PySide 和 OpenVC 查看网络摄像头提要:https://gist.github.com/bsdnoobz/8464000 。通过注释掉这两行,我也使它适用于视频

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_frameis the frame that was obtained with self.capture.read()).

在视频帧上(bgr_frame用 获得的帧在哪里self.capture.read())。

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

(请注意,此处进行的 OpenCV 常量有一些不同的命名和命名空间约定,可能是由于cv2版本不同?)