久しぶりにimshowで表示した画像をズームする必要が生じたので、Qtを含めたビルドをしようとしたものの、何故か過去に実施した際のビルド設定では失敗しました。
イチからやり直しましたので、備忘録がてら記録を。
CMake、Visual Studio、OpenCV、OpenCV contribはOpenCV/4.8.0のビルドのとおりですが、OpenCV関係はバージョンアップされてますので4.9.0を使用します。
Qtは、まず公式サイトからオープンソース版のインストーラをダウンロードします。
インストーラを実行すると、インストールするバージョンやコンポーネントの選択画面が出てきますので、「Archive」にチェックを入れて「フィルター」をクリックし、「Qt5.15.2」の「MSVC 2019 64-bit」だけにチェックを入れてインストールします。
なお、そろそろQt6系にも対応してくれたかなと期待して、現時点で最新バージョンの6.6.2でも試してみましたがOpenCVのビルドはできませんでした。
あとは、環境変数のPathに「[Qtインストール場所]\5.15.2\msvc2019_64\bin」を設定して、Qtの準備は完了です。
また、別件でFFmpeg以外のvideoioバックエンドを使って遊びたかったので、今回は以下のサイトを参考にGStreamerも含めました。
次に、CMakeの設定ですが、まずは以下の設定を行います。
- BUILD_opencv_world にチェック
- OPENCV_EXTRA_MODULE_PATH に [contribの配置場所]/module を設定
- WITH_GSTREAMER にチェック
- WITH_QT にチェック
- 私のように別件で構築したJavaやPython環境が邪魔という方は、以下の設定のチェックを全て外す
この状態でConfigureを実行すると、特にエラーは出ないと思いますし、Pathが通せていれば他に設定せずとも、QtとGStreamerのValueには適切なパラメータが反映されると思います。
が、しかし、このままビルドすると、cvv::gui::CallTabほか多数でLNK2001のエラーが生じました。
cvvは「GUI for Interactive Visual Debugging of Computer Vision Programs」、つまりデバッグ用GUIツールなのですが、どうもこれを含めているとビルドでこけるようです。
なので、以下の設定を追加で行い、再度Configure。
- BUILD_opencv_cvv のチェックを外す
あとはGenerate⇒Open Project⇒ビルドのお決まりの流れで完了です。
えー…余談となりますが、そもそもimshowで表示した画像をズームしたかった理由は、画像上の任意の点を選択する機能を持ったプログラムを作成したかったからなのですが、上記のとおり素直にビルドし、imshowで表示したウィンドウ上でマウスホイールをくるくるっと操作してズームしてみると…あら不思議、マウスカーソルが矢印から手に変わりますよね。
クリックして座標選択するのにはものすごく不向きなマウスカーソルです。
というわけで、実際には、ビルドする前に「highgui/src/window_QT.cpp」のコードを以下のとおり修正しました。
- DefaultViewPort::mousePressEvent の setCursor(Qt::ClosedHandCursor); を setCursor(Qt::ArrowCursor); に変更
- DefaultViewPort::mouseReleaseEvent 及び DefaultViewPort::scaleView の setCursor(Qt::OpenHandCursor); を setCursor(Qt::OpenHandCursor); に変更
動作確認用に使用したテストコードは以下のとおりです。
#include<opencv2/opencv.hpp> using namespace cv; void onMouse(int event, int x, int y, int flag, void*); Mat canvas = imread("lena.jpg"); int main() { namedWindow("image", WINDOW_NORMAL | WINDOW_KEEPRATIO | WINDOW_GUI_NORMAL); setMouseCallback("image", onMouse, 0); while (true) { imshow("image", canvas); int key = waitKey(1); if (key == 27) { break; } } destroyWindow("image"); return 0; } void onMouse(int event, int x, int y, int flag, void*) { switch (event) { case EVENT_LBUTTONDOWN: circle(canvas, Point(x, y), 0, Scalar::all(0), 0, LINE_4, 0); break; } }
実行結果は以下のとおりです。
左から順に初期表示、ズーム時、マウスクリック時ですが、クリックした座標に黒色の点を描画することができていますので、これで細かな座標指定が実現できるはずです。