OpenCV4.9.0×Qt5.15.2のビルド

久しぶりにimshowで表示した画像をズームする必要が生じたので、Qtを含めたビルドをしようとしたものの、何故か過去に実施した際のビルド設定では失敗しました。

イチからやり直しましたので、備忘録がてら記録を。

 

CMake、Visual StudioOpenCVOpenCV 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も含めました。

qiita.com

 

次に、CMakeの設定ですが、まずは以下の設定を行います。

  • BUILD_opencv_world にチェック
  • OPENCV_EXTRA_MODULE_PATH に [contribの配置場所]/module を設定
  • WITH_GSTREAMER にチェック
  • WITH_QT にチェック
  • 私のように別件で構築したJavaPython環境が邪魔という方は、以下の設定のチェックを全て外す

この状態で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;
    }
}

実行結果は以下のとおりです。

左から順に初期表示、ズーム時、マウスクリック時ですが、クリックした座標に黒色の点を描画することができていますので、これで細かな座標指定が実現できるはずです。

OpenCV/4.8.0のビルド

日本時間で6/29の午前2時頃でしょうか、OpenCVのver.4.8.0がReleaseされました。

github.com

自分の備忘録+超初心者にもわかるように・を意識して手順を記録しておこうと思います。

 

CMake、Visual Studioは予め用意しておくこととします。

私の環境では、CMake 3.22.2、Visual Studio 2022 Professionalを利用しています。

 

はじめに、OpenCVライブラリのダウンロード。

今回はとりあえずCUDAとかQtとかは無しで、拡張ライブラリ(contrib)のみのシンプルなビルドを行いますので、以下リンクからzipファイルをダウンロードします。

いずれも「Code」の「Download ZIP」をクリックしたら取得できます。

解凍したら「opencv-4.8.0」と「opencv_contrib-4.8.0」が出てきますので、扱いやすいところに配置します。

なお、以降の説明で出てくるパス設定等は、以下に示す私の環境におけるものですので、異なる配置の場合は読み替えるようにしてください。

C:
├ _develop_lib
│ ├ opencv
│ │ ├ opencv-4.8.0
│ │ └ opencv_contrib-4.8.0
│ └ opencv_build
│ └ 4.8.0
opencv
 └ 4.8.0

ざっくりまとめると、ダウンロードしたものは「C:\_develop_lib\opencv」、ビルドしたものは「C:\_develop_lib\opencv_build」、本番利用するものは「C:\opencv」にそれぞれ配置するようにしています。

 

次に、CMakeの設定ですが、超初心者にもわかるように・がモットーなので、GUI版で説明します。

「Where is the source code:」にOpenCV本体のパス、「Where to build the binaries:」にビルド結果保存先のパスをそれぞれ設定し、「Configure」をクリックすると子画面が出てきてVisual Studioのバージョンを設定するように促してくるので、適切なバージョンを選択して「Finisih」をクリックします。

 

しばらくは以下のような画面が表示されます。

終わると画面下部のメッセージボックスに「Configure done」と表示され、ビルドパラメータの設定ができるようになります。

今回はシンプル設定なので、以下の設定だけ行って、再度「Configure」をクリックします。

  • BUILD_oepncv_world にチェック
  • CMAKE_INSTALL_PREFIX … C:/_develop_lib/opencv_build/4.8.0/install
  • OPENCV_EXTRA_MODULES_PATH … C:/_develop_lib/opencv/opencv_contrib-4.8.0/modules

変なエラーとかが出ることもなく、きちんと「Configure done」が表示されたら「Generate」をクリックします。

ちなみに私の環境だと、最終的に以下のようなメッセージが出力されています。

