【OpenCV】ステップイン実行でOpenCVのソースを確認する方法

OpenCVは当然ながらオープンソースなので、ソースコードは公開されているのですが、ある特定の関数がOpenCV内部では、どのような処理をしているのか?を確認するのに、いきなりソースコードを眺めても、処理を追うのは、かなり困難かと思います。

 

そんな時には、やはりデバッグ実行しながら処理を追いかけた方が分かりやすいのですが、OpenCVの関数内へステップイン実行する方法を紹介します。

 

まず、確認したい処理のサンプルプログラムを作成し、ステップイン(関数の中身へ移動する)したい関数の行の右端のグレーの部分をクリックするか、ステップインする関数の行を選択してF9ボタンを押し、ブレイクポイント(処理を一時停止する場所)を指定します。

 

すると行の左側へ赤丸印が表示され、デバッグ実行を行うと、この赤丸印までの処理が行われ、一時停止状態となります。

 

 

次にメニューのデバッグステップインと選択するか、F11ボタンを押すと、以下のように初回だけ表示されます。

 

これは、今回の例ではcv::imshowの中身を見ようとしているのですが、この処理に必要なファイルがどこにあるのか?を聞かれます。

 

今回の例ではファイルの種類の部分にmatrix.cppと表示されているので、このファイルがあるフォルダを探し、そのフォルダを指定します。

 

ちなみに、matrix.cppのファイルは \opencv\modules\core\src 内にあります。

 

 

すると、ブレークポイントで指定した行で使われている関数の中へ、処理が移動していきます。

 

引き続きステップイン(F11ボタンを押す)実行を行うと、さらに関数の内部へ、ステップオーバー(F10ボタンを押す)実行を行うと、関数の内部へは行かずに、次の行へと移動します。

 

そうすると、実際に行われている処理の通りに、表示される行が移動していくので、処理の流れを確認し易いかと思います。

 

ちなみに!

今回、確認したかったのはcv::imshowの処理。

 

Windowsでは画像データのメモリの幅が4の倍数バイトとなるように調整しないと正しく表示されないハズにも係わらず、C++インターフェースのcv:Matでは、メモリの幅のバイト数を示すstepの値が、必ずしも4の倍数とならないのが、とても気になっていたんです。

 

そこで、実際にモノクロ8ビット(CV_8UC1)のcv::Matをcv::imshowへ渡し、ステップイン実行してみたところ、モノクロ画像と同じ画素数の24bitのメモリを確保し(このメモリは、幅が4の倍数バイトに調整されている)、cvConvertImage関数が呼ばれ、その内部では、OpenCV内部だけで使われるicvCvt_Gray2BGR_8u_C1C3Rという関数が実行され、8bitグレーの輝度値がR,G,Bの値が同じ、24bitのカラーデータへと変換されて、Win32APIのBitBltで画像が表示されている事が分かりました。

 

つまり、cv::imshowでモノクロの画像を表示する時に関数内部では、モノクロ画像の3倍のメモリが確保され、モノクロからカラーデータへの変換が行われています。

 

って、なんて無駄なんだ~!

この辺はやっぱりIplImageの方が好きなんだよな~

 

OpenCVへ戻る

【OpenCV】スタティックリンクライブラリの使用方法

OpenCVをダウンロードすると、ビルド済みのスタティックリンクライブラリがstaticlibというフォルダ内に格納されているのですが、以前、試した時には、うまく利用する事ができずに、CMakeでビルドしていました。

 

OpenCVをスタティックリンクライブラリでビルドする方法

https://imagingsolution.net/program/opencv/build_opencv231_static_library/

 

再度、OpenCV2.4.6で試してみたところ、以下の方法でスタティックリンクライブラリを使用する事ができました。

 

まず、こちら↓

http://sourceforge.net/projects/opencvlibrary/files/opencv-win/

よりOpenCVをダウンロードします。

 

WindowsのVer.2.4.6の場合はOpenCV-2.4.6.0.exeのファイルをダウンロードします。

 

ダウンロードしたファイルをダブルクリックすると自己解凍されますが、以下、ルートディレクトリ(c:\ )に解凍した場合を想定して説明します。

 

目的のスタティックリンクライブラリは下記フォルダに格納されています。

 

opencv
├build
├x86
│ ├vc9
│ ├vc10
│ │ ├staticlib
│ ├vc11
├x64

 

