7

I am trying to access my webcam through OpenCV in WSL2 (Ubuntu). I found this blog post where it explains how to connect USB devices to WSL2. Running usbipd wsl list in windows command prompt lists the following devices:

> usbipd wsl list
BUSID  VID:PID    DEVICE                                                        STATE
1-1    0c45:6725  Integrated Webcam                                             Not attached
1-2    046d:c534  USB Input Device                                              Not attached
1-3    0cf3:e007  Qualcomm QCA61x4A Bluetooth                                   Not attached
1-4    27c6:639c  Goodix Moc Fingerprint                                        Not attached
2-2    8564:7000  USB Mass Storage Device                                       Not attached

Here my machine's integrated webcam is a USB device with BUSID 1-1. I ran usbipd wsl attach --busid 1-1 to connect my integrated webcam to WSL.

Now from WSL, typing lsusb lists the devices as follows:

> lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 0c45:6725 Microdia Integrated_Webcam_HD
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

It looks like the integrated webcam has been successfully connected to WSL (listed as Microdia Integrated_Webcam_HD).

This is the code used to access the webcam:

import cv2
import sys

source = cv2.VideoCapture(0)

win_name = 'Camera Preview' cv2.namedWindow(win_name, cv2.WINDOW_NORMAL)

while cv2.waitKey(1) != 27: # Escape has_frame, frame = source.read() if not has_frame: break cv2.imshow(win_name, frame)

source.release() cv2.destroyWindow(win_name)

Here cv2.VideoCapture() takes an index as argument. The OpenCV documentation mentions: doc

If I run the code above with 0 as the argument, I get the following output:

[ WARN:0@0.216] global /io/opencv/modules/videoio/src/cap_v4l.cpp (889) open VIDEOIO(V4L2:/dev/video0): can't open camera by index

I have connected USB devices to WSL, but still I am not able to access the integrated webcam. Any ideas how to get around this problem would be much appreciated!

Terrarium
  • 345

3 Answers3

5

TL;DL: I was with the same problem, this GitHub that someone mentioned on the comments worked for me:

https://github.com/PINTO0309/wsl2_linux_kernel_usbcam_enable_conf


I spent the whole day trying a lot of workarounds, but this was the only thing that worked for me.

I knew beforehand that it was some WSL Kernel related problem because the webcam worked just fine on an Ubuntu 22.04 virtual machine running on Virtual Box.

On the GitHub page it's not specified, but you will need fist:

1 - Install usbipd-win

You can follow all the steps for this here: https://github.com/dorssel/usbipd-win/wiki/WSL-support

After you'd manage to attach your device to the WSL, AND IT SHOWS with the lsusb command, you can follow their tutorial.

2 - Follow the steps described in this repository

https://github.com/PINTO0309/wsl2_linux_kernel_usbcam_enable_conf

All that they describe here you could do it by yourself following the usbipd installation to the end, but the big difference is that they already pre-configured a .config file to compile the kernel just for the webcam to work. (And it worked for me like magic)


I'm on Windows 11 Pro Build 22621 and my webcam is a integrated one, compatible with uvcvideo, I will post the full specs here:

$ v4l2-ctl -d /dev/video0 --all