General configuration for OpenCV 4.8.0 =====================================
  Version control:               unknown

  Extra modules:
    Location (extra):            C:/_develop_lib/opencv/opencv_contrib-4.8.0/modules
    Version control (extra):     unknown

  Platform:
    Timestamp:                   2023-06-29T12:11:58Z
    Host:                        Windows 10.0.22621 AMD64
    CMake:                       3.22.2
    CMake generator:             Visual Studio 17 2022
    CMake build tool:            C:/Program Files/Microsoft Visual Studio/2022/Professional/MSBuild/Current/Bin/amd64/MSBuild.exe
    MSVC:                        1936
    Configuration:               Debug Release

  CPU/HW features:
    Baseline:                    SSE SSE2 SSE3
      requested:                 SSE3
    Dispatched code generation:  SSE4_1 SSE4_2 FP16 AVX AVX2 AVX512_SKX
      requested:                 SSE4_1 SSE4_2 AVX FP16 AVX2 AVX512_SKX
      SSE4_1 (18 files):         + SSSE3 SSE4_1
      SSE4_2 (2 files):          + SSSE3 SSE4_1 POPCNT SSE4_2
      FP16 (1 files):            + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 AVX
      AVX (8 files):             + SSSE3 SSE4_1 POPCNT SSE4_2 AVX
      AVX2 (37 files):           + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2
      AVX512_SKX (8 files):      + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2 AVX_512F AVX512_COMMON AVX512_SKX

  C/C++:
    Built as dynamic libs?:      YES
    C++ standard:                11
    C++ Compiler:                C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.36.32532/bin/Hostx64/x64/cl.exe  (ver 19.36.32532.0)
    C++ flags (Release):         /DWIN32 /D_WINDOWS /W4 /GR  /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi  /fp:precise     /EHa /wd4127 /wd4251 /wd4324 /wd4275 /wd4512 /wd4589 /wd4819 /MP  /MD /O2 /Ob2 /DNDEBUG 
    C++ flags (Debug):           /DWIN32 /D_WINDOWS /W4 /GR  /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi  /fp:precise     /EHa /wd4127 /wd4251 /wd4324 /wd4275 /wd4512 /wd4589 /wd4819 /MP  /MDd /Zi /Ob0 /Od /RTC1 
    C Compiler:                  C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.36.32532/bin/Hostx64/x64/cl.exe
    C flags (Release):           /DWIN32 /D_WINDOWS /W3  /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi  /fp:precise     /MP   /MD /O2 /Ob2 /DNDEBUG 
    C flags (Debug):             /DWIN32 /D_WINDOWS /W3  /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi  /fp:precise     /MP /MDd /Zi /Ob0 /Od /RTC1 
    Linker flags (Release):      /machine:x64  /INCREMENTAL:NO 
    Linker flags (Debug):        /machine:x64  /debug /INCREMENTAL 
    ccache:                      NO
    Precompiled headers:         NO
    Extra dependencies:
    3rdparty dependencies:

  OpenCV modules:
    To be built:                 aruco bgsegm bioinspired calib3d ccalib core datasets dnn dnn_objdetect dnn_superres dpm face features2d flann fuzzy gapi hfs highgui img_hash imgcodecs imgproc intensity_transform line_descriptor mcc ml objdetect optflow phase_unwrapping photo plot python3 quality rapid reg rgbd saliency shape stereo stitching structured_light superres surface_matching text tracking ts video videoio videostab wechat_qrcode world xfeatures2d ximgproc xobjdetect xphoto
    Disabled:                    -
    Disabled by dependency:      -
    Unavailable:                 alphamat cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping cudev cvv freetype hdf java julia matlab ovis python2 python2 sfm viz
    Applications:                tests perf_tests apps
    Documentation:               NO
    Non-free algorithms:         NO

  Windows RT support:            NO

  GUI: 
    Win32 UI:                    YES
    VTK support:                 NO

  Media I/O: 
    ZLib:                        build (ver 1.2.13)
    JPEG:                        build-libjpeg-turbo (ver 2.1.3-62)
      SIMD Support Request:      YES
      SIMD Support:              NO
    WEBP:                        build (ver encoder: 0x020f)
    PNG:                         build (ver 1.6.37)
    TIFF:                        build (ver 42 - 4.2.0)
    JPEG 2000:                   build (ver 2.5.0)
    OpenEXR:                     build (ver 2.3.0)
    HDR:                         YES
    SUNRASTER:                   YES
    PXM:                         YES
    PFM:                         YES

  Video I/O:
    DC1394:                      NO
    FFMPEG:                      YES (prebuilt binaries)
      avcodec:                   YES (58.134.100)
      avformat:                  YES (58.76.100)
      avutil:                    YES (56.70.100)
      swscale:                   YES (5.9.100)
      avresample:                YES (4.0.0)
    GStreamer:                   NO
    DirectShow:                  YES
    Media Foundation:            YES
      DXVA:                      YES

  Parallel framework:            Concurrency

  Trace:                         YES (with Intel ITT)

  Other third-party libraries:
    Intel IPP:                   2021.8 [2021.8.0]
           at:                   C:/_develop_lib/opencv_build/4.8.0/3rdparty/ippicv/ippicv_win/icv
    Intel IPP IW:                sources (2021.8.0)
              at:                C:/_develop_lib/opencv_build/4.8.0/3rdparty/ippicv/ippicv_win/iw
    Lapack:                      NO
    Eigen:                       NO
    Custom HAL:                  NO
    Protobuf:                    build (3.19.1)
    Flatbuffers:                 builtin/3rdparty (23.5.9)

  OpenCL:                        YES (NVD3D11)
    Include path:                C:/_develop_lib/opencv/opencv-4.8.0/3rdparty/include/opencl/1.2
    Link libraries:              Dynamic load

  Python 3:
    Interpreter:                 C:/_tool/anaconda3/python.exe (ver 3.10.9)
    Libraries:                   C:/_tool/anaconda3/libs/python310.lib (ver 3.10.9)
    numpy:                       C:/_tool/anaconda3/lib/site-packages/numpy/core/include (ver 1.23.5)
    install path:                C:/_tool/anaconda3/Lib/site-packages/cv2/python-3.10

  Python (for build):            C:/_tool/anaconda3/python.exe

  Java:                          
    ant:                         NO
    Java:                        NO
    JNI:                         NO
    Java wrappers:               NO
    Java tests:                  NO

  Install to:                    C:/_develop_lib/opencv_build/4.8.0/install

