pyqt5是一套Python绑定Digia QT5应用的框架。它可用于Python 2和3。Qt库是最强大的GUI库之一。pyqt5很大的优势就是跨平台,而且使用起来非常的方便,编写的代码比较精简,又能实现比较复杂的界面。在很多视觉程序中都需要GUI, 搭配OpenCV, pyqt5可方便的实现各种视觉类应用。下面的代码相当相当于一个框架,实现了摄像头采集到处理的一个框架,摄像头采集的代码放在单独的线程中,这样就避免了因为图像处理算法耗时较多而导致摄像头数据采集的不及时。

import sys
from PyQt5.QtWidgets import (QWidget, QPushButton, QApplication, QLabel)
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import QCoreApplication
import cv2
import threading
import copy


class demo_window(QWidget):

    def __init__(self):
        super().__init__()
        self.cap = cv2.VideoCapture()
        self.init_ui()

    def init_ui(self):
        self.image = QLabel(self)
        self.image.setGeometry(0, 0, 400, 300)
        self.image.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0.0284091, "
                                 + "stop:0 rgba(67, 88, 89, 177), stop:1 rgba(110, 161, 164, 195));")

        self.didou = QLabel(self)
        self.didou.setGeometry(300+140, 30, 60, 120)
        self.didou.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0.034091, "
                                 + "stop:0 rgba(210, 88, 89, 177), stop:1 rgba(210, 161, 164, 195));")

        self.label = QLabel(self)
        self.label.setText("<B>液面高度:</B>")
        self.label.move(500, 80)

        self.btn = QPushButton('打开摄像头', self)
        self.btn.move(410, 200)
        self.btn.clicked.connect(self.open_camera)

        self.btn = QPushButton('拍摄并识别', self)
        self.btn.move(510, 200)
        self.btn.clicked.connect(self.capture_and_rec)

        self.btn = QPushButton('关闭摄像头', self)
        self.btn.move(600, 200)
        self.btn.clicked.connect(self.close_camera)

        self.setGeometry(300, 300, 700, 300)
        self.setWindowTitle('Demo')

        self.stopEvent = threading.Event()
        self.stopEvent.clear()
        self.R = threading.Lock()

    def open_camera(self):
        if self.cap.isOpened():
            print("is opened!")
            return
        self.cap = cv2.VideoCapture("Capture00000.avi")
        if self.cap.isOpened():
            th = threading.Thread(target=self.Display)
            th.start()
        pass

    def close_camera(self):
        self.stopEvent.set()
        pass

    def capture_and_rec(self):
        self.R.acquire()
        frame = self.src_image
        self.R.release()
        # 处理图像的过程可以在这里完成
        img = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
        self.didou.setPixmap(QPixmap.fromImage(img))

    def Display(self):
        while self.cap.isOpened():
            success, frame = self.cap.read()
            if success is False:
                continue

            self.R.acquire()
            self.src_image = copy.deepcopy(frame)
            self.R.release()

            frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)  # RGB转BGR
            frame = cv2.resize(frame, (400, 300))
            img = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
            self.image.setPixmap(QPixmap.fromImage(img))
            cv2.waitKey(1)
            # 判断关闭事件是否已触发
            if self.stopEvent.is_set():
                self.stopEvent.clear()
                self.image.clear()
                self.cap.release()
                break


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