Driver Info: Driver name : uvcvideo Card type : Integrated_Webcam_HD: Integrate Bus info : usb-vhci_hcd.0-1 Driver version : 5.15.90 Capabilities : 0x84a00001 Video Capture Metadata Capture Streaming Extended Pix Format Device Capabilities Device Caps : 0x04200001 Video Capture Streaming Extended Pix Format Priority: 2 Video input : 0 (Camera 1: ok) Format Video Capture: Width/Height : 640/480 Pixel Format : 'MJPG' (Motion-JPEG) Field : None Bytes per Line : 0 Size Image : 614989 Colorspace : Default Transfer Function : Default (maps to Rec. 709) YCbCr/HSV Encoding: Default (maps to ITU-R 601) Quantization : Default (maps to Full Range) Flags : Crop Capability Video Capture: Bounds : Left 0, Top 0, Width 640, Height 480 Default : Left 0, Top 0, Width 640, Height 480 Pixel Aspect: 1/1 Selection Video Capture: crop_default, Left 0, Top 0, Width 640, Height 480, Flags: Selection Video Capture: crop_bounds, Left 0, Top 0, Width 640, Height 480, Flags: Streaming Parameters Video Capture: Capabilities : timeperframe Frames per second: 30.000 (30/1) Read buffers : 0 brightness 0x00980900 (int) : min=-64 max=64 step=1 default=0 value=0 contrast 0x00980901 (int) : min=0 max=95 step=1 default=0 value=0 saturation 0x00980902 (int) : min=0 max=100 step=1 default=64 value=64 hue 0x00980903 (int) : min=-2000 max=2000 step=1 default=0 value=0 white_balance_temperature_auto 0x0098090c (bool) : default=1 value=1 gamma 0x00980910 (int) : min=100 max=300 step=1 default=100 value=100 gain 0x00980913 (int) : min=1 max=8 step=1 default=1 value=1 power_line_frequency 0x00980918 (menu) : min=0 max=2 default=2 value=1 (50 Hz) 0: Disabled 1: 50 Hz 2: 60 Hz white_balance_temperature 0x0098091a (int) : min=2800 max=6500 step=1 default=4600 value=4600 flags=inactive sharpness 0x0098091b (int) : min=1 max=7 step=1 default=2 value=2 backlight_compensation 0x0098091c (int) : min=0 max=3 step=1 default=3 value=3 exposure_auto 0x009a0901 (menu) : min=0 max=3 default=3 value=3 (Aperture Priority Mode) 1: Manual Mode 3: Aperture Priority Mode exposure_absolute 0x009a0902 (int) : min=9 max=625 step=1 default=157 value=157 flags=inactive exposure_auto_priority 0x009a0903 (bool) : default=0 value=0

And here is a screenshot of my camera working (I put my finger in front of it, of course, but the image is just fine) camera working with the github tutorial script from PINTO0309

Marcio
  • 66
3

The answer above works. However, the configurations in the GitHub repo are only available for several WSL versions. What if we want to compile other WSL versions, such as the latest one?

Here, I give the common method to build a WSL kernel with USB and integrated camera drivers. The version I tested is the latest version- linux-msft-wsl-6.6.36.6, but it should be available for most versions with minor differences.

I have tested this solution with the integrated camera on my PC.

I compile the WSL source code in WSL2 (Ubuntu 22.04)

1) Compile the WSL kernel with any version

Step1: Install the dependencies

# update package source
sudo apt update && sudo apt upgrade

install dependencies according to the README file in the source code

sudo apt install build-essential flex bison dwarves libssl-dev libelf-dev cpio

install dependencies for configuration, according to my experience

sudo apt install libncurses-dev

Step2: Get the source code. You can clone the repo, or download it from the release page

  • Remember to put them into a Linux system (I put them into WSL2)
# enter a directory
cd ~

clone the repo, for example, the tag "linux-msft-wsl-6.6.36.6"

git clone --depth 1 -b linux-msft-wsl-6.6.36.6 https://github.com/microsoft/WSL2-Linux-Kernel.git

enter the source directory

cd WSL2-Linux-Kernel

Step3. Config the WSL kernel with the command: make menuconfig KCONFIG_CONFIG=Microsoft/config-wsl

Then we can see a terminal GUI for configuration

  • General setup - Local version: add a suffix -usb-add for later version check (you can add your own suffix)
  • Device Drivers-Multimedia support: change it to * status (press space key), and then enter its config (press enter key)
    • change Filter media drivers,Autoselect ancillary drivers (tuners, sensors, i2c, spi, frontends) to * status
    • change Media device types - Cameras and video grabbers to * status
    • change Media drivers - Media USB Adapters to * status, and then enter its config
      • change GSPCA based webcams and USB Video Class (UVC) to "M" status
      • enter GSPCA based webcams, change all USB camera drivers to M , because we don't know our camera mode type
  • change Device Drivers-USB support to * status, and then enter its config
    • change Support for Host-side USB to * status
    • change USB/IP support to * status, and then change all its subitems to * status

