1. 核心概念解析
(1) stream=True
的作用
- 生成器模式:當處理視頻或圖像序列時,
stream=True
會將結果包裝成一個 生成器(Generator),逐幀生成Results
對象,而不是一次性返回所有結果。 - 內存優化:避免同時加載全部幀的檢測結果,顯著降低內存占用(尤其對長視頻或高分辨率輸入至關重要)。
(2) Results
對象生成器
- 每次迭代返回一個
Results
對象,對應視頻的 一幀 或輸入列表中的 一個元素。 - 每個
Results
對象包含該幀的檢測信息(如boxes
、masks
等)。
2. 工作流程對比
傳統方式(stream=False
)
results = model("video.mp4") # 一次性處理所有幀
# 所有結果存儲在內存中,可能導致OOM(內存不足)
- 內存峰值高:需緩存整個視頻的檢測結果。
- 延遲高:必須等待全部處理完成才能訪問結果。
流式處理(stream=True
)
results = model("video.mp4", stream=True) # 生成器
for frame_results in results: # 逐幀處理print(frame_results.boxes) # 實時訪問當前幀結果
- 內存友好:同一時間僅處理一幀的數據。
- 實時性:邊處理邊輸出,適合實時分析或長時間視頻。
3. 典型使用場景
(1) 視頻處理
cap = cv2.VideoCapture("input.mp4")
out = cv2.VideoWriter("output.mp4", cv2.VideoWriter_fourcc(*'mp4v'), 30, (640, 480))# 流式推理
results = model("input.mp4", stream=True)
for frame_results in results:annotated_frame = frame_results.plot() # 繪制檢測框out.write(annotated_frame) # 寫入輸出視頻
- 優勢:避免因視頻過長導致內存爆炸。
- 值得注意,(輸出視頻只有1KB)通常是由于 視頻編解碼器配置問題 或 幀尺寸不匹配 導致的。以下是修正后的完整代碼,解決寫入視頻無效的問題:
import cv2
from ultralytics import YOLO# 初始化模型
model = YOLO("../models/yolo11n.pt") # pretrained YOLO11n model# 輸入視頻路徑
input_video = "../videos/test.mp4"# 讀取輸入視頻獲取幀尺寸和FPS
cap = cv2.VideoCapture(input_video)
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
cap.release()# 定義視頻寫入器(關鍵修正點)
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 或改用 'avc1' 兼容H.264
out = cv2.VideoWriter("output.mp4",fourcc,fps,(width, height) # 必須與原始視頻尺寸一致!
)# 流式推理
results = model(input_video, stream=True, imgsz=640) # imgsz可調整for frame_results in results:# 獲取帶標注的幀(BGR格式)annotated_frame = frame_results.plot() # 自動返回numpy數組 (H,W,3)# 確保幀尺寸與寫入器匹配(額外安全檢查)if (annotated_frame.shape[1], annotated_frame.shape[0]) != (width, height):annotated_frame = cv2.resize(annotated_frame, (width, height))# 寫入幀out.write(annotated_frame)# 釋放資源
out.release()
print(f"視頻已保存至 output.mp4,尺寸: {width}x{height}, FPS: {fps}")
(2) 實時攝像頭流
results = model(0, stream=True) # 攝像頭ID=0
for frame_results in results:cv2.imshow("Live", frame_results.plot())if cv2.waitKey(1) == ord('q'): # 按Q退出break
- 優勢:低延遲,適合實時監控。
4. 內存優化原理
處理方式 | 內存占用曲線 | 特點 |
---|---|---|
stream=False | ![]() | 內存隨幀數線性增長 |
stream=True | ![]() | 內存恒定(僅緩存當前幀) |
5. 注意事項
-
性能權衡:
- 優點:節省內存,適合資源受限環境。
- 缺點:總處理時間可能略長(因無法并行處理所有幀)。
-
不可逆迭代:
results = model(source, stream=True) list(results) # 第一次迭代后生成器耗盡,再次遍歷需重新推理
-
與多線程結合:
from concurrent.futures import ThreadPoolExecutordef process_frame(frame_results):return frame_results.plot()with ThreadPoolExecutor() as executor:annotated_frames = list(executor.map(process_frame, results))
6. 類比解釋
- 傳統方式:像一次性下載整部電影再看 → 占用硬盤空間大。
- 流式處理:像在線邊緩沖邊播放 → 內存占用穩定。
通過 stream=True
,YOLOv8 實現了 高效流水線處理,尤其適合嵌入式設備或大規模視頻分析場景。