引言
学习多线程最典型的问题就是如何在多个线程之间传递消息与写作,PyQT5的线程支持在不同线程之间传递信号触发事件,实现多个线程之间的协助,完成诸如生产者-消费者这样经典的多线程协作。本文将通过QThread与信号槽机制构建一个生产者-消费者模型,演示多个线程之间的协作。
应用程序概述
这里演示了一个从图像采集(用本地图像数据集替代)到图像分析处理(简单二值化+形态学处理)、到主界面更新的应用程序。主界面是UI线程、图像采集跟图像分析分别在两个不同的工作线程中,通过信号与槽机制协作工作,相互配合实现图像采集到分析到结果更新到界面线程。
多线程协作信号触发示意图

代码实现
这样实现了三个类
ImageFetchThread // 图像采集 ImageAnalysisThread // 图像分析 ContentPanel // 界面显示与更新
这三个类的代码分别,interwetten与威廉的赔率体系 图像采集线程
1classImageFetchThread(QtCore.QThread): 2fire_stats_signal=QtCore.pyqtSignal(dict) 3 4def__init__(self,images_dir): 5super(ImageFetchThread,self).__init__() 6self.images_dir=images_dir 7self.read_next=True 8 9defrequest_image(self): 10self.read_next=True 11 12defrun(self): 13iflen(self.images_dir)==0: 14return 15files=os.listdir(self.images_dir) 16idx=0 17whileTrue: 18ifidx==len(files): 19break 20ifself.read_nextisTrue: 21print("graboneimage...") 22image=cv.imread(os.path.join(self.images_dir,files[idx])) 23gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY) 24idx+=1 25self.read_next=False 26self.fire_stats_signal.emit({"im_data":gray}) 27self.fire_stats_signal.emit({"done":"done"}) 28return
处理图像线程
1classImageAnalysisThread(QtCore.QThread):
2request_image_signal=QtCore.pyqtSignal()
3update_result_signal=QtCore.pyqtSignal(dict)
4
5def__init__(self):
6super(ImageAnalysisThread,self).__init__()
7self.image_data=None
8self.stop=False
9
10defprocess_im(self,results):
11self.image_data=results.get("im_data")
12ifresults.get("done")isnotNone:
13self.stop=True
14
15defrun(self):
16whileTrue:
17ifself.stopisTrue:
18break
19ifself.image_dataisNone:
20continue
21print("startedtoprocessoneimage...")
22#ret,binary=cv.threshold(self.image_data,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)
23binary=cv.adaptiveThreshold(self.image_data,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,
24cv.THRESH_BINARY_INV,25,10)
25se=cv.getStructuringElement(cv.MORPH_RECT,(7,7))
26resutl=cv.morphologyEx(binary,cv.MORPH_DILATE,se)
27self.request_image_signal.emit()
28self.update_result_signal.emit({"im_data":resutl})
29self.image_data=None
30self.update_result_signal.emit({"done":"done"})
31return
界面线程
1classContentPanel(QtWidgets.QWidget):
2def__init__(self,parent=None):
3super().__init__(parent)
4fileBtn=QtWidgets.QPushButton("目录...")
5self.image_files_dir=QtWidgets.QLineEdit()
6self.image_files_dir.setMinimumWidth(100)
7self.image_files_dir.setEnabled(False)
8self.processBtn=QtWidgets.QPushButton("开始处理")
9hbox_layout=QtWidgets.QHBoxLayout()
10hbox_layout.addWidget(fileBtn)
11hbox_layout.addWidget(self.image_files_dir)
12hbox_layout.addWidget(self.processBtn)
13panel1=QtWidgets.QGroupBox("目录选择")
14panel1.setLayout(hbox_layout)
15
16#图像标签
17self.imgLabel=QtWidgets.QLabel()
18self.imgLabel.setMinimumSize(800,600)
19self.imgLabel.setStyleSheet("background-color:black;color:deeppink")
20self.imgLabel.setAlignment(QtCore.Qt.AlignCenter)
21
22#添加到布局管理器中
23vbox_layout=QtWidgets.QVBoxLayout()
24vbox_layout.addWidget(panel1)
25vbox_layout.addWidget(self.imgLabel)
26vbox_layout.addStretch(1)
27
28#面板容器
29self.setLayout(vbox_layout)
30
31#setuplistener
32fileBtn.clicked.connect(self.on_select_image_dir)
33self.processBtn.clicked.connect(self.on_process)
34
35self.fetch_thread=None
36self.analysis_thread=None
37
38defon_select_image_dir(self):
39img_dir=QtWidgets.QFileDialog.getExistingDirectory(self,"图像文件夹",".")
40self.image_files_dir.setText(img_dir)
演示部分



-
多线程
+关注
关注
0文章
277浏览量
19933 -
应用程序
+关注
关注
37文章
3253浏览量
57650 -
OpenCV
+关注
关注
30文章
629浏览量
41309 -
图像分析
+关注
关注
0文章
82浏览量
18668 -
pyqt5
+关注
关注
0文章
25浏览量
3395
原文标题:PyQT5+OpenCV多线程协作演示
文章出处:【微信号:CVSCHOOL,微信公众号:OpenCV学堂】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
Java多线程的用法
可视可交互!H618上用OpenCV读取图像显示到PyQt5窗口上
多线程好还是单线程好?单线程和多线程的区别 优缺点分析
mfc多线程编程实例及代码,mfc多线程间通信介绍
什么是多线程编程?多线程编程基础知识
PyQT多线程正确的调用方式
PyQT5+OpenCV开发的应用如何打包发布?
OpenCV+PyQT5开发桌面应用几个重要的坑与解决
多线程事务怎么回滚?一个简单示例演示多线程事务
基于PyQT5与ONNXRUNTIME实现风格迁移应用

PyQT5+OpenCV多线程协作演示
评论