WSL2上のOpenCVでUSBカメラつかう (VLCによるストリーミング)

WSL2上のOpenCVでUSBカメラつかう (VLCによるストリーミング) WSL
スポンサーリンク

前回はWindowsからWSL2へFFMPEGでUSBカメラの映像をストリーミングすることで、WSL2上のOpenCVでUSBカメラの映像を取得してみました。

このときはWindowsからUSBカメラを映像をストリーミングする際にFFMPEGというソフトを使いましたが、今回はVLC media playerを使ってみたいと思います。

スポンサーリンク

WSL2でUSBカメラを利用するためのストリーミング

WSL2は仮想環境のようなものでUSBデバイスを直接利用できません。

WSL2でUSBカメラを使うためにはUSBをIPに変換する方法があります。

WSL2でUSBカメラを使う - 前編
今回はWSL2のUbuntuでUSBデバイスを認識できるようにしてみます。WSL2は仮想マシンのようなものなので物理的なUSBポートは有りませんが、USBIPD-WINというツールを使うことでWindowsに接続されたUSBデバイスを認識することができます。ただWSL2のLinux kernelにはUSBカメラのドライバが含まれていないため、USBカメラを使うにはもう一工夫必要です。
WSL2でUSBカメラを使う - 後編
今回はWSL2でUSBカメラを使えるようにしてみます。WSL2のLinux KernelはV4L2やUVCが有効になっていないため、USBカメラを利用するにはLinux Kernelを自分でコンパイルして差し替える必要があります。Linux Kernelを変更すればUSBIPD-WINと組み合わせることによってWSL2でUSBカメラを利用することができます。ただ転送速度に難があるようなのが残念です。

しかし、これにはいくつか課題があり、代替案としてネットワークストリーミングを利用したのが前回の記事です。

WSL2上のOpenCVでUSBカメラつかう (FFMPEGによるストリーミング)
今回はWSL2上のOpenCVでUSBカメラの映像を取得するために、Windows上のFFMPEGを使ってストリーミングしてみます。事前にストリーミングを開始する手間が必要ですが、USBIPD-WINを使ってWSL2にUSBデバイスを見せるよりも、高解像度の映像を取得できるのがメリットです。ただし、映像の遅延はストリーミングの方が大きくなるので、使い分けると良さそうです。

この記事では、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は下記のサイトからダウンロードできます。

Official download of VLC media player, the best Open Source player - VideoLAN
Official download of VLC media player, the best Open Source player

最近ではMicrosoft Storeからも入手できるようです。

VLC - Microsoft Store の公式アプリ
VLC media player (previously the VideoLAN Client and commonly known as simply VLC) is a free and open-source, portable, cross-platform media player software and streaming media server developed by the VideoLAN project. VLC is available for ...

インストール自体は簡単なので説明する必要はないと思います。

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を追加すると、次のような画面になります。

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でストリーミングされている映像)が表示されるはずです。

ffplayerによる表示

これでVLC media playerでストリーミングができることが確認できました。

WSL2上のOpenCVによるキャプチャ

ようやく本題です。

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がストリーミングしている映像)が表示されます。

OpenCVによるキャプチャ

もし「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の執筆環境を考えたいと思います。

コメント

タイトルとURLをコピーしました