Then, save them,and then exit with Save and Exit at the bottom

Step4: Build the kernel and install the modules

# compile the kernel
make KCONFIG_CONFIG=Microsoft/config-wsl -j$(nproc)

compile all the modules according to the config file

sudo make KCONFIG_CONFIG=Microsoft/config-wsl modules -j$(nproc)

install all the modules according to the config file

sudo make KCONFIG_CONFIG=Microsoft/config-wsl modules_install -j$(nproc)

Then, you will get the WSL kernel (./vmlinux);

The modules are installed into the current system (/lib/modules/6.6.36.6-microsoft-standard-WSL2-usb-add+).

  • Here, the current system is the current WSL subsystem (Distro).
  • The modules are the parts that are marked M status in the configuration (Step 3)
  • If the current subsystem (suppose it Ubuntu-ROS) is removed (unregistered), the modules (it contains USB camera drivers) will disappear, and other subsystems will also lose the modules; If WSL is restarted, you have to start the subsystem (Ubuntu-ROS) once to add the modules into WSL.
  • I don't think you want to compile it again for the same issue. Backing up the WSL Distro is a solution. But, backing up the module folder is a better solution (See Section 4).

2) Replace the kernel with the default one

Now, you can copy the kernel into your Windows path and add the path to the WSL config file

  • Step1: copy your kernel into your Windows path: sudo cp ./vmlinux /mnt/c/WSL/kernel/
  • Step2: add the path into the C:/Users/{your user name}/.wslconfig (if this file doesn't exist, create a new one)
[wsl2]
kernel=C:\\WSL\\kernel\\vmlinux
  • Step3: shutdown the WSL: wsl --shutdown
  • Step4: enter the WSL and check the version: uname -a

If you see the suffix (-usb-add), it means you have succeeded. The WSL kernel should support USB, and integrated camera now.

3) Camera Test

If you want to use cameras, you should share the camera with WSL.

Firstly, you need to install usbipd-win

Secondly, run the commands below on your Windows with Powershell.

# list all USB devices
usbipd list

share your camera, suppose its BUSID is "1-6"

usbipd bind --busid 1-6 # this needs administration permission

attach to WSL

usbipd attach --wsl --busid 1-6

Thirdly, enter WSL and run the commands below

ls /dev/video*

If you see any video devices with the command above, it means you have succeeded. Now, you can use the camera with OpenCV in WSL.

4) Backup your effort

Compiling the kernel and modules is complicated and time-consuming (1 hour +). So, backing up the result is important.

Firstly, save the WSL kernel (vmlinux file).

Secondly, back up the modules.

# package the modules folder to a .tar.gz file
tar -zcvf ~/module.tar.gz /lib/modules/6.6.36.6-microsoft-standard-WSL2-usb-add+/

How to restore the modules?

Release the file modules.tar.gz to any WSL subsystem (Distro). After you shut down WSL, enter WSL again. The modules will be loaded into WSL automatically.

BConic
  • 103
1

I had built a custom Linux kernel by running the install.sh script in the https://github.com/randomwons/WSL2-USB-Camera.git repository. After replacing the default Linux kernel of WSL2 with the custom Linux kernel, I was able to play video from my computer's USB camera in a WSL2 Ubuntu 22.04 instance using ffplay after attaching the USB web camera to the WSL2 Ubuntu 22.04 instance using usbipd. The /dev/video0 device does exist in the WSL2 Ubuntu 22.04 machine. However, when I run the following Python code, I can't get a single frame from the camera:

user@PC:~/OpenCV-Cam$ python3
Python 3.10.12 (main, Nov  6 2024, 20:22:13) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cap = cv2.VideoCapture(0)
>>> ret, frame = cap.read()
[ WARN:0@21.942] global cap_v4l.cpp:1136 tryIoctl VIDEOIO(V4L2:/dev/video0): select() timeout.
>>> ret
False
>>> frame
>>> cap.release()
>>>

