2023年一月份跟二月份創(chuàng)建了一個(gè)PyQT5人工智能軟件開發(fā)系列的文章系列,過去的兩個(gè)月都沒怎么更新,心里一直想有時(shí)間繼續(xù)更新下去,今天又更新了一篇,基于PyQT5實(shí)現(xiàn)多線程、界面化、YOLOv8對(duì)象檢測(cè)、實(shí)例分割、姿態(tài)評(píng)估的推理。
基本設(shè)計(jì)思路
這個(gè)系列我好久沒有更新了,今天更新一篇PyQT5中如何實(shí)現(xiàn)YOLOv8 + ONNRUNTIME推理界面化與多線程支持。首先需要實(shí)現(xiàn)三個(gè)類分別完成YOLOv8的對(duì)象檢測(cè)、實(shí)例分割、姿態(tài)評(píng)估模型推理。然后在實(shí)現(xiàn)界面類,構(gòu)建如圖:

推理類型通過單選按鈕實(shí)現(xiàn)選擇,支持對(duì)象檢測(cè)、實(shí)例分割、姿態(tài)評(píng)估。參數(shù)設(shè)置選擇模型文件與標(biāo)簽文件地址作為輸入,同時(shí)選擇置信度,置信度之在0~1之間。 推理按鈕開發(fā)推理演示,支持視頻與圖像文件,開始推理會(huì)單獨(dú)開啟一個(gè)推理線程實(shí)現(xiàn)推理,推理結(jié)果通過信號(hào)發(fā)送到指定的槽函數(shù)處理之后更新界面,通過信號(hào)與槽機(jī)制實(shí)現(xiàn)界面線程跟推理線程相互獨(dú)立與數(shù)據(jù)共享。
界面代碼實(shí)現(xiàn)
界面部分通過一個(gè)QWidget實(shí)現(xiàn)一個(gè)面板,通過垂直與水平布局實(shí)現(xiàn)界面組件的布局管理,相關(guān)的代碼實(shí)現(xiàn)如下:
classYOLOv8InferPanel(QtWidgets.QWidget): def__init__(self,parent=None): super().__init__(parent) #文本標(biāo)簽 self.rbtn0=QtWidgets.QRadioButton("對(duì)象檢測(cè)") self.rbtn1=QtWidgets.QRadioButton("實(shí)例分割") self.rbtn3=QtWidgets.QRadioButton("姿態(tài)評(píng)估") self.rbtn0.setChecked(True) hbox_layout1=QtWidgets.QHBoxLayout() hbox_layout1.addWidget(self.rbtn0) hbox_layout1.addWidget(self.rbtn1) hbox_layout1.addWidget(self.rbtn3) panel3=QtWidgets.QGroupBox("推理類型") panel3.setLayout(hbox_layout1) #輸入文本框 self.image_file_edit=QtWidgets.QLineEdit() self.image_file_edit.setMinimumWidth(100) self.image_file_edit.setEnabled(False) fileBtn=QtWidgets.QPushButton("圖像文件") self.weight_file_path=QtWidgets.QLineEdit() self.weight_file_path.setMinimumWidth(100) self.weight_file_path.setEnabled(False) modelBtn=QtWidgets.QPushButton("模型文件") self.label_file_path=QtWidgets.QLineEdit() self.label_file_path.setMinimumWidth(100) self.label_file_path.setEnabled(False) labelBtn=QtWidgets.QPushButton("標(biāo)簽文件") self.conf_spinbox=QtWidgets.QDoubleSpinBox() self.conf_spinbox.setRange(0,1) self.conf_spinbox.setSingleStep(0.01) self.conf_spinbox.setValue(0.25) grid_layout2=QtWidgets.QGridLayout() grid_layout2.addWidget(fileBtn,0,0) grid_layout2.addWidget(self.image_file_edit,0,1) grid_layout2.addWidget(modelBtn,0,2) grid_layout2.addWidget(self.weight_file_path,0,3) grid_layout2.addWidget(labelBtn,1,0) grid_layout2.addWidget(self.label_file_path,1,1) grid_layout2.addWidget(QtWidgets.QLabel("置信:"),1,2) grid_layout2.addWidget(self.conf_spinbox,1,3) panel2=QtWidgets.QGroupBox("參數(shù)設(shè)置") panel2.setLayout(grid_layout2) #輸入文本框 self.label=QtWidgets.QLabel() self.label.setMinimumSize(1280,720) pixmap=QtGui.QPixmap("images/wp.jpg") pix=pixmap.scaled(QtCore.QSize(1280,720),QtCore.Qt.KeepAspectRatio) self.label.setPixmap(pix) self.label.setAlignment(QtCore.Qt.AlignCenter) self.label.setStyleSheet("background-color:black;color:green") self.startBtn=QtWidgets.QPushButton("開始推理") self.stopBtn=QtWidgets.QPushButton("停止") self.startBtn.setStyleSheet("background-color:cyan;color:black") self.stopBtn.setStyleSheet("background-color:gray;color:white") self.stopBtn.setEnabled(False) hbox_layout=QtWidgets.QHBoxLayout() hbox_layout.addStretch(1) hbox_layout.addWidget(self.startBtn) hbox_layout.addWidget(self.stopBtn) panel1=QtWidgets.QWidget() panel1.setLayout(hbox_layout) #添加到布局管理器中 vbox_layout=QtWidgets.QVBoxLayout() vbox_layout.addWidget(panel3) vbox_layout.addWidget(panel2) vbox_layout.addWidget(panel1) vbox_layout.addWidget(self.label) vbox_layout.addStretch(1) #面板容器 self.setLayout(vbox_layout) #setuplistener modelBtn.clicked.connect(self.on_weight_select) fileBtn.clicked.connect(self.on_update_image) labelBtn.clicked.connect(self.on_label_select) self.startBtn.clicked.connect(self.on_yolov8_infer) self.work_thread=None
推理線程
基于QThread繼承實(shí)現(xiàn)run方法,完成推理線程構(gòu)建,根據(jù)傳入的參數(shù)不同,初始化不同的推理類型(對(duì)象檢測(cè)、實(shí)例分割、姿態(tài)評(píng)估),推理線程實(shí)現(xiàn)代碼如下:
classInferenceThread(QtCore.QThread):
fire_stats_signal=QtCore.pyqtSignal(dict)
def__init__(self,settings):
super(InferenceThread,self).__init__()
self.settings=settings
self.detector=None
ifself.settings.model_type==0:
self.detector=YOLOv8ORTDetector(settings)
ifself.settings.model_type==1:
self.detector=YOLOv8ORTSegment(settings)
ifself.settings.model_type==2:
self.detector=YOLOv8ORTPose(settings)
self.input_image=settings.input_image
defrun(self):
ifself.detectorisNone:
return
ifself.input_image.endswith(".mp4"):
cap=cv.VideoCapture(self.input_image)
whileTrue:
ret,frame=cap.read()
ifretisTrue:
self.detector.infer_image(frame)
self.fire_stats_signal.emit({"result":frame})
else:
break
else:
frame=cv.imread(self.input_image)
self.detector.infer_image(frame)
self.fire_stats_signal.emit({"result":frame})
self.fire_stats_signal.emit({"done":"done"})
return



