前回はWindowsからWSL2へFFMPEGでUSBカメラの映像をストリーミングすることで、WSL2上のOpenCVでUSBカメラの映像を取得してみました。
このときはWindowsからUSBカメラを映像をストリーミングする際にFFMPEGというソフトを使いましたが、今回はVLC media playerを使ってみたいと思います。
WSL2でUSBカメラを利用するためのストリーミング
WSL2は仮想環境のようなものでUSBデバイスを直接利用できません。
WSL2でUSBカメラを使うためにはUSBをIPに変換する方法があります。
しかし、これにはいくつか課題があり、代替案としてネットワークストリーミングを利用したのが前回の記事です。
この記事では、WindowsからUSBカメラの映像をストリーミングするためには、FFMPEGというツールを利用しました。
このFFMPEGは大変多機能なのですが、コマンドラインで操作しなければならず、少々とっつきにくいところがあります。
そこで今回はGUIで操作できるVLC media playerを利用したいと思います。
構築するシステムは
- USBカメラはWindows PCに接続する
- Windows PCからWSL2のLinuxへUSBカメラの映像をストリーミングする
- WSL2のLinuxで動作するOpenCVではストリーミングされた映像を受信する
という形になります。
今回はこの2番目のステップでVLC media playerを利用します。
Windows側の準備
Windowsにはストリーミングを行うソフトウェアとしてVLC media playerをインストールします。
VLC media playerは下記のサイトからダウンロードできます。
最近ではMicrosoft Storeからも入手できるようです。
インストール自体は簡単なので説明する必要はないと思います。
WSL2側の準備
WSL2のLinuxで導入する必要があるのはOpenCVとFFMPEGです。FFMPEGは事前の動作確認時に利用します。
OpenCVについては次のコマンドで導入できます。
$ sudo apt-get install libopencv-dev
FFMPEGのインストールは次のコマンドです。
$ sudo apt-get install ffmpeg
またストリーミングに必要な情報としてWSL2側のIPアドレスが必要です。WSL2のIPアドレスは次のコマンドで表示されます。
$ ip -4 addr show dev eth0
6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 inet 172.18.227.172/20 brd 172.18.239.255 scope global eth0 valid_lft forever preferred_lft forever
IPアドレスはinetに続く「172.19.227.172」の部分です。
このIPアドレスはのちのち使うのでメモしておきます。
WSL2ではWSL2を起動する度にIPアドレスが変化してしまいますので注意してください。
IPアドレスはストリーミングを実施する直前に確認する方が良いかもしれません。
VLCによるUSBカメラのストリーミング
それではWidnowsにインストールしたVLC media playerを使ってUSBカメラの映像をストリーミングしてみましょう。
ストリーミングの開始
VLC media playerを起動したら、メニューで「メディア」→「キャプチャーデバイスを開く」を選択します。
「メディアを開く」というウィンドウが開いたら、「デバイスの選択」の「ビデオデバイス名」の欄から接続しているUSBカメラの名前を選びます。
続いて右下の「再生ボタン」の右側の「▼」を選択し、表示された選択肢の中からで「ストリーム再生」を選択します。
続いて「ストリーム出力」というウィンドウが表示されます。
最初の「入力元」についてはそのまま「次へ」を選択してOKです。
続いて出力先の設定です。
ここでは新しい出力先として「UDP (legacy)」を選択して「追加」を選択します。
ここで「ローカルで再生する」をチェックしておくと、ストリーミング中の映像を見ることができます。
新しい出力先としてUDPを追加すると、次のような画面になります。
ここでは「アドレス」に先ほど調べたWSL2のLinuxのIPアドレスを入力します、ポート番号は何でも良いのですがここでは「5120」としておきます。
続いてトランスコーディングの設定です。
ここでは「トランスコーディングを有効にする」をチェックした上で、プロファイルとして「Video – H.264 + MP3 (TS)」を選択します。
ここでプロファイルの右側のスパナアイコンを選択すると、ビットレートなどのカスタマイズができますが、今回は説明を省略します。
最後に「すべての基本ストリームをストリーミングする」をチェックして右下の「ストリーム」を選択します。
これでVLC media playerによるストリーミングが開始されます。
VLC media playerの画面には「Converting ddshow://」と表示されます。
このとき左下のタイムコードが時間とともに増加していけば、ストリーミングが正常に開始しています。
ストリーミングの確認
VLC media playerによるストリーミングを開始したら、このストリーミングデータがWSL2側に届いているかどうかを確認してみましょう。
この確認はFFMPEGに付属する「ffplay」というコマンドを利用します。WSL2側のターミナルで
$ ffplay udp://127.0.0.1:5120
を実行してみましょう。
最初は
[h264 @ 0x7fe660026580] decode_slice_header error [h264 @ 0x7fe660026580] no frame! [h264 @ 0x7fe660026580] non-existing PPS 0 referenced Last message repeated 1 times [h264 @ 0x7fe660026580] decode_slice_header error [h264 @ 0x7fe660026580] no frame! [h264 @ 0x7fe660026580] non-existing PPS 0 referenced Last message repeated 1 times [h264 @ 0x7fe660026580] decode_slice_header error [h264 @ 0x7fe660026580] no frame! [h264 @ 0x7fe660026580] non-existing PPS 0 referenced Last message repeated 1 times
とエラーっぽいメッセージが表示されますが、5~10秒ほど待つとウィンドウが表示され、USBカメラの映像(=WindowsのVLC media playerでストリーミングされている映像)が表示されるはずです。
これでVLC media playerでストリーミングができることが確認できました。
WSL2のターミナルでffplayコマンドを実行する際には、WSL2でGUIが利用できる状態で行ってください。
WSL2上のOpenCVによるキャプチャ
このセクションの内容は前回と全く同じです。
つまりWindows上えトリーミングを行うソフトがFFMPEGからVLC media playerになっただけで、WSL2側でおこなう内容は変っていないことになります。
ようやく本題です。
WSL上のOpenCVで上記のVLC media playerによるストリーミングをキャプチャするために、次のようなソースコードを作成します。
#include <string> #include <iostream> #include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> int main(int argc, char* argv[]) { const std::string window_name("OpenCV Sample"); cv::VideoCapture cap("udp://127.0.0.1:5120"); if ( !cap.isOpened() ) { std::cerr << "Can't open capture device" << std::endl; return -1; } cv::Mat frame; while (1) { cap >> frame; if ( frame.empty() ) { std::cerr << "Fail to capture video" << std::endl; break; } cv::imshow(window_name, frame); if ( cv::waitKey(100) >= 0 ) { break; } } return 0; }
このファイルをcapture-streaming.cppとして保存して、次のようにコンパイルします。
$ /usr/bin/g++ -I/usr/include/opencv4 -fdiagnostics-color=always capture-streaming.cpp -o capture-streaming -lopencv_core -lopencv_imgcodecs -lopencv_highgui -lopencv_videoio
ビルドに成功すると「capture-streaming」というファイル名の実行ファイルが生成されます。
そしてその実行ファイルを実行してみます。
$ ./capture-streaming
5秒ほどすると「OpenCV Sample」というタイトルのウィンドウが表示され、そのウィンドウでUSBカメラの映像(=Windows上のVLC media playerがストリーミングしている映像)が表示されます。
もし「Can’t open capture device」というエラーになってしまう場合は
- Windows上のVLC media playerでストリーミングを開始しているか?
- WSL2上でストリーミングを受信しているプログラムはないか? (例えば、テストに利用したffplay)
を確認してみてください。
また、cv::VideoCaptureのインスタンスを生成する部分を
cv::VideoCapture cap("udp://127.0.0.1:5120" , cv::CAP_FFMPEG);
とするとうまくいくかもしれません。
まとめ
今回はWSL2上のOpenCVでUSBカメラの映像を取得するために、Windows上のVLC media playerを使ってストリーミングしてみました。
VLC media playerを利用することで、GUIでストリーミングの設定をすることができ、FFMPEGを用いるより簡単かもしれません。
遅延が大きい等の制限はありますが、WSL2上のOpenCVでUSBカメラの映像を取得したい方は、ストリーミングを試してみてください。
次回はWordPressの執筆環境を考えたいと思います。
コメント