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からも入手できるようです。

Get VLC from the 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をコピーしました