應(yīng)用程序演示
最終調(diào)用應(yīng)用程序代碼,實(shí)現(xiàn)啟動(dòng)與運(yùn)行的界面如下:
#初始化APP實(shí)例
importplatform
app=QtWidgets.QApplication(sys.argv)
if'Windows'==platform.system():
app.setStyle('Windows')
#初始化桌面容器
main_win=QtWidgets.QMainWindow()
#設(shè)置APP窗口名稱
main_win.setWindowTitle("YOLOv8多線程推理應(yīng)用演示-2號(hào)高手")
#初始化內(nèi)容面板
content_panel=YOLOv8InferPanel()
#設(shè)置窗口大小
main_win.setMinimumSize(1340,960)
main_win.setCentralWidget(content_panel)
#請(qǐng)求顯示
main_win.show()
#加載窗口并啟動(dòng)App
app.exec()
-
軟件
+關(guān)注
關(guān)注
69文章
5332瀏覽量
91575 -
人工智能
+關(guān)注
關(guān)注
1817文章
50094瀏覽量
265276 -
pyqt5
+關(guān)注
關(guān)注
0文章
25瀏覽量
3628
原文標(biāo)題:多線程界面化、ONNXRUNTIME + YOLOv8推理演示
文章出處:【微信號(hào):CVSCHOOL,微信公眾號(hào):OpenCV學(xué)堂】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
基于YOLOv8實(shí)現(xiàn)自定義姿態(tài)評(píng)估模型訓(xùn)練
使用YOLOv8做目標(biāo)檢測(cè)和實(shí)例分割的演示
YOLOv8自定義數(shù)據(jù)集訓(xùn)練到模型部署推理簡(jiǎn)析
TensorRT 8.6 C++開發(fā)環(huán)境配置與YOLOv8實(shí)例分割推理演示
YOLOv8版本升級(jí)支持小目標(biāo)檢測(cè)與高分辨率圖像輸入
教你如何用兩行代碼搞定YOLOv8各種模型推理
目標(biāo)檢測(cè)算法再升級(jí)!YOLOv8保姆級(jí)教程一鍵體驗(yàn)
三種主流模型部署框架YOLOv8推理演示
OpenCV4.8+YOLOv8對(duì)象檢測(cè)C++推理演示
基于YOLOv8的自定義醫(yī)學(xué)圖像分割
YOLOv8實(shí)現(xiàn)旋轉(zhuǎn)對(duì)象檢測(cè)
基于OpenCV DNN實(shí)現(xiàn)YOLOv8的模型部署與推理演示
RV1126 yolov8訓(xùn)練部署教程
使用ROCm?優(yōu)化并部署YOLOv8模型
如何實(shí)現(xiàn)YOLOv8 + ONNRUNTIME推理界面化與多線程支持
評(píng)論