WSL2とVS Codeの環境でOpenCVを利用してみる(C++)

WSL2+VS CodeでOpenCVをC++利用してみるWSL
スポンサーリンク

前回はWSL2+VS Codeの環境でC++を利用してみました。

今回は一歩進んでOpenCVを使ってみたいと思います。OpenCVはC++とPythonから利用できますが、今回はC++を使います。

スポンサーリンク

OpenCVについて

OpenCVはコンピュータビジョンに関わる様々な処理を実装したオープンソースのライブラリです。

Home - OpenCV
OpenCV provides a real-time optimized Computer Vision library, tools, and hardware. It also supports model execution for Machine Learning (ML) and Artificial In...

色変換や幾何変形というような画像処理から、物体検出のような高度な画像処理まで実装されています。

このあたりはWikipediaが参考になります。

OpenCV - Wikipedia

この分野のライブラリとしてはもはやデファクトスタンダードと言ってもよいと思います。

OpenCVは様々なプログラミング言語から利用できますが、C++あるいはPythonから利用するのが主流のようです。

今回はWSL2のLinux上にあるOpenCVを、Windows上のVS Codeから使って見ようということになります。

ちなみに参考文献は下記の書物になります。

スポンサーリンク

環境

今回はWindows 11上のWSL2に導入したUbuntu (20.04LTS)を使っています。

UbuntuをWindows 11上で動かす その1: 準備とインストール
今回はWindows Subsystem for Linux (WSL2)を使ってWindows11にUbuntuをインストールしてみます。WSLを利用するためには以前は複数のステップが必要でしたが、ついにwslコマンド一発で導入できるようになりました。WSLを使う敷居がますます低くなったように感じます。

Windows 11のWSL2であるため、Wndows側にWSL2のグラフィックスを表示するWSLgが利用できます。

また開発環境であるVisual Studio Code (VS Code)は、WSL2を利用しているWindows上にインストールしています。

VS CodeからWSL2に接続するためには「Remote – WSL拡張機能」を利用することになります。

WSL2とVS CodeでC言語を利用してみる (Remote - WSL編)
今回はWSL2でLinuxを導入したWindowsにVS Codeをインストールして、C言語を使って見ます。拡張機能「Remote – WSL」を使ってVS CodeとWSL2を連携させると、Linuxのコマンドラインを一切使わずに、LinuxでC言語のプログラムをコンパイル・デバッグすることができます。かなり開発の敷居が下がるのではないでしょうか。

準備

実際に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つの拡張機能を導入しておく必要があります。

C/C++ - Visual Studio Marketplace
Extension for Visual Studio Code - C/C++ IntelliSense, debugging, and code browsing.
Remote - WSL - Visual Studio Marketplace
Extension for Visual Studio Code - Open any folder in the Windows Subsystem for Linux (WSL) and take advantage of Visual Studio Code's full feature set.

またコーディングを支援する拡張機能を入れておいても良いでしょう。

プログラミング(コーディング)に便利なVS Codeの拡張機能
今回はプログラミング(コーディング)に便利はVisual Studio Code(VS Code)の拡張機能を紹介します。VS Codeには様々な拡張機能があり、導入する拡張機能により使い勝手が大きく変わります。ここで紹介した拡張機能以外にもいろいろあるので、自分にあった拡張機能を探すと良いでしょう。

またtasks.jsonやlaunch.jsonのファイルについてもある程度を把握しておくとよいと思います。

WSL2とVS CodeでC++を利用してみる
今回はVisual Studio Code + WSL2という環境でC++のコーディング・ビルド・デバッグを試してみます。多少は手で設定する項目は有りますが、VS Codeによってビジュアルでデバッグできるのはかなり使いやすいのではないかと思います。

OpenCVを試す

今回はOpenCVの基本部分を試してみると言うことで「JPEGファイルの表示」を試してみたいと思います。

なお、ソースコードは参考文献の第2章を参考にしています。

VS Codeでのコーディング

JPEGファイルの読み込みにはcv::imread()関数を利用します。

リファレンスマニュアルによれば「#include <opencv2/imgcodecs.hpp>」が必要となっています。

OpenCV: Image file reading and writing

そこでVS Codeで適当なフォルダにソースコードを作成し、このインクルード文を書いてみます。するとVS Codeはこのヘッダファイルを見つけられず赤の波線が表示されてしまいます。

ヘッダが見つからないことを示す赤の波線

この行の右側には電球マークが表示されているので、選択してみましょう。

すると次のような選択肢が表示されるので、「”includePath”に追加: /usr/include/opencv」を選択しましょう

C/C++拡張機能のインクルードパスに追加

これでC/C++拡張機能設定の「パスを含める」に/usr/include/opencv4」が追加されます。

追加されたインクルードパス

もう少し細かい話をすると、c_pp_properties.jsonというファイルが、.vscodeディレクトリに作成され、このファイルの”inludePath”キーに「/usr/inlcude/opencv4」が追加されます。

追加されたインクルードパス (c_pp_properties.json)

これで赤の波線が消えるだけでなく、他のOpenCVのヘッダファイルをincludeする際にファイル名が補完されたり、OpenCVのクラスを利用する際にIntelliSenseの補完が使えたりするようになります。

例えば、下の画面はcv::imread関数を利用しようとしているところですが、cv::imread関数の説明や他の入力候補が表示されていることがわかります。

OpenCVの関数に対するInteliSense

このようにアシストをうけながら次のようなソースコードを作成しました。

#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カメラを利用してみたいと思います。

コメント