最近更新于 2023-06-09 00:28

前言

目前 WSL2 内核中还没有 USB 摄像头驱动(笔记本电脑自带的摄像头一般也是 USB 接入),在做相关开发的时候没法直接获取摄像头的数据流,不是很方便,不过也在完善,现在都能支持 CUDA 了,VMware 虚拟机目前是没法借助显卡加速的,这一点非常的具备优势。除此之外相比于虚拟机额外消耗的硬件资源更少,在早些版本支持图形窗口程序渲染还得自己配置,现在是直接就能运行图形窗口,也是很大的改善了。
针对摄像头数据流获取的问题,可以借助 ffmpeg 解决,在 Windows 中使用 ffmpeg 读取摄像头然后以 UDP(实时性好,TCP 的机制丢包了会重新发送,像实时聊天视频一般就是采用 UDP 传输)协议发送给 WSL,WSL 内部的程序读取就行。

环境

主机:

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

上面的是笔记本电脑自带的,下面的是我外接的
file

然后主机中使用 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()

file