OpenCV/Linux試用記
OpenCV-2.4.5-1/Fedora 19における注意をこのWebsiteの最後に加筆しました。
Visual C++/Windows用の説明はこちらのウェブサイト
Linux (Ubuntu 12.04 LTS)にOpenCVをインストールしたが(2013/03/22)、備忘録としてこのウェブサイトを構築した。
Ubuntuの場合、インストールはソフトウェアセンターにおいて「opencv」を検索語として設定すると関連するソフトウェアが表示される(図1)。
図1
ハードディスクに余裕があるので、すべてインストールすることにした。まず、「Development files for opencv」を選んでインストールすると、他の多くのソフトウェアも一緒にインストールされる。その後、まだインストールされていないソフトウェア(多くない。あと数回のインストールですべてインストールできる)を1つずつインストールしていく。
インストールが終わったので、簡単なプログラムを書いて、試してみた。プログラムをコンパイルとリンク、すなわちビルドして、実行形式のファイル(オブジェクト)を作成した。コンパイルではヘッダーファイルの指定、リンクではライブラリの指定を行うことになる。ヘッダーファイルの指定は、プログラムを書くときにも関係してくるので、「プログラミングとコンパイル(ヘッダーファイルの指定)」として説明する。その後、「リンクにおけるライブラリの指定」の説明を行う。また、2つのWindowを表示する簡単なプログラムを複数の*.cppファイルで作成し、makeファイルによるビルド例を示す。
以下のようなプログラムを書いた。
============== リスト1 =====================
#include <highgui_c.h>
int main(){
IplImage * img = cvLoadImage( "TestImg.bmp" );
cvNamedWindow( "TestImage", CV_WINDOW_AUTOSIZE );
cvShowImage( "TestImage", img );
cvMoveWindow( "TestImage", 100, 100 );
cvWaitKey(0);
cvReleaseImage( &img );
cvDestroyWindow( "TestImage" );
return 0;
}
=========================================
まず、コンパイルのために必要なヘッダーファイルを探す必要がある。上のプログラムでは「highgui_c.h」が指定されているが、これは以下のようにして見つけることができる。
「Find Files/Folders」を起動して、「内容」ページの「次のテキストを含む」欄に上のプログラムで用いられているOpenCVの関数、例えば「cvLoadImage」を設定する。
図2
次に、「名前/場所」ページの「場所」欄に、ヘッダーファイルを探しているので「/usr/include」まで設定する。自信がないときはルート「/」でもよいが、検索に時間が掛かる。
図3
場所の設定後、「検索」ボタンをクリックすると検索が始まる。検索が終了すると図4のように、指定したテキスト(図2)を含むファイルが、名前とその存在するフォルダ名とともに表示される(図4)。
図4
表示されているファイル名をクリックすると、そのファイルがエディタで表示される(図5)。エディタの検索機能を使ってテキスト(図2の場合は、「cvLoadImage」)を探せばよい。
図5
図5でのcvLoadImage関数の関数頭部の宣言から、cvLoadImageの宣言がhighgui_c.hで行われていることがわかる。引数の並びにおける「CV_DEFAULT(値)」は別のヘッダーファイルで定義されているマクロであり、この左のiscolorがデフォルト引数であることを示すものである(すなわち、何も指定しなくてもよい)。図4、図5に示されている結果から、関数cvLoadImageを用いるためには、フォルダ /usr/include/opencv2/highgui/ にあるファイル highgui_c.h をヘッダーファイルとしてincludeしなければならないことがわかる。g++ コマンドを以下のように実行する(図6)。
g++ −c –I/usr/include/opencv2/highgui/ Check.cpp
図6に示されているようにコンパイルは成功している。オプション「-c」は、コンパイルのみ行うことを意味する。「-I」を付けて「-I/usr/include/opencv2/highgui/」と示したフォルダ「/usr/include/opencv2/highgui/」は、ファイル名が「<highgui_c.h>」のように < と > で挟まれたファイル highgui_c.h が、システムに登録されたフォルダに加えて「-I」を付けて示されたフォルダからも探されることを指示するものである。
コンパイルまでは成功したので、次はリンク時に指定するライブラリの設定を行う。
OpenCVのライブラリは「libopencv_」で始まり、「.a」で終わる形式の名前であり、フォルダ「/usr/lib」以下に格納されているので、図7のように「Find Files/Folders」の「名前」欄と「場所」欄を設定する。文字 * は任意の文字列と対応可能である。
図7
プログラム(リスト1)の関数「cvLoadImage」を検索条件のテキストとして指定して(図8)、「検索」ボタンをクリックすると図8のような検索結果を得る。
図8
「最初にマッチ・・・」欄で数値の一番小さい「libopencv_highgui.a」を必要なライブラリの候補として試してみるため、このライブラリをリンク時に探索するものとして指定する「-lopencv_highgui」を付けて「-c」オプションを「-o」に変えたg++コマンドを次のように実行してみる。
g++ -o Check –I/usr/include/opencv2/highgui/ Check.cpp –lopencv_highgui
オプション「-l文字列」は、リンク時に必要なものを「lib文字列.a」のライブラリからも探すように指示するものである。したがって、「-lopencv_highgui」は、「libopencv_highgui.a」というライブラリからもリンク時に必要なものが探されることになる。このファイルは、フォルダ「/usr/lib」下にあるが、フォルダ「/usr/lib」がリンク時の探索の対象に含まれていることは、システムに設定されている。
上の「g++ -o ・・・」の実行結果は、図6に示されているように「cvReleaseImage」に関連して「・・・libopencv_core・・・」に関わるエラーが出ている。検索テキストとして「cvReleaseImage」を設定して、図7の条件で検索すると図9の結果を得る。
図9
「libopencv_core.a」が上がっているので、オプションに「-lopencv_core」を加えた
g++ -o Check –I/usr/include/opencv2/highgui/ Check.cpp –lopencv_highgui –lopencv_core
を実行してみる。結果は、図6に示されているように成功である。プログラムで指定されている「TestImg.bmp」という名前の画像ファイルをプログラムと同じフォルダに用意して、作成された実行形式ファイルを
./Check
と実行すると、図10のように画像ファイルが表示される。
図10
Enterキーを押すと、「cvWaitKey(0);」の実行終了となり、表示された画像は消えてプログラムの実行終了となる。
makefileの利用
makefileの基本構成要素は
ターゲット: 条件1 ・・・ 条件N
(タブ)コマンド
となっている。「ターゲット」が存在しない、あるいは「ターゲット」の作成時刻より新しい作成時刻をもつ「条件?」が存在するとき、「タブ」に続く「コマンド」が実行される。上のコマンド
g++ -o Check –I/usr/include/opencv2/highgui/ Check.cpp –lopencv_highgui –lopencv_core
を実行するmakefileは
============== makefile ========================
Check: Check.cpp
g++ -o Check –I/usr/include/opencv2/highgui/ Check.cpp –lopencv_highgui –lopencv_core
===========================================
と作成すればよい。このmakefileをプログラムと同じフォルダに置いておいて、コマンドmakeを
make
と実行すれば、実行形式のファイルCheckが存在しない、あるいはプログラムソースコードファイルCheck.cppの方が実行形式のファイルCheckより新しいとき、コマンド
g++ -o Check –I/usr/include/opencv2/highgui/ Check.cpp –lopencv_highgui –lopencv_core
が実行される(図11)。
図11
makefileを作成するときに、利用する可能性のあるヘッダーファイルのフォルダとライブラリをすべて列挙しておくと便利である。このとき、makefileの形式として
実行形式ファイル名: プログラミングで作成するファイル名の並び
g++ -o 実行形式ファイル名 ヘッダーファイルの存在する可能性のあるフォルダの指定の並び コンパイルの対象となる *.cpp ファイルの並び 使用する可能性のあるライブラリファイルの指定の並び
という形が簡単である。
まず、OpenCVのヘッダーファイルの存在するフォルダの場所を調べる。名前として「opencv*」( * は任意の文字列を表す)、場所として「/usr/include」を指定して検索すると図12の結果を得る。
図12
/usr/include/opencv/の中を見ると図13のように表示される。したがって、「-I/usr/include/opencv」と指定しておけばよいことがわかる。
図13
/usr/include/opencv2/の中は図14のようになっている。「-I/usr/include/opencv2/calib3d」・・・と指定しておく。
図14
ライブラリの方は、「libopencv_???.a」という形式の名前なので、名前欄は「*opencv*.a」を設定し、場所欄は「/usr/lib」を設定して検索すると、図15の結果を得る。
図15
ライブラリの検索場所としてシステムには「/usr/lib」が登録されており、またライブラリ名は先頭の「lib」と末尾の「.a」を除いた形で指定するので、「-lopencv_features2d」・・・などとオプションを追加しておく。
図11で用いられているmakefileを、他のOpenCVのプログラムのときに使用する可能性のあるヘッダーファイルのフォルダとライブラリを追加したものに拡張すると以下のようになる。
CheckAll: Check.cpp
g++ -o CheckAll -I/usr/include/opencv -I/usr/include/opencv2 -I/usr/include/opencv2/calib3d -I/usr/include/opencv2/contrib -I/usr/include/opencv2/core -I/usr/include/opencv2/features2d -I/usr/include/opencv2/flann -I/usr/include/opencv2/gpu -I/usr/include/opencv2/highgui/ -I/usr/include/opencv2/imgproc -I/usr/include/opencv2/legacy -I/usr/include/opencv2/ml -I/usr/include/opencv2/objdetect -I/usr/include/opencv2/video Check.cpp -lopencv_calib3d -lopencv_contrib -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_gpu -lopencv_highgui -lopencv_imgproc -lopencv_legacy -lopencv_ml -lopencv_objdetect -lopencv_video
上の内容をmakefileAllという名前のファイルとして保存したときは、makeコマンドは
make –f makefileAll
という形式で用いる(図16)。オプション「-f ファイル名」を付けると、「-f」に続くファイル名のファイルの内容がmakeによって実行される。単に「make」だけのコマンドのときは、makefileがmakeコマンドの対象となる。
図16
以上の解説におけるプログラムおよびmakefileは、圧縮ファイルDemoOpenCV.zipとして用意した。ダウンロード・解凍して自由に用いることができる。
上のmakefileの形式の説明おける「コンパイルの対象となる *.cpp ファイルの並び」は、複数のファイルがコンパイルの対象となる可能性を含んでいる。次に、複数のファイルで構成されたプログラムのビルドを行うmakefileの例を示す。
2つのWindowの提示とmakeファイルの使用例
リスト1のプログラムは単一のソースコードファイルから構成されている。複数のソースコードファイルを扱っている場合の例を、2つのWindowを提示するリスト2のプログラムで説明する。
=========== リスト2 ==============
#include <highgui_c.h>
#include "win_1.h"
#include "win_2.h"
int main(){
//
// The first window appears
//
show_win_1();
cvWaitKey(0);
//
// The second window appears
//
show_win_2();
cvWaitKey(0);
//
// The second window disappears
//
cvReleaseImage( &img_2 );
cvDestroyWindow( "TestImage_2" );
cvWaitKey(0);
//
// The first window disappears
//
cvReleaseImage( &img_1 );
cvDestroyWindow( "TestImage" );
return 0;
}
================================
リスト2のプログラムでは、最初のWindowを提示するソースコードファイルwin_1.cppと2番目のWindowsを提示するソースコードファイルwin_2.cppが別に用意されている。また、プログラム全体にわたって用いる変数を定義するためのソースコードファイルcommon.cppも用意されている。これらのファイルをそれぞれのヘッダーファイルとともに以下に示す。
=========== common.h ==================
#ifndef COMMON_CK
#define COMMON_CK
#include <highgui_c.h>
extern char * wnm_1, * wnm_2;
extern IplImage * img_1, * img_2;
#endif
====================================
=========== common.cpp =================
#include "common.h"
char * wnm_1, * wnm_2;
IplImage * img_1, * img_2;
====================================
=========== win_1.h ====================
#ifndef WIN_1_CK
#define WIN_1_CK
#include "common.h"
void show_win_1();
#endif
====================================
=========== win_1.cpp ===================
#include "win_1.h"
void show_win_1(){
img_1 = cvLoadImage( "TestImg.bmp" );
cvNamedWindow( "TestImage", CV_WINDOW_AUTOSIZE );
cvShowImage( "TestImage", img_1 );
cvMoveWindow( "TestImage", 100, 50 );
}
====================================
========== win_2.h =====================
#ifndef WIN_2_CK
#define WIN_2_CK
#include "common.h"
void show_win_2();
#endif
====================================
========== win_2.cpp ====================
#include "win_2.h"
void show_win_2(){
img_2 = cvLoadImage( "TestImg_2.png" );
cvNamedWindow( "TestImage_2", CV_WINDOW_AUTOSIZE );
cvShowImage( "TestImage_2", img_2 );
cvMoveWindow( "TestImage_2", 150, 100 );
}
====================================
上のプログラムをビルドするmakefileを以下のように用意した(makefileの形式およびおよびg++(-Iオプションと-lオプションについての説明参照)。
check: Check_1_2.cpp common.h common.cpp win_1.h win_1.cpp win_2.h win_2.cpp
g++ -o check -I/usr/include/opencv -I/usr/include/opencv2 -I/usr/include/opencv2/calib3d -I/usr/include/opencv2/contrib -I/usr/include/opencv2/core -I/usr/include/opencv2/features2d -I/usr/include/opencv2/flann -I/usr/include/opencv2/gpu -I/usr/include/opencv2/highgui/ -I/usr/include/opencv2/imgproc -I/usr/include/opencv2/legacy -I/usr/include/opencv2/ml -I/usr/include/opencv2/objdetect -I/usr/include/opencv2/video Check_1_2.cpp common.cpp win_1.cpp win_2.cpp -lopencv_calib3d -lopencv_contrib -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_gpu -lopencv_highgui -lopencv_imgproc -lopencv_legacy -lopencv_ml -lopencv_objdetect -lopencv_video
makeコマンドによる実行例を図17に示す。
図17
Windowに表示される2枚の画像のファイルをプログラムと同じフォルダに用意した後、プログラムを
./check
と実行すると、まず1番目のWindowが表示される(図18)。
図18
Enterキーを押すと2番目のWindowが表示される(図19)。
図19
さらにEnterキーを押すと、2番目のWindowが消える(図20)。
図20
次のEnterキーの押下で、1番目のWindowも消えて、プログラムの実行終了となる。
上のmakefileの例のように、複数のソースコードファイルを扱うビルドになるとmakefileにおいて指定するファイル名が増えてくる。また、「/usr/include/opencv2/」のように同じ文字列が何回も使われている。これらをマクロを使って書き直すと以下のようになる(ファイルmakefileMacroとして作成した)。
OCV_I = /usr/include/opencv2
FILES_H = common.h win_1.h win_2.h
FILES_CPP = Check_1_2.cpp common.cpp win_1.cpp win_2.cpp
check: $(FILES_CPP) $(FILES_H)
g++ -o check -I/usr/include/opencv -I$(OCV_I) -I$(OCV_I)/calib3d -I$(OCV_I)/contrib -I$(OCV_I)/core -I$(OCV_I)/features2d -I$(OCV_I)/flann -I$(OCV_I)/gpu -I$(OCV_I)/highgui/ -I$(OCV_I)/imgproc -I$(OCV_I)/legacy -I$(OCV_I)/ml -I$(OCV_I)/objdetect -I$(OCV_I)/video $(FILES_CPP) -lopencv_calib3d -lopencv_contrib -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_gpu -lopencv_highgui -lopencv_imgproc -lopencv_legacy -lopencv_ml -lopencv_objdetect -lopencv_video
上のmakefileMacroを使用するmakeコマンドの実行は、オプション「-f」を付けて
make –f makefileMacro
となる。実行例を図21に示す。
図21
マクロOCV_I、FILES_H、FILES_CPPがmakeコマンドの実行時にその値である文字列に置き換わっていることが分かる。ファイルmakefileMacroは、マクロFILES_HおよびFILES_CPPに適切なヘッダーファイル名のリストおよびソースコードファイル名のリストを並べることにより、他のプログラムに対して同じように使用することができる。ファイルmakefileMacroおよびプログラムファイルは圧縮ファイルDemoOpenCV_1_2.zipにまとめた。ダウンロード・解凍して自由に用いることができる。
上の説明はubuntu 12.04 LTS での作業に基づいたものである。Fedora 19において、上記の圧縮ファイルDemoOpenCV_1_2.zipをダウンロードして解凍後、makeコマンドを実行すると図22のエラーが出た。
図22
これは、上のubuntu 12.04 LTSでは、OpenCV-2.3がインストールされているが、fedora 19ではOpenCV-2.4.5-1がインストールされるためである(2013.7.6)。エラーメッセージに合わせてmakefileを図23のように変更する。
図23
すなわち、「-lopencv_gpu」の部分を削除する。削除・保存した後、makeコマンドを実行すると図24に示すように成功する。
図24
「make」コマンドによって「g++ -o check ・・・」と「g++」コマンドが実行されているので、作成された実行形式のファイルcheckを
./check
と実行すると、図18のようにウィンドウが表示される。
openSUSE 13.2 において、以下のようにサンプルプログラムDemoOpenCV_1_2.zipをダウンロードして実行した。makefileはそのまま使用できた。
まず、g++、OpenCV、makeがインストールされていないときは、これらをインストールするが、これは以下のように簡単にできる。
g++ のインストールはこのサイトでも説明しているが、以下のようである。
「YaST2 モジュ…」を選ぶ(図S1)。
図S1
「YaST2 モジュ…」から「ソフトウェア管理」を選ぶ(図S2)。
図S2
表示される「YaST2」ウィンドウにおいて、検索語として「gcc-c++」を設定して、「検索」ボタンをクリックする(図S3)。
図S3
右側のペインに表示される「gcc-c++」の項目にチェックを付けて「了解」ボタンをクリックする(図S4)。
図S4
「変更されたパッケージ」ウィンドウが表示される(図S5)。
図S5
「続行」ボタンをクリックして続行する。
次に「OpenCV」を同様の手順でインストールする。
「YaST2」ウィンドウを表示させて、検索語に「opencv」と設定して「検索」ボタンをクリックすると、関係するパッケージが右側に表示される(図S6)。
図S6
候補のパッケージの数が多くないので、すべてにチェックを入れて「了解」ボタンをクリックする(図S7)。
図S7
図S8のウィンドウが表示されるので、「続行」ボタンをクリックして続行する。
図S8
make のインストールのときは、多くのパッケージが表示されるので、「make」だけを選んでチェックを付けて「了解」ボタンをクリックし、インストールする(図S9)。
図S9
以上の準備の後、サンプルプログラムの圧縮ファイルDemoOpenCV_1_2.zipをダウンロードする。
ダウンロードした圧縮ファイル名をマウスの右ボタンでクリックして表示されるメニュから「ここに展開する」を選んで展開する。
図S10
図S11のようにフォルダが作成されて、その中にファイルが展開される。
図S11
ターミナルを起動して、展開して作成されたフォルダに移り、make を実行する(図S13)。
図S12
make の実行によって g++ が呼び出され、「-o check」の指定によって、ビルドによって実行形式のファイル check が作成される(図S13)。
図S13
「./check」と入力して実行すると、プログラムが実行されて図S14のようにウィンドウが表示される。
図S14
これは、図18と同じ状態である。Enterキーを押すと2枚目のウィンドウが表示され、次のEnterキーの押下で2枚目のウィンドウが消える。3回目のEnterキーの押下でプログラムは終了する。