PythonのところにAnaconda3の設定が表示されちゃってますが、別件で遊んでたのが読み込まれちゃっただけなので気にしないでください。

このように「Generating done」が表示されたら、「Where to build the binaries:」で指定したパスに「OpenCV.sln」ができています。

 

いよいよビルド作業です。

OpenCV.sln」を開き、「ビルド>バッチビルド」を選択、「ALL_BUILD」と「INSTALL」を探し、それぞれ「Debug」と「Release」の両方(計4か所)にチェックを入れたら「ビルド」をクリックするだけです。

あとは終わるのを待つだけです。

エラーさえ無ければ大丈夫なことが多いです。

なお、今回は以下のようなエラーがありましたが、Pythonを使う気は全く無いので無問題として無視します。

エラー LNK1104 ファイル 'python310_d.lib' を開くことができません。 opencv_python3 C:\_develop_lib\opencv_build\4.8.0\modules\python3\LINK 1

 

「CMAKE_INSTALL_PREFIX」で設定したパスに成果物ができているはずですので、本番利用するつもりの場所(あとでパスを通します)に配置します。

私の環境ですと(わかりやすさのために3階層目以下は省略していますが)以下のような配置になっています。

C:\opencv\4.8.0>tree | findstr /R /C:"^├" /C:"^│  ├" /C:"^│  └" /C:"^└"
├─bin
├─etc
│  ├─haarcascades
│  ├─lbpcascades
│  └─licenses
├─include
│  └─opencv2
└─x64

 

キーボードでWin+pauseを押し、「システムの詳細設定」から「環境変数」を選択します。

「Path」を選択して「編集」をクリックし、以下のように設定すれば完了です。

あとは、以下を参考にプロジェクト側で設定すれば準備完了です。

 

動作確認として、以下のコードを実行しました。

