靈芯派的 V4L2 驅動根本不會因為“設置 320×200”去重啓傳感器或重新協商媒體類型,它只在驅動層做裁剪/縮放,所以零額外耗時;Windows 的 Direc
一、V4L2 為什麼敢“秒切”
- 攝像頭硬件本身只輸出 固定幾種分辨率(比如 1920×1080 MJPEG、640×480 YUYV …)。
- 靈芯派內核驅動(bcm2835-v4l2 / sunxi-v4l2)在
open()時就已經讓傳感器跑在 某一種原生模式(通常是 1920×1080 MJPEG)。 - 當你
cap.set(CAP_PROP_FRAME_WIDTH, 320)時,V4L2 只做兩件事:
- 在 VIDIOC_S_FMT 裏把返回的 width/height 字段改成 320×200;
- 後續每次
read()到達時,驅動 現場做裁剪或縮小,再把數據拷貝到用户空間。
傳感器時鐘一次都沒停,所以感覺不到延遲。
二、Windows DirectShow 為什麼“必卡”
- DirectShow 的 Capture Pin 在 graph 運行後 不允許動態改格式;
- 你一旦
set(320, 200),Filter Graph Manager 必須:
- 停止整個 graph → 釋放 Pin → 重新協商 AM_MEDIA_TYPE → 重新 connect → 再 run;
- 這一步要 重新打開內核流接口,USB 攝像頭固件會收到 SET_CUR 請求,很多芯片會 掉電-上電 切換輸出,物理重啓流 3-4 s 就這樣來的。
- 靈芯派(V4L2)
- 驅動確實很少重啓傳感器,你設任意分辨率都當成「用户想要的後處理尺寸」——實時裁剪/縮放,成本就是 CPU(或 NEON/VPU)算力。
- 例外:如果你設置的尺寸正好等於驅動列表裏的某個原生模式,部分驅動會「順水推舟」把傳感器切過去,這時 CPU 開銷為零,但切換本身仍比 Windows 快得多(內核級,無 Pin 重建)。
- Windows
- DirectShow / MediaFoundation 的框架規定:Pin 一旦運行就不能改格式,所以「前期固定」與「後期 CPU 裁」是二選一——
- 想省 CPU → 提前選好原生分辨率,接受 3-4 s 重啓;
- 想秒開 → 原生分辨率+軟件 resize,代價是持續佔用 CPU/GPU 算力。
- 因此只有 Windows 才需要糾結「啓動慢 vs 運行慢」的權衡。
總結一句話:
靈芯派永遠可以「後期軟件裁」而幾乎不額外耗時;Windows 下如果你不想等 3-8 s,就必須接受後期 CPU 裁。
import cv2, time
def fast_open():
start = time.time()
# 1) 原生打開
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # 減少內部緩衝
# 2) 立即讀一幀
ret, frame = cap.read()
open_time = time.time()
print(f"原生打開+首幀: {open_time - start:.3f}s shape={frame.shape}")
# 3) 軟件縮到目標尺寸
small = cv2.resize(frame, (320, 200))
resize_time = time.time()
print(f"軟件縮放耗時: {resize_time - open_time:.3f}s")
cv2.imshow("small", small)
cv2.waitKey(0)
cap.release()
if __name__ == "__main__":
fast_open()