赞
踩
在之前的PYQT5笔记 008 :图片读出界面程序,如果想对界面进行视频的帧进行处理然后显示,最简单的想法可能是,将多个显示内容依次写出来:
dir = r"C:\Users\Administrator\Desktop\car.jpg"
self.label.setPixmap(showImage)
time.sleep(3)
dir = r"C:\Users\Administrator\Desktop\cat.jpg"
self.label.setPixmap(showImage)
但这样写运行的效果为,显示灰色无内容的界面,然后几秒之后直接显示cat图像,而没有car图像。解决方法是使用线程实现:
def readframe(self):
th = Thread(target=self.myreadframe) # 需要 from threading import *
th.start()
def myreadframe(self):
dir = r"C:\Users\Administrator\Desktop\car.jpg"
self.SetPic(dir)
dir = r"C:\Users\Administrator\Desktop\cat.jpg"
self.SetPic(dir)
def SetPic(self,dir):
pixmap = QPixmap(dir)
self.label2.setPixmap(pixmap)
time.sleep(3)
print(123)
Python 标准库提供了threading,要启动一个单独的线程,需创建一个Thread实例,然后启动它。
x = threading.Thread(target=thread_function, args=(1,))
x.start()
到此位置,可以思考一下线程的停止了,如果创建了一个服务线程,主线程已经停止,但服务线程还能工作,如以下例子:
import threading
import time
def server():
while True:
print("服务线程运行中")
time.sleep(1)
if __name__ == '__main__':
ser = threading.Thread(target=server)
ser.start()
print('主线程开始')
time.sleep(6)
print('主线程结束')
使用以下设置为守护线程,设置为守护线程后,在主线程退出后,守护线程也会退出(即当pyqt推出后,守护)。
ser.daemon = True
或者
ser = threading.Thread(target=server, args=(index,), daemon=True)
这样就能正常运行了:
import threading
import time
def server():
while True:
print("服务线程运行中")
time.sleep(1)
if __name__ == '__main__':
ser = threading.Thread(target=server)
ser.daemon = True
ser.start()
print('主线程开始')
time.sleep(6)
print('主线程结束')
还可以进行等待的设置比如ser.join(),当ser的方法运行完之后,在进行下一步的运行。
ser = threading.Thread(target=server)
ser.daemon = True
ser.start()
ser.join()
print('主线程开始')
time.sleep(6)
print('主线程结束')
还可以创建多线程:
threads = list() # 用一个容器盛放线程,join时可以在启动完成之后进行join
for index in range(3):
x = threading.Thread(target=thread_function)
threads.append(x)
x.start()
# submit提交 import threading import time import concurrent.futures from concurrent.futures.thread import ThreadPoolExecutor def server(a,b): print(a+b) time.sleep(1) return a # while True: # print("服务线程运行中") # time.sleep(1) if __name__ == '__main__': # ser = threading.Thread(target=server) # ser.daemon = True # ser.start() # ser.join() with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(server, 1, 2)# 返回future对象 print(future.result()) # 获取函数的返回值 并打印 print('主线程开始') time.sleep(6) print('主线程结束')
# map方法提交,执行可迭代的对象
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
executor.map(thread_function, range(3))# range(3)为 iterable object
# 更多内容详见官方文档
# 视频教程 https://www.bilibili.com/video/BV1wb4y1S7d6?
https://realpython.com/intro-to-python-threading/
https://docs.python.org/zh-cn/3/library/threading.html
import cv2 import sys from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * from threading import * import time class mywindow(QWidget): def __init__(self): super().__init__() return self.initUI() def initUI(self): self.setGeometry(300, 300, 800, 600) self.setWindowTitle("showcamera") self.lable = QLabel("showcamera", self) self.lable.setGeometry(0, 0, 800, 600) self.lable.setScaledContents(True) self.show() def SetPic(self, img): self.lable.setPixmap(QPixmap.fromImage(img)) def showcamre(): imgName, imgType = QFileDialog.getOpenFileName(None, "打开mp4", "", "*.mp4;;*.png;;All Files(*)") cap = cv2.VideoCapture(imgName) # 或读取相机cap = cv2.VideoCapture(0) # 视频流设置 参数详见https://github.com/opencv/opencv/blob/master/modules/videoio/include/opencv2/videoio.hpp cap.set(cv2.CAP_PROP_FPS, 60) //帧率 帧/秒 https://www.javaroad.cn/questions/288491 while cap.isOpened(): success, frame = cap.read() if success == False: continue a = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888) mywindow.SetPic(a) time.sleep(0.01) # https://stackoverflow.com/questions/52068277/change-frame-rate-in-opencv-3-4-2 app = QApplication(sys.argv) window = mywindow() th = Thread(target=showcamre)# https://www.bbsmax.com/A/kmzLkAjKdG/ th.start() app.exec_()
“不断清除相机的帧缓冲区” - 这是关键,我想知道为什么所有初学者教程都忽略了这一点,只是盲目地循环轮询相机并导致 CPU 利用率过高。或者,我可以只 sleep() 循环一段时间以等待下一帧以避免处理同一帧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。