この記事はOpenCV Advent Calendar 2021の5日目の記事です。
はじめに
従来、OpenCVのcv::parallel_for_
backend、highgui backend、videoio backendはOpenCVインストール時に決定されてしまうため、OpenCVインストール後にbackendを変更しようと思うとOpenCVのビルドオプションを変更して再インストールする必要がありました。
OpenCV 4.5.xからプラグイン機構が導入され、OpenCVインストール後にこれらのbackendを動的に変更することができるようになりました。OpenCV 4.5.4時点で用意されているプラグインは以下のとおりです
- threadingプラグイン
-
cv::parallel_for_
backendを動的に変更できるプラグイン
-
- highguiプラグイン
- highgui backendを動的に変更できるプラグイン
- videoioプラグイン
- videoio backendを動的に変更できるプラグイン
とはいえ、なぜプラグイン機構を導入するに至ったかの経緯が気になってきます。https://docs.opencv.org/4.5.3/d0/d3d/tutorial_general_install.html#tutorial_general_install_plugins_4には以下の記述があります。
It is possible to decouple some of OpenCV dependencies and make them optional by extracting parts of the code into dynamically-loaded plugins. It helps to produce adaptive binary distributions which can work on systems with less dependencies and extend functionality just by installing missing libraries.
プラグインとして切り離しておき動的にロードする仕組みにしておけば、それぞれの環境に合ったプラグインを使用する形態にでき、依存ライブラリが入っていなくてプログラムが動かないなどのトラブルが減らせそうなことが書いてあります。
ということで、今回はOpenCVのプラグイン機能について簡単に紹介したいと思います。
threadingプラグイン
threadingプラグインを使うことでcv::parallel_for_
のバックエンドを動的に変更することができるようになります。OpenCV 4.5.2以降のバージョンでthreadingプラグインを使用することができます。
threadingプラグイン有効化
OpenCVビルド時にPARALLEL_ENABLE_PLUGINS=ON
にしておき、プラグイン機能を有効にします。
CMakeオプション | デフォルト値 | オプションの意味 |
---|---|---|
PARALLEL_ENABLE_PLUGINS | ON | threadingプラグインサポートの有効化、無効化を指定 |
threadingプラグイン生成
threadingプラグインを生成します。https://docs.opencv.org/4.5.3/d0/d3d/tutorial_general_install.html#tutorial_general_install_plugins_4にはCMakeオプションが以下のように紹介されています
cmake -G<generator> \
-DOPENCV_PLUGIN_NAME=opencv_core_tbb_<suffix> \
-DOPENCV_PLUGIN_DESTINATION=<dest-folder> \
-DCMAKE_BUILD_TYPE=<config> \
<opencv>/modules/core/misc/plugins/parallel_tbb
今回は以下のようなコマンドでMakefileを生成しました。
cmake -G"Unix Makefiles" \
-DOPENCV_PLUGIN_NAME=opencv_core_tbb_1 \
-DOPENCV_PLUGIN_DESTINATION=$HOME/opencv_plugin \
-DCMAKE_BUILD_TYPE=Release \
$HOME/dev/opencv-4.5.3/modules/core/misc/plugins/parallel_tbb
その後、
make
を実行すると$HOME/opencv_plugin
以下にlibopencv_core_tbb_1.so
が生成されます(今回、suffix
は適当に1を付けただけなので深い意味はありません)。
threadingプラグインの使い方
先程生成したthreadingプラグイン(前述の例だとlibopencv_core_tbb_1.so
)をOpenCVライブラリが配置されているパスに格納します。
TBBを使う場合
cv::parallel_for_
のバックエンドとしてTBBを使う場合のサンプルコードを以下に示します。
// TBB backendを使う場合はインクルードする
#include <opencv2/core/parallel/backend/parallel_for.tbb.hpp>
int main()
{
// cv::parallel_for_のバックエンドとしてTBBを使う
cv::parallel::setParallelForBackend(std::make_shared<cv::parallel::tbb::ParallelForBackend>());
return 0;
}
https://docs.opencv.org/4.5.4/de/d55/group__core__parallel__backend.html#ga7791f3c18e50f00b5fa88ac9d44cd52fにも以下の記載があり、cv::parallel::setParallelForBackend
の呼び出しについては注意が必要です。
This call is not thread-safe. Consider calling this function from the
main()
before any other OpenCV processing functions (and without any other created threads).
OpenMPを使う場合
cv::parallel_for_
のバックエンドとしてOpenMPを使う場合のサンプルコードを以下に示します。
前述の通り、cv::parallel::setParallelForBackend
の呼び出しについては注意が必要です。
// OpenMP backendを使う場合はインクルードする
#include <opencv2/core/parallel/backend/parallel_for.openmp.hpp>
int main()
{
// cv::parallel_for_のバックエンドとしてOpenMPを使う
cv::parallel::setParallelForBackend(std::make_shared<cv::parallel::openmp::ParallelForBackend>());
return 0;
}
highguiプラグイン
highguiプラグインを使うことでhighguiモジュールのバックエンドを動的に変更することができるようになります。OpenCV 4.5.3以降のバージョンでhighguiプラグインを使用することができます。
highguiプラグイン有効化
OpenCVビルド時にHIGHGUI_ENABLE_PLUGINS=ON
にしておき、プラグイン機能を有効にします。
CMakeオプション | デフォルト値 | オプションの意味 |
---|---|---|
HIGHGUI_ENABLE_PLUGINS | ON | highguiプラグインサポートの有効化、無効化を指定 |
HIGHGUI_PLUGIN_LIST | empty | バックエンド名をカンマ、もしくはセミコロンで区切って指定します。gtk, gtk2, gtk3が選択できます |
HIGHGUI_PLUGIN_LIST
に関して、
gtk, gtk2, gtk3が選択できます
はOpenCVドキュメントにある情報ですが、https://github.com/opencv/opencv/pull/20281を読むとわかるようにhttps://github.com/opencv/opencv/blob/4.5.4/modules/highgui/cmake/init.cmake#L39に
add_backend("win32ui" WITH_WIN32UI)
とあるので、HIGHGUI_PLUGIN_LISTにwin32ui
が指定できそうです(ドキュメントの更新漏れ?)。
また、https://github.com/opencv/opencv/blob/4.5.4/modules/highgui/cmake/init.cmake#L40-L42を読むと以下のようになっているので、OpenCV 4.5.4時点でCocoa、Qt対応などはまだのようです。
# TODO cocoa
# TODO qt
# TODO opengl
highguiプラグイン生成
highguiプラグインを生成します。
今回は以下のようなコマンドでMakefileを生成しました。
cmake -G"Unix Makefiles" \
-DOPENCV_PLUGIN_NAME=opencv_highgui_gtk_3 \
-DOPENCV_PLUGIN_DESTINATION=$HOME/opencv_plugin \
-DCMAKE_BUILD_TYPE=Release \
$HOME/dev/opencv-4.5.3/modules/highgui/misc/plugins/plugin_gtk
その後、
make
を実行すると$HOME/opencv_plugin
以下にlibopencv_highgui_gtk_3.so
が生成されます(今回、suffix
は適当に3を付けただけなので深い意味はありません)。
highguiプラグインの使い方
先程生成したhighguiプラグイン(前述の例だとlibopencv_highgui_gtk_3.so
)をOpenCVライブラリが配置されているパスに格納します。
videoioプラグイン
videoioプラグインを使うことでvideoioモジュールのバックエンドを動的に変更することができるようになります。
videoioプラグイン有効化
OpenCVビルド時にVIDEOIO_ENABLE_PLUGINS=ON
にしておき、プラグイン機能を有効にします。
CMakeオプション | デフォルト値 | オプションの意味 |
---|---|---|
VIDEOIO_ENABLE_PLUGINS | ON | videoioプラグインサポートの有効化、無効化を指定 |
VIDEOIO_PLUGIN_LIST | empty | バックエンド名をカンマ、もしくはセミコロンで区切って指定します。ffmpeg, gstreamer, msmf, mfxが選択できます |
VIDEOIO_PLUGIN_LIST
に関して、
ffmpeg, gstreamer, msmf, mfxが選択できます
はOpenCVドキュメントにある情報ですが、https://github.com/opencv/opencv/blob/4.5.4/modules/videoio/cmake/init.cmake#L11-L33を読むと以下のようになっています。
add_backend("ffmpeg" WITH_FFMPEG)
add_backend("gstreamer" WITH_GSTREAMER)
add_backend("v4l" WITH_V4L)
add_backend("aravis" WITH_ARAVIS)
add_backend("dc1394" WITH_1394)
add_backend("gphoto" WITH_GPHOTO2)
add_backend("msdk" WITH_MFX)
add_backend("openni2" WITH_OPENNI2)
add_backend("pvapi" WITH_PVAPI)
add_backend("realsense" WITH_LIBREALSENSE)
add_backend("ueye" WITH_UEYE)
add_backend("ximea" WITH_XIMEA)
add_backend("xine" WITH_XINE)
add_backend("avfoundation" WITH_AVFOUNDATION)
add_backend("ios" WITH_CAP_IOS)
add_backend("dshow" WITH_DSHOW)
add_backend("msmf" WITH_MSMF)
add_backend("android_mediandk" WITH_ANDROID_MEDIANDK)
add_backend("android_camera" WITH_ANDROID_NATIVE_CAMERA)
これだけ見るとVIDEOIO_PLUGIN_LIST
で指定できるパラメータがドキュメント記載のものよりも揃っているように見えます。時間の都合上、ドキュメントに記載のないフレームワークを指定しても動作するかの確認までできていないのでドキュメントの更新漏れなのかどうかはわかりません。
videoioプラグイン生成
videoioプラグインを生成します。
今回は以下のようなコマンドでMakefileを生成しました。
cmake -G"Unix Makefiles" \
-DOPENCV_PLUGIN_NAME=opencv_videoio_ffmpeg_3 \
-DOPENCV_PLUGIN_DESTINATION=$HOME/opencv_plugin \
-DCMAKE_BUILD_TYPE=Release \
$HOME/dev/opencv-4.5.3/modules/videoio/misc/plugin_ffmpeg
その後、
make
を実行すると$HOME/opencv_plugin
以下にlibopencv_videoio_ffmpeg_3.so
が生成されます(今回、suffix
は適当に3を付けただけなので深い意味はありません)。
videoioプラグインの使い方
先程生成したvideoioプラグイン(前述の例だとlibopencv_videoio_ffmpeg_3.so
)をOpenCVライブラリが配置されているパスに格納します。
おわりに
本記事では最近OpenCVに追加されたプラグイン機能について紹介しました。OpenCV 4.5.4時点だと一部バックエンドのみのサポートではありますが、揃ってくると配布時に便利なケースも出てきそうです。
参考URL
関連PR
- threadingプラグインのPR:https://github.com/opencv/opencv/pull/19470
- highguiプラグインのPR:https://github.com/opencv/opencv/pull/20116
- videoioプラグインのPR:https://github.com/opencv/opencv/pull/19320