最近更新于 2024-05-05 23:08
前言
目前 WSL2 内核中还没有 USB 摄像头驱动(笔记本电脑自带的摄像头一般也是 USB 接入),在做相关开发的时候没法直接获取摄像头的数据流,不是很方便,不过也在完善,现在都能支持 CUDA 了,VMware 虚拟机目前是没法借助显卡加速的,这一点非常的具备优势。除此之外相比于虚拟机额外消耗的硬件资源更少,在早些版本支持图形窗口程序渲染还得自己配置,现在是直接就能运行图形窗口,也是很大的改善了。
针对摄像头数据流获取的问题,可以借助 ffmpeg 解决,在 Windows 中使用 ffmpeg 读取摄像头然后以 UDP(实时性好,TCP 的机制丢包了会重新发送,像实时聊天视频一般就是采用 UDP 传输)协议发送给 WSL,WSL 内部的程序读取就行。
环境
主机:
- Windows 11 22H2 专业工作站版
- ffmpeg 版本 N-110972-gbaa9fccf8d-20230601(配置参考:https://blog.iyatt.com/?p=8613 )
WSL2:
- Ubuntu 22.04
- Python 3.11.3
- OpenCV 4.7.0
示例说明
首先 WSL 中查询本机的 IP
ifconfig
主机中使用 ffmpeg 查询 USB 摄像头名称
ffmpeg -list_devices true -f dshow -i dummy
上面的是笔记本电脑自带的,下面的是我外接的
然后主机中使用 ffmpeg 发送摄像头数据流
ffmpeg -f dshow -i video="摄像头名称" -preset ultrafast -tune zerolatency -vcodec libx264 -f mpegts udp://【IP】:【Port】
比如这里我使用自带的摄像头,然后 IP 写 WSL 的,端口自己定(1024 以下,Windows 需要管理员权限运行,Linux 中需要 root 运行),我就用 5000
ffmpeg -f dshow -i video="Integrated Camera" -preset ultrafast -tune zerolatency -vcodec libx264 -f mpegts udp://172.27.119.76:5000
然后 WSL 中就读取本机对应的端口,即 udp://127.0.0.1:5000 或者 udp://localhost:5000
import cv2
address = "udp://localhost:5000"
cap = cv2.VideoCapture(address)
if not cap.isOpened():
print("未接收到数据流,请确认数据流是否发送到本机!")
cap.release()
exit()
while True:
ret, frame = cap.read()
if ret:
cv2.imshow("frame", frame)
else:
print('等待数据......')
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
WSL2 中获取摄像头数据流