Here's information about the USB camera that I got from the Ubuntu 22.04 instance:

user@PC:~/OpenCV-Cam$ v4l2-ctl -d /dev/video0 --all
Driver Info:
        Driver name      : uvcvideo
        Card type        : HP Wide Vision HD Camera: HP Wi
        Bus info         : usb-vhci_hcd.0-1
        Driver version   : 5.15.167
        Capabilities     : 0x84a00001
                Video Capture
                Metadata Capture
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps      : 0x04200001
                Video Capture
                Streaming
                Extended Pix Format
Media Driver Info:
        Driver name      : uvcvideo
        Model            : HP Wide Vision HD Camera: HP Wi
        Serial           :
        Bus info         : usb-vhci_hcd.0-1
        Media version    : 5.15.167
        Hardware revision: 0x00000004 (4)
        Driver version   : 5.15.167
Interface Info:
        ID               : 0x03000002
        Type             : V4L Video
Entity Info:
        ID               : 0x00000001 (1)
        Name             : HP Wide Vision HD Camera: HP Wi
        Function         : V4L2 I/O
        Flags            : default
        Pad 0x01000007   : 0: Sink
          Link 0x02000013: from remote pad 0x100000a of entity 'Extension 4' (Video Pixel Formatter): Data, Enabled, Immutable
Priority: 2
Video input : 0 (Input 1: ok)
Format Video Capture:
        Width/Height      : 640/360
        Pixel Format      : 'MJPG' (Motion-JPEG)
        Field             : None
        Bytes per Line    : 0
        Size Image        : 460800
        Colorspace        : sRGB
        Transfer Function : Rec. 709
        YCbCr/HSV Encoding: ITU-R 601
        Quantization      : Default (maps to Full Range)
        Flags             :
Crop Capability Video Capture:
        Bounds      : Left 0, Top 0, Width 640, Height 360
        Default     : Left 0, Top 0, Width 640, Height 360
        Pixel Aspect: 1/1
Selection Video Capture: crop_default, Left 0, Top 0, Width 640, Height 360, Flags:
Selection Video Capture: crop_bounds, Left 0, Top 0, Width 640, Height 360, Flags:
Streaming Parameters Video Capture:
        Capabilities     : timeperframe
        Frames per second: 30.000 (30/1)
        Read buffers     : 0

User Controls

                 brightness 0x00980900 (int)    : min=0 max=255 step=1 default=128 value=128
                   contrast 0x00980901 (int)    : min=0 max=255 step=1 default=32 value=32
                 saturation 0x00980902 (int)    : min=0 max=100 step=1 default=64 value=64
                        hue 0x00980903 (int)    : min=-180 max=180 step=1 default=0 value=0
    white_balance_automatic 0x0098090c (bool)   : default=1 value=1
                      gamma 0x00980910 (int)    : min=90 max=150 step=1 default=120 value=120
                       gain 0x00980913 (int)    : min=4 max=8 step=1 default=4 value=4
       power_line_frequency 0x00980918 (menu)   : min=0 max=2 default=2 value=2 (60 Hz)
                            0: Disabled
                            1: 50 Hz
                            2: 60 Hz
  white_balance_temperature 0x0098091a (int)    : min=2800 max=6500 step=1 default=4000 value=4000 flags=inactive
                  sharpness 0x0098091b (int)    : min=0 max=7 step=1 default=2 value=2
     backlight_compensation 0x0098091c (int)    : min=0 max=2 step=1 default=0 value=0

Camera Controls

              auto_exposure 0x009a0901 (menu)   : min=0 max=3 default=3 value=3 (Aperture Priority Mode)
                            1: Manual Mode
                            3: Aperture Priority Mode
     exposure_time_absolute 0x009a0902 (int)    : min=10 max=2500 step=1 default=156 value=156 flags=inactive
 exposure_dynamic_framerate 0x009a0903 (bool)   : default=0 value=1