引言
學(xué)習(xí)多線程最典型的問(wèn)題就是如何在多個(gè)線程之間傳遞消息與寫作,PyQT5的線程支持在不同線程之間傳遞信號(hào)觸發(fā)事件,實(shí)現(xiàn)多個(gè)線程之間的協(xié)助,完成諸如生產(chǎn)者-消費(fèi)者這樣經(jīng)典的多線程協(xié)作。本文將通過(guò)QThread與信號(hào)槽機(jī)制構(gòu)建一個(gè)生產(chǎn)者-消費(fèi)者模型,演示多個(gè)線程之間的協(xié)作。
應(yīng)用程序概述
這里演示了一個(gè)從圖像采集(用本地圖像數(shù)據(jù)集替代)到圖像分析處理(簡(jiǎn)單二值化+形態(tài)學(xué)處理)、到主界面更新的應(yīng)用程序。主界面是UI線程、圖像采集跟圖像分析分別在兩個(gè)不同的工作線程中,通過(guò)信號(hào)與槽機(jī)制協(xié)作工作,相互配合實(shí)現(xiàn)圖像采集到分析到結(jié)果更新到界面線程。
多線程協(xié)作信號(hào)觸發(fā)示意圖

代碼實(shí)現(xiàn)
這樣實(shí)現(xiàn)了三個(gè)類
ImageFetchThread // 圖像采集 ImageAnalysisThread // 圖像分析 ContentPanel // 界面顯示與更新
這三個(gè)類的代碼分別,模擬圖像采集線程
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("開(kāi)始處理")
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#圖像標(biāo)簽
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)
演示部分



-
多線程
+關(guān)注
關(guān)注
0文章
279瀏覽量
20841 -
應(yīng)用程序
+關(guān)注
關(guān)注
38文章
3340瀏覽量
59799 -
OpenCV
+關(guān)注
關(guān)注
33文章
650瀏覽量
44192 -
圖像分析
+關(guān)注
關(guān)注
0文章
82瀏覽量
19124 -
pyqt5
+關(guān)注
關(guān)注
0文章
25瀏覽量
3586
原文標(biāo)題:PyQT5+OpenCV多線程協(xié)作演示
文章出處:【微信號(hào):CVSCHOOL,微信公眾號(hào):OpenCV學(xué)堂】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
Java多線程的用法
可視可交互!H618上用OpenCV讀取圖像顯示到PyQt5窗口上
多線程好還是單線程好?單線程和多線程的區(qū)別 優(yōu)缺點(diǎn)分析
mfc多線程編程實(shí)例及代碼,mfc多線程間通信介紹
什么是多線程編程?多線程編程基礎(chǔ)知識(shí)
PyQT多線程正確的調(diào)用方式
PyQT5+OpenCV開(kāi)發(fā)的應(yīng)用如何打包發(fā)布?
OpenCV+PyQT5開(kāi)發(fā)桌面應(yīng)用幾個(gè)重要的坑與解決
多線程事務(wù)怎么回滾?一個(gè)簡(jiǎn)單示例演示多線程事務(wù)
基于PyQT5與ONNXRUNTIME實(shí)現(xiàn)風(fēng)格遷移應(yīng)用

PyQT5+OpenCV多線程協(xié)作演示
評(píng)論