x86やx64、vc9,vc10,vc11は使用する環境に合わせて使用するフォルダを選択します。

 

まず、C++のプロジェクトを作成し、プロジェクトのプロパティで、構成すべての構成にし、構成のプロパティ→C/C++→全般→追加のインクルードディレクトリにopencv2のあるフォルダ

 

c:\opencv\build\include

 

などを指定します。(ファイルの解凍先によりディレクトリが異なります。)

 

 

次にスタティックリンクライブラリのあるフォルダの設定を行います。

こちらもプロジェクトのプロパティで、構成すべての構成にし、構成のプロパティ→リンカー→全般→追加のライブラリディレクトリ

 

c:\opencv\build\x86\vc10\staticlib

 

などを指定します。(ファイルの解凍先や開発環境によりディレクトリが異なります。)

 

x86・・・32bitプログラムを作成する場合(OSが64bitでも32bitプログラムは作成可能です。)
x64・・・64bitプログラムを作成する場合
(構成マネージャでプラットフォームをx64にするのをお忘れなく。
分からなければ、64bitOSであっても、まずはx86を使用して下さい。)
vc9・・・Visual Studio 2008で開発する場合
vc10・・・Visual Studio 2010で開発する場合
vc11・・・Visual Studio 2012で開発する場合

 

次に特定の規定のライブラリの無視というのを設定するのですが、これはDebugとReleaseで設定が違うので、構成のプロパティ→リンカー→入力→特定の規定のライブラリの無視の設定

 

構成がDebugの場合
Libcmtd.lib;msvcprtd.lib

構成がReleaseの場合
Libcmt.lib;msvcprt.lib

 

と入力します。

 

 

これで、OpenCVを使う準備ができたので、コードを下記のように書きます。

ここでのポイントはcomclt32.libファイルを追加している部分ぐらい。

以下、Canny Edge Detectorのサンプルコードです。

#include "stdafx.h"

//プロジェクトのプロパティ⇒C/C++⇒全般 の追加のインクルードディレクトリに
// opencv2のあるフォルダ(C:\opencv\build\includeなど)を追加のこと
#include "opencv2\opencv.hpp"

#pragma comment(lib,"comctl32.lib")

// バージョン名の取得
#define CV_VERSION_STR CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)

// libファイル名の最後の部分をReleaseとDebugで分ける
#ifdef _DEBUG
#define CV_EXT_STR "d.lib"
#else
#define CV_EXT_STR ".lib"
#endif

//プロジェクトのプロパティ⇒リンカー⇒全般 の追加のライブラリディレクトリに
// libファイルのあるフォルダ(C:\opencv\build\x86\vc10\libなど)を追加のこと
#pragma comment(lib, "opencv_core"	CV_VERSION_STR CV_EXT_STR)
#pragma comment(lib, "opencv_imgproc"	CV_VERSION_STR CV_EXT_STR)
#pragma comment(lib, "opencv_highgui"	CV_VERSION_STR CV_EXT_STR)

#pragma comment(lib, "zlib"	CV_EXT_STR)
#pragma comment(lib, "IlmImf"	CV_EXT_STR)
#pragma comment(lib, "libjasper"CV_EXT_STR)
#pragma comment(lib, "libjpeg"	CV_EXT_STR)
#pragma comment(lib, "libpng"	CV_EXT_STR)
#pragma comment(lib, "libtiff"	CV_EXT_STR)

int _tmain(int argc, _TCHAR* argv[])
{
    //画像データの読込
    cv::Mat src_img = cv::imread("lena.jpg", -1);
    if (src_img.empty()){
        return -1;
    }

    //表示ウィンドウの作成
    cv::namedWindow("src");
    cv::namedWindow("dst");

    //処理後画像データ格納用
    cv::Mat dst_img;

    //画像処理例(Canny Edge Detector)
    cv::Canny(src_img, dst_img, 100.0, 150.0);

	//画像の表示
    cv::imshow("src", src_img);
    cv::imshow("dst", dst_img);

	//キー入力待ち
    cv::waitKey (0);

	return 0;
}

(実行結果)

 

サンプルプロジェクトファイルはこちら↓

OpenCVStaticSample.zip

(OpenCV2.4.6 + Visual Studio 2010 C++ Expressのサンプルです)

 

スタティックリンクライブラリを使うと、Pathの設定が無いので、ちょっと楽!

 

OpenCVへ戻る