WindowsでOpenCVSharpのビルドしなおしメモ


今回RTSP受信にGStreamerを使いたかったのでOpenCVSharpのOpenCVをビルドしなおしてみます。

まずはGstremaerをインストール

MinGWのランタイムとdevelopment両方インストールします。

をクローン

download_opencv_windows.ps1 を実行
opencv_filesが作成される

中身はこんな感じ

READMEに従えとあります

- [CMake](https://cmake.org/)
- [vcpkg](https://github.com/shimat/vcpkg) (forked by shimat)
  - For Tesseract dependency

とのことでCMAKEとvcpkgをインストールします。
現時点(2021/5/19)ではCMaake 3.20.2が最新でした。
パスを通すように設定してInstall

https://github.com/shimat/vcpkg/releases
にアクセスし最新版のダウンロード(2020.11)
展開するとこんな感じ

bootstrap-vcpkg.batを実行するとvcpkg.exeが生成されます。
build_windows.ps1を編集してvcpkg.exeのパスを変更するか、そのパスに従ってC:¥Tools¥vcpkg.exeに配置します。

システム環境変数 PATH C:\Tools\vcpkg追加
VisualStudioに英語言語パック追加

build_windows.ps1を編集してOpenCVのスイッチとして以下の行を追加
※以下のパスはgstreamerをC直下にインストールした場合です
※もしかしたらここまで要らないかもしれませんが未検証です

build_windows.ps1
          -D WITH_FFMPEG=OFF `
          -D WITH_GTREAMER=ON `
          -D GSTREAMER_DIR="C:/gstreamer/1.0/mingw_x86_64" `
          -D GSTREAMER_app_LIBRARY="C:/gstreamer/1.0/mingw_x86_64/lib/gstapp-1.0.lib" `
          -D GSTREAMER_base_LIBRARY="C:/gstreamer/1.0/mingw_x86_64/lib/gstbase-1.0.lib" `
          -D GSTREAMER_glib_INCLUDE_DIR="C:/gstreamer/1.0/mingw_x86_64/include/glib-2.0" `
          -D GSTREAMER_glib_LIBRARY="C:/gstreamer/1.0/mingw_x86_64/lib/glib-2.0.lib" `
          -D GSTREAMER_glibconfig_INCLUDE_DIR="C:/gstreamer/1.0/mingw_x86_64/lib/glib-2.0/include" `
          -D GSTREAMER_gobject_LIBRARY="C:/gstreamer/1.0/mingw_x86_64/lib/gobject-2.0.lib" `
          -D GSTREAMER_gst_INCLUDE_DIR="C:/gstreamer/1.0/mingw_x86_64/include/gstreamer-1.0" `
          -D GSTREAMER_gstreamer_LIBRARY="C:/gstreamer/1.0/mingw_x86_64/lib/gstreamer-1.0.lib" `
          -D GSTREAMER_pbutils_LIBRARY="C:/gstreamer/1.0/mingw_x86_64/lib/gstpbutils-1.0.lib" `
          -D GSTREAMER_riff_LIBRARY="C:/gstreamer/1.0/mingw_x86_64/lib/gstriff-1.0.lib" `
          -D GST_PLUGIN_PATH="C:/gstreamer/1.0/mingw_x86_64/lib/gstreamer-1.0" 

build_windows.ps1を実行するとビルドしてくれます。
最後にビルド結果を出してくれていましてGStreamerが有効になっていることを確認しましょう。

--   Video I/O:
--     DC1394:                      NO
--     GStreamer:                   YES (1.18.4)
--     DirectShow:                  YES
--     Media Foundation:            YES
--       DXVA:                      YES

build_win_x64と言うフォルダが作られます

opencvsharp/download_tesseract_windows.ps1を実行。
tesseract_filesが出来ます。
opencv_files\build_win_x64\modules\text
以下に
opencvsharp\tesseract_files\tesseract_vcpkg\installed\x64-windows-static\include\tesseract
をコピーします。

その中のOpenCV.slnを開きRelease x64でINSTALLをルドします。
(DebugでビルドするとOpenCVSharpExternビルド時にLNK1181でファイルが見つからないエラーが出ます)

opencv_files\build_win_x64\install
以下に必要なファイル群が生成されますので
opencvsharp\opencv_files\opencv452_win_x64
にコピーします。

同様にWin32もビルド、ファイルのコピーをしておきましょう。

opencvsharp/OpenCvSharpExternのプロジェクトのプロパティを開き
VC++ディレクトリ → インクルードディレクトリに追加

C:\gstreamer\1.0\mingw_x86_64\include\gstreamer-1.0
C:\gstreamer\1.0\mingw_x86_64\include\glib-2.0
C:\gstreamer\1.0\mingw_x86_64\include

既存のパスの$(SolutionDir)の直後の¥を削除(これはバージョンの問題かも?)

VC++ディレクトリ->ライブラリディレクトリに追加

C:\gstreamer\1.0\mingw_x86_64\lib\gstreamer-1.0
C:\gstreamer\1.0\mingw_x86_64\lib

既存のパスの$(SolutionDir)の直後の¥を削除(これはバージョンの問題かも?)

リンカー→全般→ 追加のライブラリディレクトリに以下を追加

C:\gstreamer\1.0\mingw_x86_64\lib
C:\gstreamer\1.0\mingw_x86_64\lib\gstreamer-1.0

リンカー→入力→追加の依存ファイルに追加

gstriff-1.0.lib
gstvideo-1.0.lib
gstbase-1.0.lib
gstreamer-1.0.lib
gstapp-1.0.lib
gobject-2.0.lib
glib-2.0.lib
gstadaptivedemux-1.0.lib
gstallocators-1.0.lib
gstbasecamerabinsrc-1.0.lib
gstcheck-1.0.lib
gstcodecparsers-1.0.lib
gstcontroller-1.0.lib
gstfft-1.0.lib
gstgl-1.0.lib
gstinsertbin-1.0.lib
gstisoff-1.0.lib
gstmpegts-1.0.lib
gstnet-1.0.lib
gstpbutils-1.0.lib
gstphotography-1.0.lib
gstplayer-1.0.lib
gstrtp-1.0.lib
gstrtsp-1.0.lib
gstrtspserver-1.0.lib

ffmpegのファイルは存在しないのでビルド後イベントのコマンドを一部削除

これでOpenCVSharpExternがビルドできました。

ソリューション内すべてをRelease x64とRelease x86でビルドします。

opencvsharp/nuget/OpenCvSharp4.runtime.win.nuspecをコピーして
opencvsharp/nuget/OpenCvSharp4_withGStreamer.rutime.win.nuspecにリネームして編集

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
    <metadata>
    ~~~~~
        <contentFiles>
            <files include="any\any\*.*" buildAction="None" copyToOutput="true" />
            <files include="any\any\gstreamer.plugins\*.*" buildAction="None" copyToOutput="true" />
        </contentFiles>
    </metadata>


    <files>
        <file src="gstreamer.bin\**" target="contentFiles\any\any\" />
        <file src="gstreamer.plugins\**" target="contentFiles\any\any\gstreamer.plugins" />
        <file src="..\src\Release\x64\OpenCvSharpExtern.dll"   target="runtimes\win-x64\native" />
        <file src="..\src\Release\Win32\OpenCvSharpExtern.dll" target="runtimes\win-x86\native" />
        <file src="OpenCvSharp4_withGStreamer.runtime.win.props" target="build\net\OpenCvSharp4.runtime.win.props" />
        <file src="OpenCvSharp4_withGStreamer.runtime.win.props" target="build\netstandard\OpenCvSharp4.runtime.win.props" />
        <file src="OpenCvSharp4_withGStreamer.runtime.win.props" target="build\netcoreapp\OpenCvSharp4.runtime.win.props" />

    </files>
</package>

gstreamer関連のDllをパッケージに組み込みますので

C:\gstreamer\1.0\mingw_x86_64\binからDLLとファイルをopencvsharp/nuget/gstreamer.binにコピー
C:\gstreamer\1.0\mingw_x86_64\lib\gstreamer-1.0からdllをopencvsharp/nuget/gstreamer.pluginsにコピー

PowerShellなど開き
cd opencvsharp/nuget/

.\nuget.exe pack OpenCvSharp4_withGStreamer.nuspec
.\nuget.exe pack OpenCvSharp4_withGStreamer.rutime.win.nuspec

動作確認のために↑で作ったnugetpackageをテスト用プロジェクトに追加

gstremer関連の依存ファイルがあるので

C:\gstreamer\1.0\mingw_x86_64\binからDLLとファイルを実行先にコピー
C:\gstreamer\1.0\mingw_x86_64\lib\gstreamer-1.0からdllを実行先のgstreamerpluginsにコピー
(RTSPはPluginで入ってるらしく↑の場所をGST_PLUGIN_PATHとして環境変数を登録する必要があります)

とりあえず動作させるために適当にコードを書いてみます。

var capture = new VideoCapture();

            try
            {
                capture.Set(VideoCaptureProperties.BufferSize, 3);
                Environment.SetEnvironmentVariable("GST_PLUGIN_PATH", @"gstreamer.plugins");
                capture.Open($"rtspsrc location=\"{networkAddress}\" latency=10 ! rtph265depay ! decodebin ! videoconvert ! appsink");
                }
            catch (Exception)
            {
                capture.Dispose();
            }
                while (true)
                {
                    if (_videoCapture.Read(mat))
                    {
                        Cv2.ImShow("test", mat);
                        Cv2.WaitKey(5);
                    }

                }

とりあえず動作はしました。

GST_PLUGIN_PATHの実行をOpenCVSharp内で実行するなどできれば綺麗になりますかね・・・。