持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,
在QT里面定时器是一个非常重要的概念,尤其是在需要规律的执行某个任务时,我们可以设置任务的定时执行之间,从而完成一系列的自动化操作。在将摄像头的视频数据实时显示到label时就需要借助定时器的配合,将每一帧读取转换为QImage类型,显示到label中,然后继续读取下一帧执行上述操作。当然上面的操作我们也可以放在一个while里面执行,但是使用while在进行界面编程时会导致界面假死,不响应别的处理请求的问题,所以还是要使用更加灵活的定时器来完成这一部分工作。
在上一篇博客中提到了怎么给pycharm配置qt designer更加方便的设计自己的界面,这一篇博客算是上篇博客的补充,因为许多时候我们都需要对视频数据进行处理,例如下面的代码中我将实时视频数据进行边缘检测后输出到label中,所以这时看到的并不是彩色图像,而是一幅二值化的边缘图像。代码如下
下面是UI界面文件,相比于上一篇博客中的界面没有太大的改变,仅增加了一个按钮,用来打开本地的摄像头
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'demo.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(1066, 796)
self.horizontalLayoutWidget = QtWidgets.QWidget(Form)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 10, 1051, 80))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.openimg = QtWidgets.QPushButton(self.horizontalLayoutWidget)
self.openimg.setObjectName("openimg")
self.horizontalLayout.addWidget(self.openimg)
self.detect = QtWidgets.QPushButton(self.horizontalLayoutWidget)
self.detect.setObjectName("detect")
self.horizontalLayout.addWidget(self.detect)
self.opencCanera = QtWidgets.QPushButton(self.horizontalLayoutWidget)
self.opencCanera.setObjectName("opencCanera")
self.horizontalLayout.addWidget(self.opencCanera)
self.closewindow = QtWidgets.QPushButton(self.horizontalLayoutWidget)
self.closewindow.setObjectName("closewindow")
self.horizontalLayout.addWidget(self.closewindow)
self.horizontalLayoutWidget_2 = QtWidgets.QWidget(Form)
self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(10, 90, 1051, 701))
self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label = QtWidgets.QLabel(self.horizontalLayoutWidget_2)
self.label.setObjectName("label")
self.horizontalLayout_2.addWidget(self.label)
self.retranslateUi(Form)
self.openimg.clicked.connect(Form.shouImg)
self.detect.clicked.connect(Form.edgeDetect)
self.closewindow.clicked.connect(Form.close)
self.opencCanera.clicked.connect(Form.showVideo)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.openimg.setText(_translate("Form", "打开图片"))
self.detect.setText(_translate("Form", "边缘检测"))
self.opencCanera.setText(_translate("Form", "打开本地摄像头"))
self.closewindow.setText(_translate("Form", "关闭窗口"))
self.label.setText(_translate("Form", "show Image"))
复制代码
对UI的调用代码如下,相对上一篇博客的改动较大
from demo import Ui_Form
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import cv2
import sys
class MainWindow(QMainWindow, Ui_Form):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent=parent)
self.setupUi(self)
self.path = None
self.cameraTimer = QTimer()
self.msg = QMessageBox()
# 打开图片按钮槽函数
def shouImg(self):
filePath = self.getFileDir()
self.path = filePath[0][0]
if self.cameraTimer.isActive() and self.path is not None:
self.cameraTimer.stop()
self.cap.release()
img = cv2.imread(filePath[0][0])
img_dis = QImage(img, img.shape[1], img.shape[0], QImage.Format_RGB888)
# 加载图片,并设定图片大小
img_dis = QPixmap(img_dis).scaled(int(img.shape[1]), int(img.shape[0]))
width = img_dis.width() ##获取图片宽度
height = img_dis.height() ##获取图片高度
if width / self.label.width() >= height / self.label.height(): ##比较图片宽度与label宽度之比和图片高度与label高度之比
ratio = width / self.label.width()
else:
ratio = height / self.label.height()
new_width = int(width / ratio) ##定义新图片的宽和高
new_height = int(height / ratio)
new_img = img_dis.scaled(new_width, new_height) ##调整图片尺寸
# img_dis = QPixmap(img_dis).scaled(int(img.shape[1]), int(img.shape[0]))
self.label.setPixmap(new_img)
# 获取文件地址函数
def getFileDir(self):
try:
self.file_path = QFileDialog.getOpenFileNames(self, "select file", "./", "*.*")
except Exception as e:
print(e)
return self.file_path
# 边缘检测按钮槽函数
def edgeDetect(self):
if self.cameraTimer.isActive() and self.path is not None:
self.cameraTimer.stop()
self.cap.release()
if self.path is None:
QMessageBox.information(QWidget(), '这是提示框', '请先打开一幅图像', QMessageBox.Yes | QMessageBox.No)
else:
img = cv2.imread(self.path, 0)
# print(img.shape)
img = cv2.Canny(img, 50, 200)
# print(img.shape)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_dis = QImage(img, img.shape[1], img.shape[0], QImage.Format_RGB888)
# 加载图片,并设定图片大小
img_dis = QPixmap(img_dis).scaled(int(img.shape[1]), int(img.shape[0]))
width = img_dis.width() ##获取图片宽度
height = img_dis.height() ##获取图片高度
if width / self.label.width() >= height / self.label.height(): ##比较图片宽度与label宽度之比和图片高度与label高度之比
ratio = width / self.label.width()
else:
ratio = height / self.label.height()
new_width = int(width / ratio) ##定义新图片的宽和高
new_height = int(height / ratio)
new_img = img_dis.scaled(new_width, new_height) ##调整图片尺寸
# img_dis = QPixmap(img_dis).scaled(int(img.shape[1]), int(img.shape[0]))
self.label.setPixmap(new_img)
# 调用本地摄像头按钮槽函数
def showVideo(self):
self.cap = cv2.VideoCapture(0)
self.cameraTimer.start(100)
self.cameraTimer.timeout.connect(self.OpenFrame)
# 调用本地摄像头显示视频,同时是定时器的槽函数
def OpenFrame(self):
ret, image = self.cap.read()
# 这个地方,与下面的地方放开后,打开摄像头看到的是实时的边缘检测视频
# image = cv2.Canny(image, 50, 180)
if ret:
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
vedio_img = QImage(image.data, image.shape[1], image.shape[0], QImage.Format_RGB888)
elif len(image.shape) == 1:
vedio_img = QImage(image.data, image.shape[1], image.shape[0], QImage.Format_Indexed8)
else:
# 这里的注释和上面的注释放开后显示的是实时的边缘检测视频
# image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
vedio_img = QImage(image.data, image.shape[1], image.shape[0], QImage.Format_RGB888)
self.label.setPixmap(QPixmap(vedio_img))
self.label.setScaledContents(True)
else:
self.cap.release()
self.cameraTimer.stop()
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
复制代码
运行界面如下
打开图像进行显示
打开图像的边缘检测结果
说明一下,边缘检测按钮使用时需要先用打开图片按钮打开一幅图像,不然的话会弹窗提示
打开摄像头的原彩图这里就不展示了,展示一下实时边缘检测的图像
在后面的博客中误会分享更多的代码,跟大家一起学习,有什么问题大家可以在评论中随时提出,一起讨论。