調べたこと、作ったことをメモしています。
こちらに移行中: https://blog.shimazu.me/

QtからOpenCVを使ってみた

目標

バイトでOpenCVwindowsで弄る必要があったので、そのための環境を構築した。
でも、windowsAPIとか触ったことないし、覚えるには時間かかりすぎるし・・・と思ったらちょうどいいとこにQtを勉強しているじゃないですか!ということで、GUIの環境としてQtを利用しつつOpenCVも使えるように頑張ってみた。

目次

環境

  • Windows8 64bit
  • MSVC2012
  • Qt 5.1.1 x86 (あとQt 5.1.0 x64も入れた)
  • QtCreator 2.7.2
  • OpenCV 2.4.5

ただし、MSVCはインストール済みとする。

Qtのインストール

Qt 5.1.1、およびQt CreatorのセットはQtのページの「Downloads」からすぐにダウンロード・インストールができる。
インストールはデフォルトの設定のままNext押しておけば基本的にOK。
64bitと両方入れておけばマルチプラットフォームいえーいってできるけど、Qt Creatorが2つ入っちゃったので片方スタートから消して、片方のQt Creatorのツールの設定から64bitと32bitのQtが両方使えるようにした。  

Qt Creatorへのキットの追加方法

  1. プロジェクトを開いてない状態で「ツール」→「オプション」でオプションダイアログを開き、左ペインから「ビルドと実行」をクリック。
  2. まずはQtの追加をする。「Qtバージョン」タブをクリックし、「追加」を押して、Qt(僕は64bitに同梱したCreatorを使っていたので32bit)のパスを指定。(デフォルト設定ならC:\Qt\Qt5.1.1\5.1.1\msvc2012\bin\qmake.exeとか) 名前は最初に自動検出されたものにそろえて、「Qt 5.1.1 MSVC2012 32bit」とした。
  3. 「キット」タブを開き、「追加」をクリック。名前はこれも自動検出のものにそろえて「Desktop Qt 5.1.1 MSVC2012 32bit」とし、コンパイラに「Visual C++ Compiler 11.0 (x86)」を選択。「Qtバージョン」に先ほど追加した32bitのものを追加。
  4. 32bit版をデフォルトにする(そちらのほうが互換性が高いため)。32bitのキットをクリックして、「デフォルトにする」をクリック。ついでにどうせデスクトップってやつはいらないから削除。

OpenCVのインストール

参考ページ

手順

  1. OpenCVwikiからSourceForgeのダウンロードページに飛び、適当なバージョンをダウンロード。今回は2.4.5。
  2. デフォルトのまま実行し、C:\opencvに展開する。
  3. マシンビジョン研究室 - OpenCV 2.4.5 インストール(windows 7 64bit) を参考に、パスを通す。このときx64ではなくx84を設定すること、およびVC2012はvc11ディレクトリを指定することに注意。 つまり、PATHに追加するのは「C:\opencv\build\x86\vc11\bin;C:\opencv\build\x86\vc11;」となる。
  4. 再起動する これを忘れて悩んだ。

これでパスが通ってインストールは済んだはず。

プロジェクトの作成

  1. Qt Creatorから、「ファイル」→「ファイル/プロジェクトの新規作成」を押し、プロジェクト欄から「アプリケーション」を、中ペインから「Qt GUIアプリケーション」を選択し「選択」をクリック。
  2. 名前、パスは適当に。ここでは名前を「TestCV」、パスを「C:\qtprojects」とする。
  3. キットは2つともチェックしたまま「次へ」。
  4. クラス名は適当にTestCVWindowとでもする。
  5. 僕はgitのパスを登録したので、バージョン管理システムにgitを選択して完了。これは別途でmsysgitとかパスの設定が必要なはず。
  6. TestCVWindow.proを開いて、末尾に以下を追加。
# OpenCV settings
# for Windows
win32:DEPENDPATH  += "C:\opencv\build\include"
win32:INCLUDEPATH += "C:\opencv\build\include"
win32:LIBS += -L"C:\opencv\build\x86\vc11\lib"
win32:LIBS += -lopencv_core245 -lopencv_highgui245 -lopencv_imgproc245
  1. 「ビルド」→「qmake実行」でqmakeを一度かける。
  2. これでいつも通り、「#include <opencv2/opencv.hpp>」とかできるはず。

Qtの豆知識

まだQtに慣れておらず、知らないことがいくつかあったのでメモ。

cv::MatとQImageの変換

変換部分を参考に貼っておく。 captureはこのクラスのコンストラクタで

    capture = cv::VideoCapture(0);

として初期化している。

    // Renew camera image
    cv::Mat src, dst;
    capture >> src;
    if ( src.empty() ) {
        std::cerr << "Image can't be loaded!" << std::endl;
        return;
    }

    // cv::Mat -> QImage
    cv::cvtColor(src, dst, CV_RGB2BGR);
    QImage tmp((uchar *)dst.data, dst.cols, dst.rows,
                       dst.step, QImage::Format_RGB888);
    viewImage = tmp.copy();

QImageのoperator=が、画像をコピーせずに参照だけを渡すということを知らなくてかなり悩んでしまった。コピーするときはcopyメソッドを使ってからoperator=を使うらしい。

Unused Variableへの対処

各種Eventのハンドラの引数など、使わないときにattribute指示子が使えなかったので調べたらQ_UNUSEDとやらがあるらしい。

void TestView::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
}

というように、はじめにQ_UNUSEDマクロを使えばいいらしい。

タイマの利用

一定時間ごとに何かをする、というときに、いちいちQTimerオブジェクトのtimeoutシグナルとconnectする必要はなく、QObjectの持っているtimerを使えば簡単っぽい。

TestView::TestView(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TestView)
{
    ui->setupUi(this);

    // QObjectのタイマ関数の利用 -> timerEventの発生
    startTimer(33);
}

としてやると、33msごとに自分のメンバメソッドのtimerEventを呼んでくれるみたい。