前回はWSL2+VS Codeの環境でC++を利用してみました。
今回は一歩進んでOpenCVを使ってみたいと思います。OpenCVはC++とPythonから利用できますが、今回はC++を使います。
OpenCVについて
OpenCVはコンピュータビジョンに関わる様々な処理を実装したオープンソースのライブラリです。
色変換や幾何変形というような画像処理から、物体検出のような高度な画像処理まで実装されています。
このあたりはWikipediaが参考になります。
この分野のライブラリとしてはもはやデファクトスタンダードと言ってもよいと思います。
OpenCVは様々なプログラミング言語から利用できますが、C++あるいはPythonから利用するのが主流のようです。
今回はWSL2のLinux上にあるOpenCVを、Windows上のVS Codeから使って見ようということになります。
ちなみに参考文献は下記の書物になります。
環境
今回はWindows 11上のWSL2に導入したUbuntu (20.04LTS)を使っています。
Windows 11のWSL2であるため、Wndows側にWSL2のグラフィックスを表示するWSLgが利用できます。
また開発環境であるVisual Studio Code (VS Code)は、WSL2を利用しているWindows上にインストールしています。
VS CodeからWSL2に接続するためには「Remote – WSL拡張機能」を利用することになります。
準備
実際にOpenCVを試す前にいくつかの準備が必要です。
WSL2側の準備
WSL2のLinuxにはOpenCVの開発環境を整える必要があります。
まずはC++のコンパイラ・デバッガなどを導入します。
$ sudo apt-get update $ sudo apt-get install build-essential gdb
もちろんC++のコンパイラなどの開発環境も導入しておきましょう。
続いてOpenCV関係のパッケージを導入します。
$ sudo apt-get update $ sudo apt-get install libopencv-dev
これでOpenCVに関係するパッケージがごっそり入るはずです。
インストールされたOpenCVの情報は次のようになります。
$ opencv_version 4.2.0
またopencv-docパッケージを入れておくと、テストに使えるデータもついてくるのでよいと思います。
$ sudo apt-get install opencv-doc
VS Code側の準備
VS Codeには少なくても下記の2つの拡張機能を導入しておく必要があります。
またコーディングを支援する拡張機能を入れておいても良いでしょう。
またtasks.jsonやlaunch.jsonのファイルについてもある程度を把握しておくとよいと思います。
OpenCVを試す
今回はOpenCVの基本部分を試してみると言うことで「JPEGファイルの表示」を試してみたいと思います。
なお、ソースコードは参考文献の第2章を参考にしています。
VS Codeでのコーディング
JPEGファイルの読み込みにはcv::imread()関数を利用します。
リファレンスマニュアルによれば「#include <opencv2/imgcodecs.hpp>」が必要となっています。
そこでVS Codeで適当なフォルダにソースコードを作成し、このインクルード文を書いてみます。するとVS Codeはこのヘッダファイルを見つけられず赤の波線が表示されてしまいます。
この行の右側には電球マークが表示されているので、選択してみましょう。
すると次のような選択肢が表示されるので、「”includePath”に追加: /usr/include/opencv」を選択しましょう
これでC/C++拡張機能設定の「パスを含める」に/usr/include/opencv4」が追加されます。
もう少し細かい話をすると、c_pp_properties.jsonというファイルが、.vscodeディレクトリに作成され、このファイルの”inludePath”キーに「/usr/inlcude/opencv4」が追加されます。
これで赤の波線が消えるだけでなく、他のOpenCVのヘッダファイルをincludeする際にファイル名が補完されたり、OpenCVのクラスを利用する際にIntelliSenseの補完が使えたりするようになります。
例えば、下の画面はcv::imread関数を利用しようとしているところですが、cv::imread関数の説明や他の入力候補が表示されていることがわかります。
このようにアシストをうけながら次のようなソースコードを作成しました。
#include <string> #include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> int main(int argc, char* argv[]) { const std::string window_name("OpenCV Sample"); cv::Mat img = cv::imread(argv[1]); if ( img.empty() ) { return -1; } cv::namedWindow(window_name, cv::WINDOW_AUTOSIZE); cv::imshow(window_name, img); cv::waitKey(0); cv::destroyWindow(window_name); return 0; }
VS Codeでのビルド
OpenCVのプログラムをビルドする際にはインクルードパス・リンクするライブラリなどの設定が必要です。
VS Codeではこのような設定は.vscodeディレクトリのtasks.jsonというファイルで行います。私の場合は次のようなファイルをtasks.jsonとして作成しました。
{ "version": "2.0.0", "tasks": [ { "type": "cppbuild", "label": "C/C++: OpenCVアプリのビルド", "command": "/usr/bin/g++", "args": [ "-I/usr/include/opencv4", "-fdiagnostics-color=always", "-g", "${file}", "-o", "${fileDirname}/${fileBasenameNoExtension}", "-lopencv_core", "-lopencv_imgcodecs", "-lopencv_highgui" ], "options": { "cwd": "${fileDirname}" }, "problemMatcher": [ "$gcc" ], "group": { "kind": "build", "isDefault": true }, "detail": "コンパイラ: /usr/bin/g++, OpenCVのライブラリ(core, imgcodecs, highgui)をリンク" } ] }
ポイントはargsキーの「-I/usr/include/opencv4」「-lopencv_core」「-lopencv_imgcodecs」「-lopencv_highgui」になります。
先ほど追加したインクルードパスはC/C++拡張機能がIntelliSenseのために使うものです。
コンパイラにヘッダの場所を教えるには、tasks.jsonでインクルードパスを設定する必要があります。
labelキーとdetailキーも変更していますが、これはわかりやすくするためです。
このようなtasks.jsonを作成してビルドを実行(「ターミナル」→「ビルドタスクの実行」)をすると、ビルドは正常に完了するはずです。
VS Codeでの実行・デバッグ
ビルドに成功したら実行してみましょう。
ビルドして生成されたプログラム(今回はshow-image)をターミナルで入力して実行しても良いですが、今回はVS Codeから実行してみましょう。
VS Codeでは実行する際の設定は.vscodeディレクトリのlaunch.jsonというファイルに記述します。私の場合は次のような内容としました。
{ // IntelliSense を使用して利用可能な属性を学べます。 // 既存の属性の説明をホバーして表示します。 // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "OpenCVアプリのビルドとデバッグ", "type": "cppdbg", "request": "launch", "program": "${fileDirname}/${fileBasenameNoExtension}", "args": [ "/usr/share/doc/opencv-doc/examples/data/LinuxLogo.jpg" ], "stopAtEntry": false, "cwd": "${fileDirname}", "environment": [], "externalConsole": false, "MIMode": "gdb", "setupCommands": [ { "description": "gdb の再フォーマットを有効にする", "text": "-enable-pretty-printing", "ignoreFailures": true }, { "description": "逆アセンブリ フレーバーを Intel に設定", "text": "-gdb-set disassembly-flavor intel", "ignoreFailures": true } ], "preLaunchTask": "C/C++: OpenCVアプリのビルド" } ] }
ポイントはargsキーに今回作成したプログラムで読み込みたい画像ファイルのパスを指定している点です。
argsキーの値はprogramキーで指定したプログラムの引数として渡されます。従って、この画像ファイルがビルドして生成されたプログラムの引数となります。
また、preLaunchTaskキーの値には、tasks.jsonで作成したビルドタスクを指定しています。
launch.jsonを作成したら「実行」→「デバッグの開始」を選択してみます。するとWindows上に次のようなウィンドウが表示されます。
この画像はlaunch.jsonのargsキーで指定したLinuxLogo.jpgです。そしてこのウィンドウ上で何かキーを押すと、プログラムは終了します。
WSL2がWSLgに対応していないとこのような表示はできません。
もちろん、ブレークポイントの設定してのデバッグも可能です。
例えば、cv::imread()で画像を読み込んだ後でブレークしてみると、変数imgに320×240の画像が読み込まれていることがわかります。
まとめ
今回はVisual Studio Code (VS Code)とWSL2を連携させた状態で、OpenCVを利用する簡単なプログラムをC++で作成してみました。
ちゃんと設定すると、コーディング時はIntelliSenseによるアシストを受けることができます。また、WSL2がWSLgに対応していれば、そのまま実行・デバッグを行うことができます。
WSL2を活用することで、Linux PCを用意できない人もLinux向けOpenCVの開発をできそうです。
次回はWSL2でUSBカメラを利用してみたいと思います。
コメント