#include<opencv2/opencv.hpp>
#include<iostream>
#include<string>
#include<filesystem>

namespace fs = std::filesystem;

int main() {
    std::cout << cv::getBuildInformation();
    
    fs::path imgPath = "lena512.jpg";
    cv::Mat srcImg = cv::imread(imgPath.string());

    std::string wnd_name = "image";
    cv::namedWindow(wnd_name, cv::WINDOW_AUTOSIZE | cv::WINDOW_KEEPRATIO | cv::WINDOW_GUI_NORMAL);

    while (true) {
        cv::imshow(wnd_name, srcImg);
        int key = cv::waitKey(1);

        if (key == 27) {
            break;
        }
    }

    cv::destroyWindow(wnd_name);

    return 0;
}

OpenCV/YOLO学習済みモデルの利用方法

深層学習、いわゆるディープラーニングを使用した画像処理が脚光を浴び始めてから結構経った気がします。

私は大学で画像関係の研究をしていましたが、当時勉強したSIFTとかHOGといった特徴量ベースの物体検出・認識はすっかり過去のものという雰囲気を感じて少し寂しい気もしています。

 

さて、ディープラーニングプログラミング言語といえばPython!というのも、また広く知れ渡っている事実だと思います。

私自身、現在も画像関係の仕事をしているため、「そろそろPython環境をきっちり構築して真面目にディープラーニングの勉強に取り組もうかな」と思い続けているのですが、長らくWindowsC言語C++)、VisualStudio、OpenCVという環境で遊んできたので、ついつい「新しい言語は面倒だなぁ」と感じて諸事情により職場にはインターネット接続できるパソコンがないため、Pythonだと環境構築が非常に困難かつ面倒なので二の足を踏んでいる状態です。

しかしながら、ディープラーニングを使うことで、使わないときとは比較にならないくらいお手軽かつ高精度に処理できるものが多々あることはわかりきっています。

そこで、ひとまずPythonのことは置いといて、ディープラーニングを利用することで受ける恩恵がどんなものかを知るために、学習済みモデルを使って物体検出プログラムを動かしてみようと思います。

 

OpenCVでは、dnnというモジュール内の機能を使うことでディープラーニングによる学習済みモデルを使った処理を実現でき、公式ドキュメントを見るとCaffe、TensorFlow、Torch、Darknet、DLDT、ONNXに対応していることがわかります。

OpenCV: Deep Neural Network module

後ほど登場するOpenCVのサンプルではYOLOという物体検出アルゴリズムを使用し、Darknetというフレームワークの学習モデル形式を使っていますので、ここでも同様にします。

 

私の開発環境は以下のとおりです。

IDEですが、私の場合はオフラインでも使えるようにと有償版のProfessionalを利用していますが、オンライン環境下であれば無料版であるCommunityを使用しても問題ありません。

そして、開発言語ですが、もちろんPythonは使わずC++です。

OpenCVのバージョンは4.6.0(本記事の投稿時点では最新)で、公式サイトのLibrary -> Releases -> Windowsとリンクを辿ってダウンロードできるexe形式のものではなく、Gitから追加モジュールであるcontribを含めてダウンロードし、CMakeでビルドしたものを利用しています。

少し古い(2017年9月21日)ですが、contribについては以下の記事でわかりやすく紹介してくれていますし、記事中で紹介されているリンクを辿ってOpenCVのExampleを見てるだけでも結構楽しいのでおすすめです。

atmarkit.itmedia.co.jp

 

 物体検出プログラムのコードはOpenCVのサンプルをほぼそのまま使います。

OpenCV: samples/dnn/object_detection.cpp

OpenCV: YOLO DNNs

「ほぼ」そのままと言っていますが、そのままだと動かないとかではなく、個人的に使いにくいと感じたところを自分好みに書き換えただけで、変更点は以下の4点だけです。

  1. 検出結果が人物のものだけを描画(たくさん枠が描画されると邪魔)
  2. コマンドライン引数の一部(modelPathとconfigPath)をコード内で定義
  3. namdeWindowのオプション(WINDOW_NORMAL -> WINDOW_AUTOSIZE)
  4. 処理結果映像をVideoWriterで書き出し

 

