1.YOLO:CPU實時檢測(攝像頭、視頻)https://blog.csdn.net/qq_45445740/article/details/106557451
2.YOLOv8+PyQt,實現攝像頭或視頻的實時檢測
需要安裝 PySide6
和 ultralytics
pip install PySide6
pip install ultralytics
from PySide6 import QtWidgets, QtCore, QtGui
import cv2 as cv
import os, time
from threading import Thread# 屏蔽YOLO處理輸出的調試信息
os.environ['YOLO_VERBOSE'] = 'False'
from ultralytics import YOLOclass MWindow(QtWidgets.QMainWindow):def __init__(self):super().__init__()# 設置界面self.setupUI()self.camBtn.clicked.connect(self.startCamera)self.videoBtn.clicked.connect(self.startVideoFile)self.stopBtn.clicked.connect(self.stop)# 定義定時器,用于控制顯示攝像頭視頻的幀率self.timer_camera = QtCore.QTimer()# 定時到了,回調 self.show_cameraself.timer_camera.timeout.connect(self.show_camera)# 加載 YOLO nano 模型,第一次比較耗時,要20秒左右self.model = YOLO('yolov8m.pt')# 要處理的視頻幀圖片隊列,目前就放1幀圖片self.frameToAnalyze = []# 啟動處理視頻幀獨立線程Thread(target=self.frameAnalyzeThreadFunc,daemon=True).start()# 定義定時器,用于控制顯示視頻文件的幀率self.timer_videoFile = QtCore.QTimer()# 定時到了,回調 self.show_cameraself.timer_videoFile.timeout.connect(self.show_videoFile)# 當前要播放的視頻幀號self.vframeIdx = 0# cv.VideoCapture 實例self.cap = Noneself.stopFlag = Falsedef setupUI(self):self.resize(1200, 800)self.setWindowTitle(' YOLO-PyQt Demo')# central WidgetcentralWidget = QtWidgets.QWidget(self)self.setCentralWidget(centralWidget)# central Widget 里面的 主 layoutmainLayout = QtWidgets.QVBoxLayout(centralWidget)# 界面的上半部分 : 圖形展示部分topLayout = QtWidgets.QHBoxLayout()self.label_ori_video = QtWidgets.QLabel(self)self.label_treated = QtWidgets.QLabel(self)self.label_ori_video.setFixedSize(520,400)self.label_treated.setFixedSize(520,400)# self.label_ori_video.setMinimumSize(520,400)# self.label_treated.setMinimumSize(520,400)self.label_ori_video.setStyleSheet('border:1px solid #D7E2F9;')self.label_treated.setStyleSheet('border:1px solid #D7E2F9;')topLayout.addWidget(self.label_ori_video)topLayout.addWidget(self.label_treated)mainLayout.addLayout(topLayout)# 界面下半部分: 輸出框 和 按鈕groupBox = QtWidgets.QGroupBox(self)bottomLayout = QtWidgets.QHBoxLayout(groupBox)self.textLog = QtWidgets.QTextBrowser()bottomLayout.addWidget(self.textLog)mainLayout.addWidget(groupBox)btnLayout = QtWidgets.QVBoxLayout()self.videoBtn = QtWidgets.QPushButton('🎞?視頻文件')self.camBtn = QtWidgets.QPushButton('📹攝像頭')self.stopBtn = QtWidgets.QPushButton('🛑停止')btnLayout.addWidget(self.videoBtn)btnLayout.addWidget(self.camBtn)btnLayout.addWidget(self.stopBtn)bottomLayout.addLayout(btnLayout)def startCamera(self):# 參考 https://docs.opencv.org/3.4/dd/d43/tutorial_py_video_display.html# 在 windows上指定使用 cv.CAP_DSHOW 會讓打開攝像頭快很多,# 在 Linux/Mac上 指定 V4L, FFMPEG 或者 GSTREAMERself.cap = cv.VideoCapture(0, cv.CAP_DSHOW)if not self.cap.isOpened():print("1號攝像頭不能打開")returnif self.timer_camera.isActive() == False: # 若定時器未啟動self.timer_camera.start(30)self.stopFlag = Falsedef show_camera(self):ret, frame = self.cap.read() # 從視頻流中讀取if not ret:return# 把讀到的幀的大小重新設置frame = cv.resize(frame, (520, 400))self.setFrameToOriLabel(frame)def setFrameToOriLabel(self,frame):# 視頻色彩轉換回RGB,OpenCV images as BGRframe = cv.cvtColor(frame, cv.COLOR_BGR2RGB)qImage = QtGui.QImage(frame.data, frame.shape[1], frame.shape[0],QtGui.QImage.Format_RGB888) # 變成QImage形式# 往顯示視頻的Label里 顯示QImageself.label_ori_video.setPixmap(QtGui.QPixmap.fromImage(qImage))# 如果當前沒有處理任務if not self.frameToAnalyze:self.frameToAnalyze.append(frame)def frameAnalyzeThreadFunc(self):while True:if not self.frameToAnalyze:time.sleep(0.01)continueframe = self.frameToAnalyze.pop(0)results = self.model(frame)[0]img = results.plot(line_width=1)qImage = QtGui.QImage(img.data, img.shape[1], img.shape[0],QtGui.QImage.Format_RGB888) # 變成QImage形式if self.stopFlag == False:self.label_treated.setPixmap(QtGui.QPixmap.fromImage(qImage)) # 往顯示Label里 顯示QImagetime.sleep(0.5)def stop(self, ):self.stopFlag = True # 讓 frameAnalyzeThreadFunc 不要再設置 label_treatedself.timer_camera.stop() # 關閉定時器self.timer_videoFile.stop() # 關閉定時器if self.cap:self.cap.release() # 釋放視頻流# 清空視頻顯示區域self.label_ori_video.clear()self.label_treated.clear()# # 延時500ms清除,有的定時器處理任務可能會在當前時間點后處理完最后一幀# QtCore.QTimer.singleShot(500, clearLabels)def startVideoFile(self):# 先關閉原來打開的self.stop()videoPath, _ = QtWidgets.QFileDialog.getOpenFileName(self, # 父窗口對象"選擇視頻文件", # 標題".", # 起始目錄"圖片類型 (*.mp4 *.avi)" # 選擇類型過濾項,過濾內容在括號中)print('videoPath is', videoPath)if not videoPath:returnself.cap = cv.VideoCapture(videoPath)if not self.cap.isOpened():print("打開文件失敗")returnself.timer_videoFile.start(30)self.stopFlag = Falseprint("ok")def show_videoFile(self):# 選取視頻幀位置,self.cap.set(cv.CAP_PROP_POS_FRAMES, self.vframeIdx)self.vframeIdx += 1ret, frame = self.cap.read() # 從視頻流中讀取# 讀取失敗,應該是視頻播放結束了if not ret:self.stop()returnself.setFrameToOriLabel(frame)app = QtWidgets.QApplication()
window = MWindow()
window.show()
app.exec()