这个程序我是用的vscode写的(vscode是真的好用,简洁,喜欢这个编辑器哈哈),关于如何给vscode配置pyqt5以及如何解决配置过程遇到的问题,这些我在下一个博客进行解释。
这篇博客皆是我的原创,请尊重鄙人的劳动成果(谢谢),如果转载,请附上博客链接。
我们使用QTDisginer设计GUI界面,其中摄像头的显示使用QLabel控件,按钮使用QRadioButton控件,对按钮进行解释的文本我写在QLineEdit里面。使用QTextEdit来显示视频的参数,同时使用QLineEdit的控件对刚刚那个控件进行解释。
if __name__ == "__main__":
app = QApplication(sys.argv)
md = MainCode()
md.show()
sys.exit(app.exec_())
功能:在外部向程序内部传递参数
功能:执行到主程序末尾,解释器自动退出,但是如果需要中途退出程序,可以调用sys.exit函数,带有一个可选的整数参数返回给调用它的程序,表示你可以在主程序中捕获对sys.exit的调用。(0是正常退出,其他为异常)
更加具体的使用方法可以参考https://www.cnblogs.com/cherishry/p/5725184.html。
QApplication类:用于管理图形用户界面应用程序的控制流和主要设置。它包含主事件循环,对来自窗口系统和其他资源的所有事件进行处理和调度;它也对应用程序的初始化和结束进行处理,并且提供对话管理;还对绝大多数系统范围和应用程序范围的设置进行处理。
更加具体的解释参考https://blog.csdn.net/qq_21342281/article/details/85322927
def Face_Datection(self):
faceCascade = cv2.CascadeClassifier(
'D:\\Anaconda\\pkgs\\libopencv-3.4.2-h20b85fd_0\\Library\\etc\\haarcascades\\haarcascade_frontalface_default.xml') # 加载级联分类器
ret, img = self.cap.read() # 读取摄像头的帧
img = cv2.flip(img, 1) #镜像图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换成灰度图片
self.faces = faceCascade.detectMultiScale(
gray, # 检测图片
scaleFactor=1.1,
minNeighbors=3,
minSize=(20, 20)
)
for (x, y, w, h) in self.faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) # 画矩形
roi_gray = gray[y:y + h, x:x + w]
roi_color = img[y:y + h, x:x + w]
return img
def show_picture(self):
if self.vidoe_show_status == True:
img = self.Face_Datection()
showImage = QtGui.QImage(img.data, img.shape[1],img.shape[0], QtGui.QImage.Format_RGB888)
self.video_show.setPixmap(QtGui.QPixmap.fromImage(showImage))
else:
img = np.ones([640,480,1], dtype = np.uint8)* 255 #用numpy创建纯白的图片
showImage = QtGui.QImage(img.data, img.shape[1],img.shape[0], QtGui.QImage.Format_Grayscale8)
self.video_show.setPixmap(QtGui.QPixmap.fromImage(showImage))
使用Face_Datection()函数对图像中的人脸进行检测,并标记人脸。其中我们使用使用cap.read()函数将视频流拍到的图片先读取出来,之后将BGR图像转化为灰度图,以便后面可以快速的检测出人脸。
使用show_picture()函数将已经标记好人脸的图片显示在QLabel控件上面。其中video_show_status的bool类型数据,作用是用来判断当前是否显示图像。
如果video_show_status的值为True,则需要显示视频拍到的图像在Qlabel控件上面。因为接收的图像为BGR(opencv接收的彩色图像为BGR),需要使用QImage函数将它转为RGB图像。之后再通过QPixmap显示出来。
下面这个连接是QImage()函数的最后一个参数的详细解析,根据这个链接你可以由自己读取到的图片自由选择参数。https://blog.csdn.net/weixin_39485901/article/details/88047291
下面这个链接是讲解我的代码为什么要先Qimage在使用QPixmap原因https://blog.csdn.net/qq_39654127/article/details/81906232
那么这里我选择使用QT中的定时器QTimer。
self.timer = QTimer(self) #实列化一个计时器
self.cap = cv2.VideoCapture(0) #打开摄像头
self.cap.set(3, 640) # set Width
self.cap.set(4, 480) # set Height
self.timer.timeout.connect(self.show_picture) #连接显示上一步图片的函数
self.timer.timeout.connect(self.set_video_data)#这个连接的是显示视频数据的函数,譬
#如视频打开的时间,视频中的人数。
self.timer.start(40) #使用start函数将timer开始,并且每过40毫秒触发一次定时器,start触
#发timeout,timeout触发其所connect的函数
前面提过我们使用QTextEdit控件来显示视频的参数。
这里的set_video_data()就是上面程序的那个函数,我们使用定时器不段更新数据,并使用set_video_data()将它显示出来。
def set_video_data(self):
if self.vidoe_show_status == True: #判断此时摄像头的状态,打开就实时报告数据。
self.endtime = datetime.datetime.now() #记录摄像头运行到此时的时间
running_time = (self.endtime - self.starttime).seconds #startime是随着我们打开摄像头时开始计时的。
self.textEdit.setPlainText("视频打开的时间:%f\n视频中出现的人数:%d\n " % (running_time,len(self.faces))) #setPlainText是显示文本信息的函数。
关于具体程序计时方法,请看这个博客https://www.cnblogs.com/rookie-c/p/5827694.html
那么到这里这个程序已经基本完成了。以下是全部程序,不建议新手(虽然我也是新手)直接复制代码,建议先看我上面的代码讲解,再来实现下面的代码。
#coding:utf-8
import cv2
import sys
from PyQt5.QtWidgets import QApplication,QMainWindow,QFileDialog
from PyQt5.QtCore import QTimer
from PyQt5 import QtGui
import Ui_welcom
import time
import datetime
from mail import Mail
import numpy as np
class MainCode(QMainWindow, Ui_welcom.Ui_Dialog):
email_warning_status = True
faces = []
vidoe_show_status = False
starttime = 0
endtime = 0
def __init__(self):
QMainWindow.__init__(self)
Ui_welcom.Ui_Dialog.__init__(self)
self.setupUi(self)
self.close_video.setChecked(True)
self.open_video.clicked.connect(self.switch_video_show)
self.close_video.clicked.connect(self.switch_video_show)
self.timer = QTimer(self)
self.cap = cv2.VideoCapture(0) #打开摄像头
self.cap.set(3, 640) # set Width
self.cap.set(4, 480) # set Height
self.timer.timeout.connect(self.show_picture)
self.timer.timeout.connect(self.set_video_data)
self.timer.start(40)
def set_video_data(self):
if self.vidoe_show_status == True:
self.endtime = datetime.datetime.now()
running_time = (self.endtime - self.starttime).seconds
self.textEdit.setPlainText("视频打开的时间:%f\n视频中出现的人数:%d\n " % (running_time,len(self.faces)))
def switch_video_show(self):
if self.open_video.isChecked() == True:
self.starttime = datetime.datetime.now()
self.close_video.setChecked(False)
self.vidoe_show_status = True
else:
self.open_video.setChecked(False)
self.vidoe_show_status = False
def show_picture(self):
if self.vidoe_show_status == True:
img = self.Face_Datection()
showImage = QtGui.QImage(img.data, img.shape[1],img.shape[0], QtGui.QImage.Format_RGB888)
self.video_show.setPixmap(QtGui.QPixmap.fromImage(showImage))
else:
img = np.ones([640,480,1], dtype = np.uint8)* 255
showImage = QtGui.QImage(img.data, img.shape[1],img.shape[0], QtGui.QImage.Format_Grayscale8)
self.video_show.setPixmap(QtGui.QPixmap.fromImage(showImage))
def Face_Datection(self):
faceCascade = cv2.CascadeClassifier(
'D:\\Anaconda\\pkgs\\libopencv-3.4.2-h20b85fd_0\\Library\\etc\\haarcascades\\haarcascade_frontalface_default.xml') # 加载级联分类器
ret, img = self.cap.read() # 读取摄像头的帧
img = cv2.flip(img, 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换成灰度图片
self.faces = faceCascade.detectMultiScale(
gray, # 检测图片
scaleFactor=1.1,
minNeighbors=3,
minSize=(20, 20)
)
for (x, y, w, h) in self.faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) # 画矩形
roi_gray = gray[y:y + h, x:x + w]
roi_color = img[y:y + h, x:x + w]
return img
if __name__ == "__main__":
app = QApplication(sys.argv)
md = MainCode()
md.show()
sys.exit(app.exec_())