あと必要となるものは、処理対象映像ファイルを除くと学習済みモデル関係です。

上のリンク先を見るとコマンドライン引数が以下のように書かれています。

$ example_dnn_object_detection --config=[PATH-TO-DARKNET]/cfg/yolo.cfg --model=[PATH-TO-DARKNET]/yolo.weights --classes=object_detection_classes_pascal_voc.txt --width=416 --height=416 --scale=0.00392 --input=[PATH-TO-IMAGE-OR-VIDEO-FILE] --rgb

つまり「yolo.cfg」、「yolo.weights」、「object_detection_classes_pascal_voc.txt」が必要になりますが、これらをどこから取ってきたらいいのかを調べるのに実は一番時間がかかりました。

今回は最新版であるYOLO v7を試してみたいと思いますので、以下のリンクから取得し、適当にファイル名を合わせました。

 

適切な場所に用意したファイルを配置し、先ほどのコマンドを参考に実行すれば難なく動くかと思います。

下の映像は、NHKクリエイティブ・ライブラリーで公開されている素材に対して物体検出を動かしてみた結果です。

youtu.be

閾値0.5のままですが、なかなかいい感じに検出できています。

Haar-Like特徴量やHOG特徴量等を使って人検出していたころは、サンプルコードと一緒に公開されている画像・映像以外で動かしてみるとイマイチな結果になることが多かったのですが、適当に選んだ映像でこれだけ精度良く検出できるのは素晴らしいですね。

セラ/ATF、メーターケーブルの交換

うちのセラは、そこまで状態は悪くないものの、一般的なユーザーがメンテナンスしないところ(ディーラーに任せていれば済むような各種点検・整備以外の部分と言えば伝わるでしょうか)に関しては手を入れていない雰囲気を感じる個体です。

そのため、ATF(オートマオイル)の交換はしていないだろうなぁと思い、今回ネッツトヨタさんに交換対応を依頼しました。

長期未交換のATFを上から循環交換してしまうと、スラッジを巻き上げることによる故障のリスクが無視できないので、今回は下抜きでの交換としました。

 

まず、ドレーンボルトを外してオイルを抜き、続けてオイルパンとオイルストレーナーを外します。

車底部(赤枠内がATFのオイルパン)

オイルパンとオイルストレーナーの取外し状況

排出されたオイルは一度も交換していないor交換してから結構な年数が経過していると思える汚れ方でした。

ちなみに外したオイルパンと洗浄後のオイルパンを並べるとこんな感じです。

磁石は新品なのでめちゃくちゃキレイです。

洗浄前後のオイルパンの比較

そして、取外したオイルストレーナーと新品のオイルストレーナーを並べるとこんな感じ。

新旧オイルストレーナー比較

実はオイルストレーナー(品番:35330-12020)は既にメーカー在庫なしとのことだったので、自分で調達しました。

メーカー在庫がないのにモノタロウで買えるのってなんでなんでしょうね…

なお、ガスケットはトヨタにも在庫があるとのことでしたが、オイルストレーナーを買ったら普通にガスケットも付いてました。

あとは元通りオイルストレーナーとオイルパンを取り付けてATFを入れておしまいです。

 

ここまでのATF交換における整備代金は2万5千円(うち技術料が1万円)でした。

セラのATF容量は7.2L、使用したATFはちょっとお高いカストロールのです。

安く抑えたい方は安価なATFを選択したり、工賃の安いところを探すのもありかと思います。

 

そして、旧車あるあるだとは思いますが、メーターの針がプルプル振れてたので、メーターケーブルの交換もしてもらいました。

これまた純正ケーブル(品番:83710-18030、83710-32130)が廃盤なので、スターレットのケーブル(品番:83710-16270)を持ち込みで対応してもらいました。

こちらの整備代金は1万円(部品代なし)でした。