標(biāo)檢測(cè)是在圖片或視頻中定位物體的過(guò)程。其中一個(gè)著名的目標(biāo)檢測(cè)框架是YOLO(You Only Look Once)。在某些情況下,我們不僅需要定位圖片或視頻中的物體,還需要了解每個(gè)物體的運(yùn)動(dòng),就像在這篇文章中,我們想要計(jì)數(shù)通過(guò)某些位置的物體。這就是我們需要不僅僅是檢測(cè)的地方,我們需要稱(chēng)為目標(biāo)跟蹤的東西的地方。
此外,大多數(shù)情況下,我們通常只是通過(guò)執(zhí)行腳本或命令行中的代碼來(lái)使用它,如果我們可以將我們的模型部署為GUI或應(yīng)用程序,以便用戶(hù)更輕松地使用它,那將更好。在這篇文章中,將分享如何使用框架YOLOv8和PySimpleGUI構(gòu)建一個(gè)目標(biāo)計(jì)數(shù)GUI。
什么是YOLOv8?
YOLOv8,即You Only Look Once version 8,是由UItralytics開(kāi)發(fā)的圖像處理框架,YOLOv8可以執(zhí)行目標(biāo)檢測(cè)和跟蹤、實(shí)例分割、圖像分類(lèi)和姿態(tài)估計(jì)任務(wù)。
YOLOv8的用法
YOLOv8與先前版本的性能比較
使用YOLOv8進(jìn)行目標(biāo)跟蹤
有很多方法可以使用YOLOv8進(jìn)行目標(biāo)跟蹤。我喜歡Python腳本方法,因?yàn)槲铱梢杂懈嗟目刂茩?quán),使用此方法需要執(zhí)行以下幾個(gè)步驟,您還可以從Ultralytics的文檔中查看此鏈接。
1. 創(chuàng)建虛擬環(huán)境
python -m venv yologui
2. 激活虛擬環(huán)境
yologuiScriptsactivate
3. 安裝YOLOv8的依賴(lài)項(xiàng)
pip install -r https://raw.githubusercontent.com/ultralytics/ultralytics/main/requirements.txt
4. 安裝YOLOv8
pip install ultralytics
5. 創(chuàng)建一個(gè)yolo腳本
# https://docs.ultralytics.com/modes/track/#python-examples import cv2 from ultralytics import YOLO # Load the YOLOv8 model model = YOLO('yolov8n.pt') # Open the camera cap = cv2.VideoCapture(0) # Loop through the video frames while cap.isOpened(): # Read a frame from the video success, frame = cap.read() if success: # Run YOLOv8 tracking on the frame, persisting tracks between frames results = model.track(frame, persist=True) # Visualize the results on the frame annotated_frame = results[0].plot() # Display the annotated frame cv2.imshow("YOLOv8 Tracking", annotated_frame) # Break the loop if 'q' is pressed if cv2.waitKey(1) & 0xFF == ord("q"): break else: # Break the loop if the end of the video is reached break # Release the video capture object and close the display window cap.release() cv2.destroyAllWindows()
執(zhí)行腳本,您應(yīng)該可以得到由YOLOv8進(jìn)行的目標(biāo)跟蹤:
python yolo.py
這是結(jié)果,當(dāng)滿(mǎn)意時(shí)按“Q”退出。
目標(biāo)追蹤結(jié)果
您可以看到我們的腳本可以記住左側(cè)圖片中的泰迪熊與右側(cè)圖片中的泰迪熊是相同的。實(shí)際上,他是一只狗....
添加目標(biāo)跟蹤的計(jì)數(shù)邏輯
目標(biāo)跟蹤為我們提供了比目標(biāo)檢測(cè)更多的選項(xiàng),其中之一是我們可以使用它來(lái)計(jì)算進(jìn)入或離開(kāi)框架中某個(gè)區(qū)域或線(xiàn)的獨(dú)特目標(biāo)的數(shù)量。
跟蹤物體A和B的運(yùn)動(dòng)
要計(jì)算通過(guò)我們的線(xiàn)左右經(jīng)過(guò)的物體數(shù)量,我們需要從我們的目標(biāo)跟蹤腳本中提取目標(biāo)的id和位置。Ultralytics的模型已經(jīng)為我們提供了該屬性,通過(guò)使用以下命令來(lái)處理跟蹤結(jié)果。
# Using Model results= model.track(frame, persist=True) # Extrack result result = results[0].cpu().boxes detect_id = result.id.tolist() if result.id != None else [] detect_xyxy = result.xyxy.tolist() if result.xyxy != None else [] frame_counting_buffer = dict(zip(detect_id, detect_xyxy))
因此,我們可以獲取每個(gè)目標(biāo)的位置,接下來(lái)是進(jìn)行一些計(jì)算,以了解目標(biāo)是從右到左還是從左到右經(jīng)過(guò)。在這種情況下,我只關(guān)注目標(biāo)的中心和X軸。以下是在X軸上進(jìn)行目標(biāo)計(jì)數(shù)的完整腳本。
# https://docs.ultralytics.com/modes/track/#python-examples import cv2 from ultralytics import YOLO # Load the YOLOv8 model model = YOLO('yolov8n.pt') # Counting config line_position = 50 text_size = 30 text_x_position = 50 text_y_position = 0 # Open the camera cap = cv2.VideoCapture(0) # Get Camera Parameter width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # Counting prep x_line= line_position*width/100 pt1 = (int(x_line), 0) pt2 = (int(x_line), int(height)) counting_buffer = {} counting_result = {'left-to-right' : 0, 'right-to-left' : 0} # Loop through the video frames while cap.isOpened(): # Read a frame from the video success, frame = cap.read() if success: # Run YOLOv8 tracking on the frame, persisting tracks between frames results = model.track(frame, persist=True, verbose=False) # Visualize the results on the frame annotated_frame = results[0].plot() # Get Data for counting result = results[0].cpu().boxes detect_id = result.id.tolist() if result.id != None else [] detect_xyxy = result.xyxy.tolist() if result.xyxy != None else [] frame_counting_buffer = dict(zip(detect_id, detect_xyxy)) # Process for i in frame_counting_buffer : # Prep count buffer counting_buffer[i] = counting_buffer.get(i,[]) if len(counting_buffer[i]) >= 2 : counting_buffer[i] = counting_buffer[i][-1:] # Append avg x axis to buffer avg_x = (frame_counting_buffer[i][0] + frame_counting_buffer[i][2])/2 counting_buffer[i].append(avg_x) # Count logic if len(counting_buffer[i]) >= 2 : if (counting_buffer[i][0] > x_line) & (counting_buffer[i][1] < x_line) : counting_result['right-to-left'] += 1 elif (counting_buffer[i][0] < x_line) & (counting_buffer[i][1] > x_line) : counting_result['left-to-right'] += 1 # Create Line cv2.line(annotated_frame, pt1= pt1, pt2= pt2 , color= (0,0,255), thickness= 2) # Put Counting to picture text_position = text_y_position for i in counting_result : text_position += text_size info_text = f"{i} : {counting_result[i]}" annotated_frame = cv2.putText(annotated_frame , info_text , (int(width*text_x_position/100), text_position) , cv2.FONT_HERSHEY_SIMPLEX , 1, (0,0,255), 1, cv2.LINE_AA) # Display the annotated frame cv2.imshow("YOLOv8 Tracking", annotated_frame) # Break the loop if 'q' is pressed if cv2.waitKey(1) & 0xFF == ord("q"): break else: # Break the loop if the end of the video is reached break # Release the video capture object and close the display window cap.release() cv2.destroyAllWindows()
然后,我們將得到一個(gè)如圖所示的目標(biāo)計(jì)數(shù)腳本,當(dāng)滿(mǎn)意時(shí)按Q。
什么是PySimpleGUI?
PySimpleGUI是一個(gè)用于制作GUI的Python庫(kù),具有跨平臺(tái)性且非常簡(jiǎn)單易用。
從PySimpleGUI的頁(yè)面獲取圖片
GUI的框架
創(chuàng)建GUI時(shí),有一些比編碼更重要的東西,即設(shè)計(jì)階段。我們?cè)诰幋a之前應(yīng)該有一些草圖設(shè)計(jì)。在這種情況下,我畫(huà)了一個(gè)目標(biāo)計(jì)數(shù)GUI的初步設(shè)計(jì),就像這張圖片一樣。
GUI初步設(shè)計(jì)
設(shè)計(jì)階段后,接下來(lái)就是編碼:
1. 安裝PySimpleGUI。
pip install pysimplegui
2. 創(chuàng)建一個(gè)GUI腳本
# https://www.pysimplegui.org/en/latest/#jump-start import PySimpleGUI as sg # Create Layouy of the GUI layout = [ [sg.Text('GUI Object Counting with Yolo V8')], [sg.Text('Enter Model Name', size= (15)), sg.InputText(key='model_name')], [sg.Text('X-line for Counting', size= (15)), sg.InputText(key= 'line_position')], [sg.Button('Run'), sg.Button('Stop'), sg.Button('Close')], [sg.Text('PICTURE')], [sg.Text('Left-to-Right', size= (15), key='out1'), sg.Text("0", key='out1-v')], [sg.Text('Right-to-Left', size= (15), key='out2'), sg.Text("0", key='out2-v')] ] # Create the Window window = sg.Window('GUIYoloV8-Counting', layout) # Event Loop to process "events" while True: event, values = window.read() # When press Run if event == 'Run' : print(values) # When close window or press Close if event in (sg.WIN_CLOSED, 'Close'): break # Close window window.close()
正如您所見(jiàn),PySimpleGUI的腳本非常簡(jiǎn)單。之后,我們所要做的就是運(yùn)行此GUI腳本。
python gui.py
之后,您應(yīng)該會(huì)得到一個(gè)像圖中這樣的簡(jiǎn)單GUI,嘗試玩耍并在滿(mǎn)意時(shí)關(guān)閉。
合并
在我們有了目標(biāo)計(jì)數(shù)和GUI框架之后,是時(shí)候?qū)⑺鼈兒喜⒌揭黄鹆恕N覀兛梢詫蓚€(gè)腳本合并成一個(gè)名為main.py的新腳本,如下所示:
# https://www.pysimplegui.org/en/latest/#jump-start import PySimpleGUI as sg import cv2 # https://docs.ultralytics.com/modes/track/#python-examples from ultralytics import YOLO # Create Layouy of the GUI layout = [ [sg.Text('GUI Object Counting with Yolo V8')], [sg.Text('Enter Model Name', size= (15)), sg.InputText(key='model_name')], [sg.Text('X-line for Counting', size= (15)), sg.InputText(key= 'line_position')], [sg.Button('Run'), sg.Button('Stop'), sg.Button('Close')], [sg.Image(filename='', key='image')], [sg.Text('Right-to-Left', size= (15), key='out1'), sg.Text("0", key='right-to-left')], [sg.Text('Left-to-Right', size= (15), key='out2'), sg.Text("0", key='left-to-right')] ] # Create the Window window = sg.Window('GUIYoloV8-Counting', layout) run_model, verbose = False, False # Event Loop to process "events" while True: event, values = window.read(timeout=0) # When press Run if event == 'Run' : # Load the YOLOv8 model model = YOLO(values['model_name']) # Counting config line_position = 50 text_size = 30 text_x_position = 50 text_y_position = 0 # Open the camera cap = cv2.VideoCapture(0) # Get Camera Parameter width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # Counting prep x_line= line_position*width/100 pt1 = (int(x_line), 0) pt2 = (int(x_line), int(height)) counting_buffer = {} counting_result = {'left-to-right' : 0, 'right-to-left' : 0} # Run Signal run_model = True # When close window or press Close elif event in ('Stop', sg.WIN_CLOSED, 'Close'): if run_model : run_model = False # Stop running cap.release() # Release video if event != sg.WIN_CLOSED : window['image'].update(filename='') # Destroy picture # When close window or press Close if event in (sg.WIN_CLOSED, 'Close'): break # Run Model if run_model : # Read a frame from the video success, frame = cap.read() if success: # Run YOLOv8 tracking on the frame, persisting tracks between frames results = model.track(frame , persist=True , verbose=False ) # Visualize the results on the frame annotated_frame = results[0].plot() # Get Data for counting result = results[0].cpu().boxes detect_id = result.id.tolist() if result.id != None else [] detect_xyxy = result.xyxy.tolist() if result.xyxy != None else [] frame_counting_buffer = dict(zip(detect_id, detect_xyxy)) # Process for i in frame_counting_buffer : # Prep count buffer counting_buffer[i] = counting_buffer.get(i,[]) if len(counting_buffer[i]) >= 2 : counting_buffer[i] = counting_buffer[i][-1:] # Append avg x axis to buffer avg_x = (frame_counting_buffer[i][0] + frame_counting_buffer[i][2])/2 counting_buffer[i].append(avg_x) # Count logic if len(counting_buffer[i]) >= 2 : if (counting_buffer[i][0] > x_line) & (counting_buffer[i][1] < x_line) : counting_result['right-to-left'] += 1 elif (counting_buffer[i][0] < x_line) & (counting_buffer[i][1] > x_line) : counting_result['left-to-right'] += 1 # Create Line cv2.line(annotated_frame, pt1= pt1, pt2= pt2 , color= (0,0,255), thickness= 2) # Put Counting to picture text_position = text_y_position for i in counting_result : text_position += text_size info_text = f"{i} : {counting_result[i]}" annotated_frame = cv2.putText( annotated_frame , info_text , (int(width*text_x_position/100) , text_position) , cv2.FONT_HERSHEY_SIMPLEX , 1 , (0,0,255) , 1 , cv2.LINE_AA) # Show Image imgbytes = cv2.imencode('.png', annotated_frame)[1].tobytes() window['image'].update(data=imgbytes) window['right-to-left'].update(str(counting_result['right-to-left'])) window['left-to-right'].update(str(counting_result['left-to-right'])) else: # Break the loop if not read cap.release() run_model = False # Close window window.close()
然后,我們可以運(yùn)行主腳本。
python main.py
然后,我們就可以得到以下圖片所示的目標(biāo)計(jì)數(shù)GUI。這一次,我將使用一個(gè)定制模型來(lái)識(shí)別我從Ultralytics HUB創(chuàng)建的Pompompurin。
初始階段
按下“RUN”后,我的新模型知道它現(xiàn)在是一只狗... 接下來(lái),為了讓我們的用戶(hù)更輕松地使用,我們可以創(chuàng)建一個(gè)包含以下代碼的“cmd”文件。
python main.py pause
現(xiàn)在,用戶(hù)可以通過(guò)打開(kāi)cmd文件來(lái)使用我們的GUI/應(yīng)用程序。
審核編輯:劉清
-
GUI
+關(guān)注
關(guān)注
3文章
662瀏覽量
39828 -
python
+關(guān)注
關(guān)注
56文章
4807瀏覽量
84959
原文標(biāo)題:使用YOLOv8構(gòu)建目標(biāo)計(jì)數(shù)GUI
文章出處:【微信號(hào):vision263com,微信公眾號(hào):新機(jī)器視覺(jué)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論