Windows 10 の WSL2 上 の Ubuntu 20.04 で Webカメラ を操作する
WSL上のUbuntuでUSBカメラをいじろうと思ったら思いのほか大変だったのでメモを記す。
なお、ここまでやっても最終的には大きな解像度だとタイムアウトが発生し、画像の取得ができなかった。
(160x120とかの小さな解像度はOKだったが)
しかも、WSLじゃない、ふつうのWindows上でUSBカメラが認識されなくなった。
WSL上でUSBカメラを使おうとするのは当面やめたほうが良いかもしれん。
手順
①Windows UpdateをしてWindows 10を最新の状態にする
②Windows PowerShellを管理者権限で起動し、wsl --installを実行する
③謎の呪文を唱える
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
④もう一回謎の呪文を唱える
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all
すると再起動が促されるので再起動する。
⑤再度、管理者権限で Windows PowerShell を起動し、以下を実行する
wsl --set-default-version 2
⑥wslをアップデートして最新にしておく(不要かもしれない)
wsl --update
なお、更新されたかは wsl --status
で確認できる
⑦Microsoft Storeを起動し、検索窓からUbuntu 20.04を探し、インストールする
インストール後、起動すると新ユーザーの作成を促されるので、ユーザー名とパスワードを入力する。
とりあえず、
$ sudo apt update
$ sudo apt upgrade -y
⑧Windows PCにXmingをインストールする
https://sourceforge.net/projects/xming/ から Xmingをインストール。
XmingはXサーバーで、これがないとUbuntu側からWindows側にGUIを表示させることができない。
注意点としてはXmingの起動引数に -ac を入れないといけないという点。
Xmingのショートカットのプロパティを開き、以下のようにリンク先に -ac を追加する。
"C:\Program Files (x86)\Xming\Xming.exe" :0 -clipboard -multiwindow
→
"C:\Program Files (x86)\Xming\Xming.exe" :0 -clipboard -multiwindow -ac
⑨Ubuntuにubuntu-desktopをインストールする
(もしかしたら不要かもしれない)
$ sudo apt install -y ubuntu-desktop
⑩UbuntuにDISPLAY変数を設定する
以下を実行する。毎回実行するのは面倒なので、.bashrcにでも書いておく。
$ export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0.0
$ export DISPLAY=localhost:0.0
⑪windowsにusbipを入れる
https://github.com/dorssel/usbipd-win/releases/tag/v2.2.0
から、usbipd-win_2.2.0.msiをダウンロードしてインストールする。
⑫Windows PowerShellを管理者権限で起動しusbipdが動くことを確認
usbipd list
⑬Linuxでusbipを使えるようにする
以下のコマンドを実行
$ sudo apt install -y linux-tools-5.4.0-77-generic hwdata
(secure_pathの先頭に/usr/lib/linux-tools/5.4.0-77-generic:を追加)
$ sudo visudo
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
→
Defaults secure_path="/usr/lib/linux-tools/5.4.0-77-generic:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
usbipが2.x以降になってからPowerShellで下記エラーがでるようになったので、
usbipd: error: WSL 'usbip' client not correctly installed. See https://github.com/dorssel/usbipd-win/wiki/WSL-support for the latest instructions.
$ sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/5.4.0-77-generic/usbip 20
⑭管理者権限でPowerShellを起動し、usbデバイスをアタッチする
PowerShellで以下を実行し、USBカメラのデバイス番号を取得する。
C:\Windows\system32> usbipd list
Connected:
BUSID DEVICE STATE
1-3 ASIX AX88179A USB 3.2 Gen1 to Gigabit Ethernet Adapter Not shared
2-6 HD Camera, IR Camera Not shared
2-8 Synaptics WBDI Fingerprint Reader - USB 086 Not shared
2-10 インテル(R) ワイヤレス Bluetooth(R) Not shared
3-1 FULL HD webcam, USB Microphone Not shared
3-3 USB 入力デバイス Not shared
Persisted:
GUID DEVICE
497875c2-a7d8-4228-8b4c-11ecdaccdbea FULL HD webcam, USB Microphone
上記だと、3-1がUSBカメラ。
で、これをUbuntuにアタッチする
PS C:\Windows\system32> usbipd wsl attach --busid=3-1
PS C:\Windows\system32>
これでアタッチされた。何もメッセージがでないけど。
listを見たら変わっていることがわかる。
PS C:\Windows\system32> usbipd list
Connected:
BUSID DEVICE STATE
1-3 ASIX AX88179A USB 3.2 Gen1 to Gigabit Ethernet Adapter Not shared
2-6 HD Camera, IR Camera Not shared
2-8 Synaptics WBDI Fingerprint Reader - USB 086 Not shared
2-10 インテル(R) ワイヤレス Bluetooth(R) Not shared
3-1 FULL HD webcam, USB Microphone Attached
3-3 USB 入力デバイス Not shared
Persisted:
GUID DEVICE
Ubuntu上でも見えるようになっている。lsusbで確認すると、
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 007: ID 1bcf:2283 Sunplus Innovation Technology Inc. FULL HD webcam
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
が、これで本来なら使えるはずなのだが、/dev/video0と/dev/video1がでてこない。
対応するために、カーネルをコンパイルしなければならなかった。
⑪WSLのカーネルをコンパイルする
Ubuntu上で以下を実行する。
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool zip unzip v4l-utils libssl-dev python3-pip cmake git iputils-ping net-tools
$ cd /usr/src
$ TAGVERNUM=5.10.74.3
$ TAGVER=linux-msft-wsl-${TAGVERNUM}
$ sudo git clone -b ${TAGVER} https://github.com/microsoft/WSL2-Linux-Kernel.git ${TAGVERNUM}-microsoft-standard
$ cd ${TAGVERNUM}-microsoft-standard
$ sudo cp /proc/config.gz config.gz
$ sudo gunzip config.gz
$ sudo mv config .config
menu configで項目を変更する
sudo make menuconfig
Device Drivers > Multimedia support > Video4Linux optionsの中をすべて選択(*印にする)
Device Drivers > Multimedia support > Media Driver > Media USB Adapter > USB Video Class と UVC input events device support を選択(*印にする)
Device Drivers > USB support > USB/IPサポートを選択(*印にする)
vi .config
CONFIG_DEBUG_INFO_BTF=y
→
CONFIG_DEBUG_INFO_BTF=n
すでに、 3818 # CONFIG_DEBUG_INFO_BTF is not set になっていたら何もしない。
カーネルをコンパイルする。
$ sudo make -j$(nproc)
$ sudo make modules_install -j$(nproc)
$ sudo make install -j$(nproc)
出来上がったカーネルをWindows上から見える場所にコピーする。
$ sudo cp /usr/src/${TAGVERNUM}-microsoft-standard/vmlinux /mnt/c/Users/<windows username>/
WSL2の設定ファイル(C:\Users\
[wsl2]
kernel=C:\\Users\\<windows username>\\vmlinux
⑫管理者権限でPowerShellを起動すると読み直されているので、もうOK!
以下のプログラムで動作確認をする。
import cv2
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 160)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 120)
cap.set(cv2.CAP_PROP_FPS, 10)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('Y','U','Y','V'))
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
while True:
_, img = cap.read()
cv2.imshow("", img)
key = cv2.waitKey(1)
if key == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
なお、注意が必要なのは、/dev/video0と/dev/video1はアタッチのたびに権限を変更しないといけないこと。
$ sudo chmod 777 /dev/video*
[ WARN:0@0.067] global /io/opencv/modules/videoio/src/cap_v4l.cpp (889) open VIDEOIO(V4L2:/dev/video0): can't open camera by index
高解像度だとでない
ここまで頑張ってやっとこさWSLでUSBカメラが使えるようになったのに、640x480とかにしたら
[ WARN:0@10.526] global /io/opencv/modules/videoio/src/cap_v4l.cpp (1000) tryIoctl VIDEOIO(V4L2:/dev/video0): select() timeout.
とタイムアウトエラーがでた。
解像度が大きいと駄目なようだ。
YUYVではなくモーションJPEGにしたら多少大きな解像度でもいけたが、フルHDとかは無理だった。
もういやなのであきらめた。
以上!
USBカメラがつながらなくなった!
WSL2でUSBカメラが使えないのはあきらめたが、ふと気づいたらWindows10でふつうにWebカメラが使えなくなった。
なんで?といろいろ調べたがわからず、usbipd-winをアンインストールしたら直った。
なんかもう、ってかんじ。