LoginSignup
0
0

OpenCVで作った画像をGStreamerでネットワーク送信する (C++バージョン)

Last updated at Posted at 2024-06-28

OpenCVは言わずと知れたComputer Visionのライブラリ群ですが,画像・動画ファイルは作れてもストリーミング周りは弱いです(あるのかな).それを補うためにffmpegやGStreamerと組み合わせる仕様ができていますが,いまいち使い方の文献が多くないように思います.

そこで本稿では,Windows, vcpkg, C++の環境下での実施方法についてまとめてみます.元は卒論指導用です.とりえあず細かいことは省略して書きます.追々詳細化します.

環境構築

  1. Visual Studio 2022でC++によるアプリケーション開発をする環境を整えてください.
  2. vcpkgを導入してください
  3. vcpkgでOpenCVを入れます.つけるオプションは自由ですが,最低限,
    vcpkg install opencv4[gstreamer,ffmpeg]:x64-windows
    
    が良さそうです
  4. 上の方法でOpenCVを入れると,gstreamerの1.22.5が入るようです(2024年6月28日現在).この状態で入るGStreamerは各種プラグインなどが入っていないようなので,別にインストールし,環境変数(GST_PLUGIN_PATH)を設定する必要があります.このとき,別にインストールするGStreamerとvcpkgでOpenCVとともにインストールされるGStreamerのバージョンが一致していないと,どうやらうまく動かないようです.古いGStreamerは公式のアーカイブからダウンロードできます.MSVCの方が良いみたいです.無印とDevelの両方を入れます.
  5. GStreamerのインストールが完了したら,GST_PLUGIN_PATHを環境変数に設定します.私の環境では,C:\gstreamer\1.0\msvc_x86_64\lib\gstreamer-1.0でした.

動かしてみよう

こちらのStackOverflowの回答を参考にしました.

cv::VideoWritercv::VideoCaptureを使うようです.サンプルのように,gst-launch-1.0で記述するようなパイプラインを.openメソッドの引数に指定します.このとき,appsrcappsinkがOpenCVとの窓口になるみたいです.下のサンプルの場合は,cv::VideoWriter経由でフレームを書き込むと,appsrcに流れるようです.こちらが正しく実行できれば,下図のようにautovideosinkのウィンドウでOpenCVで作成したフレームが表示されます.

パイプラインを所望のシステムになるように構築するだけですから,ストリーミングでもファイル蓄積でも,簡単にできます.

OpenCV_GStreamer_sample
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;

int main()
{

    cv::VideoWriter out;
    out.open("appsrc ! videoconvert ! autovideosink",
        cv::CAP_GSTREAMER,
        0,
        16,
        cv::Size(640, 480),
        true);

    cv::Mat frame(480, 640, CV_8UC3, cv::Scalar(0, 255, 0));

    int count = 0;
    while(1)
    {
        rectangle(frame, Rect(0, 0, 640, 480), Scalar(0, 255, 0), -1);

        frame = Mat(480, 640, CV_8UC3, cv::Scalar(0, 255, 0));

        cv::putText(frame, to_string(count++), Point(100,100), FONT_HERSHEY_SCRIPT_SIMPLEX, 3.0, Scalar::all(255), 3, 8);

        out << frame;
        //imshow("sent", frame);        

        int c = waitKey(100);

        if (c == 'q')
            break;

    }

    return 0;
}

image.png

RTPストリーミングのサンプル(H.264エンコード)

VideoWriter.openメソッドで指定するパイプラインをRTPでストリーミングするように変えてみます.こちらも先ほどのStackOverflowの回答を参考にしています.

    cv::VideoWriter out;
out.open("appsrc ! videoconvert ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast ! rtph264pay ! udpsink host=127.0.0.1 port=5000",
    cv::CAP_GSTREAMER,
    0,
    16,
    cv::Size(640, 480),
    true);

受信側はgst-launch-1.0を使って

gst-launch-1.0 udpsrc port=5000 ! application/x-rtp ! rtph264depay ! h264parse ! decodebin ! autovideosink

にして見ます.受信側から起動して,RTPストリーミング開始すれば,ローカルホスト経由ですがautovideosinkのウィンドウで再生されました.

まとめ

これは便利・・・.時間を見つけてもうちょっとちゃんと記事を書きます.あしからず.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0