プログラム要求仕様

概要

本アルゴリズムコンテストでは、配布しているプログラム中の"my_tracking.c"内の関数my_tracking_level1( )、my_tracking_level2( )、my_tracking_level3( )のいずれかに独自のアルゴリズムを実装し、提出していただきます。
C言語(ANSI C)もしくはC++言語(ANSI/ISO C++)での実装が可能です。 C++言語を利用する場合は、"my_tracking.c"の拡張子を「.cpp」に変更して"my_tracking.cpp"としてご利用ください。
本年度のアルゴリズムコンテストでは、STL、OpenCVMIST(Media Integration Standard Toolkit)のライブラリを利用することが可能です。 各ライブラリで使用可能なバージョンに関しては FAQ をご覧ください。 これら以外のライブラリの利用に関しては、alcon2010@murase.m.is.nagoya-u.ac.jpまで個別に相談して下さい。
応募者が実装する関数my_tracking_level1( )、my_tracking_level2( )、my_tracking_level3( )のプロトタイプ宣言(alcon2010.h内に記述)は以下のようになっています。
void my_tracking_level1( int frameID, unsigned char *image,
                         int width, int height, const bounding_box *box0 );
void my_tracking_level2( int frameID, unsigned char *image, int width, int height );
void my_tracking_level3( int frameID, unsigned char *image, int width, int height );
frameIDは動画中のフレーム番号、imageはframeIDに対応する動画中の画像へのポインタ、width と height は対象画像の幅と高さになります。 これらの入力を用いて移動物体がどこにあるかを発見・追跡します。 ただし、レベル1に関しては初期フレーム(frameID=0)における移動物体を囲む矩形情報がbox0として与えられます。 関数の入力、結果の出力方法に関しては以下で詳しく説明します。

入力に関する仕様

応募者に実装していただく関数の引数は、
  • unsigned char *image(対象画像)
  • int width(対象画像の幅)
  • int height(対象画像の高さ)
  • const bounding_box *box0(初期フレームにおける移動物体を囲む矩形、レベル1のみ)
の3つ(レベル1のみ4つ)となります。 結果の出力方法は後で詳しく説明します。 対象画像はwidth×height×3の長さを持つunsigned char型の配列として確保されて関数に渡されます。 画素は左上から右下への順(通常のラスタスキャンの順)で並んでおり、各画素のRGB値がこの順番で格納されています。 この並びの様子を下図に示します。
画像における軸の定義
このような並びの画像中の座標(x, y)のRGB値は、以下のようにして取り出すことができます。
Rxy = image[ ( x + y * width ) * 3 + 0 ];
Gxy = image[ ( x + y * width ) * 3 + 1 ];
Bxy = image[ ( x + y * width ) * 3 + 2 ];
任意の位置の画素値(RGB値)を取り出す場合は、上述のようにしてアクセスしてください。
また、レベル1では、動画中の各フレーム以外に、初期フレーム(frameID=0)における移動物体を囲む矩形情報がbox0として与えられます。 初期フレームのみ別処理を行う場合は、frameIDの値をご利用ください。

出力に関する仕様

実装した関数では、動画像中の各フレームにおける移動物体を囲む矩形を計算することになります。 ここで、矩形情報にはbounding_boxという構造体を利用します。 この構造体は、
typedef struct
{
	int x;	/* 左上のX座標 */
	int y;	/* 左上のY座標 */
	int w;	/* 矩形の幅    */
	int h;	/* 矩形の高さ  */
} bounding_box;
と定義されており、矩形の左上のX座標(x)、左上のY座標(y)、矩形の幅(w)、矩形の高さ(h)、の4つの変数から構成されています。 この構造体bounding_boxは、アルゴリズムの出力(レベル1では初期矩形としても利用)として利用し、以下で述べる方法で結果の出力を行う際に利用します。
応募者が実装するアルゴリズムでは、set_result関数を利用して移動物体を囲む矩形を出力します。 この関数は、
int set_result( int frameID, bounding_box box );
と定義されており、フレーム番号(frameID)と移動物体を囲む矩形(box)の組を引数とします。 各自で実装した移動物体追跡アルゴリズムの出力には、必ずこの関数を利用するようにしてください。 また、この関数は0~100の間のframeIDに対して任意のタイミングで結果を設定できます。 よって、最後までフレームを読み込んでから全ての結果を一度に登録することも可能となっています。

サンプルプログラムおよびデータ

レベル1のアルゴリズムを実装したサンプルプログラムおよび各レベルの入力動画像(フレームシーケンス)はダウンロードのページから入手することができます。 以降を読み進める前に、各自の環境用のサンプルプログラムをダウンロードしておいてください。 プログラムに関する質問やバグ等は、alcon2010@murase.m.is.nagoya-u.ac.jpまでお知らせください。

データ

本コンテストで提供するプログラムの実行には、ダウンロードのページから入手できるデータが必要となります。 このデータはレベルに応じて複数のデータセットが用意されており、各セットは動画像をフレームに分割した画像群(000.bmp~100.bmp)と各フレームにおける移動物体を囲む正解矩形情報を保存した「groundtruth.txt」というファイルからなります。 これらのファイルは全て同じディレクトリ内に保存するようにしてください(別々のディレクトリに保存した場合はプログラムが実行できません)。 また、各フレーム画像は24ビットのビットマップ画像となっています。

コンパイルと実行

サンプルプログラムを任意の場所に展開し、展開したディレクトリ内で make コマンドを実行します。
# make
成功すると、alcon2010 という実行ファイルが生成されます。プログラムのコマンドライン引数は以下の通りです。
# ./alcon2010 -level {1|2|3} [オプション] "画像群を保存したフォルダのパス"
オプションとしては、
-level
実行するレベルを指定(1~3、省略した場合は1)
-start
処理を開始するフレーム番号(デフォルトは0)
-end
処理を終了するフレーム番号(デフォルトは100)
-odir
追跡結果の各フレームを出力するディレクトリのパス
-verbose
詳細な処理情報を標準出力に表示
実装したアルゴリズムの結果を動画の各フレームに描画したものを出力する場合は「-odir」オプションを指定してください。
例えば、レベル2のアルゴリズムを"/data/set1"以下に保存したデータに適用し、結果の画像を "/tmp/res1"以下に出力する場合は、
# ./alcon2010 -level 2 -odir /tmp/res1 /data/set1
のように指定します。
プログラムを実行すると、次のような結果が出力されます。
追跡精度: 97.0 %, 計算時間: 0.653 sec.
追跡成功(重なり率>=70%): 100 % ( 100 / 100 )
コマンドプロンプトに表示される追跡精度と計算時間がコンテストの審査指標となります。 2行目に表示されている追跡成功は、重なり率が70%以上の矩形の割合を表しています。 審査には使用しませんが、どの程度プログラムが正しく動作しているかを計る指標としてご利用ください 。

Cygwin環境でのコンパイル

Cygwinのインストーラを利用してGCCをインストールした場合、バージョンが3.xのgccがインストールされます。 Cygwin環境でインストールされるバージョン3.xのgccでは「std::wstring」をサポートしていないため、このままではダウンロードにて配布しているサンプルをコンパイルすることができません。 Cygwinを利用して開発を行う場合は以下のどちらかの方法をお試しください。
※他のLinux環境でインストールされるgccには、このような問題は存在しないようです。
  1. Cygwinのインストーラを利用してgcc4のパッケージを追加する
    この方法をお勧めします。 この方法を行うとgccがgcc4を指すように変更されるため、「Makefile」等を変更することなくサンプルがコンパイルできるようになります。 ただし、gccのバージョン4を使えない環境の場合は2番目の方法をお試しください。
  2. ダウンロードから入手したサンプルを書き換える
    配布しているサンプル中の「main.cpp」を適当なエディタで開き、先頭部分を以下のように書き換えてください。 ただし、1番目の方法を行った場合は、以下の変更を行う必要はありません。
    #include <iostream>
    #include <string>
    #include <stdio.h>
    
    // ↓の3行をここに追加する
    namespace std
    {
        typedef basic_string< wchar_t > wstring;
    }
    
    // MISTのメインヘッダファイル
    #include <mist/mist.h>
    

MinGW環境でのコンパイル

MinGWでサンプルプログラムをコンパイルする場合、下記のようなリンクエラーが発生する可能性があります。
./mist/timer.h:45: warning: ignoring #pragma comment
Compiling my_tracking.c...
main.o:main.cpp:(.text+0x398d): undefined reference to `timeGetTime@0’
main.o:main.cpp:(.text+0x3b32): undefined reference to `timeGetTime@0’
main.o:main.cpp:(.text+0x3c5d): undefined reference to `timeGetTime@0’
...
collect2: ld returned 1 exit status
make: *** [alcon2010] エラー 1
この問題を解決するためには、サンプルプログラムに含まれる Makefile 内の LIBS に -lwinmm を追加してください。
CC  = gcc
CXX = gcc

INCLUDE  = -I.
LDLIBS   = 
LIBS     = -lstdc++ -lwinmm

サンプルプログラム

サンプルプログラムにはLevel1のアルゴリズムが実装されています。 このアルゴリズムは、初期フレームにおける移動物体を囲む矩形情報を基に参照画像を切り出し、以降のフレームはこの参照画像とのテンプレートマッチングを行うことで移動物体を追跡しています。 また、計算コストの削減のため、テンプレートマッチングの計算範囲をSEARCH_RANGEの範囲に制限しています。
具体的には、まず初期フレーム(frameID=0)から参照画像を切り出します。
if( frameID == 0 )
{
	/* 最初のフレームは追跡開始位置を記憶する */
	obox = *box0;
	・・・
}
そして、frameID>0に対して参照画像との各画素の2乗誤差を求め、その値が最小となる矩形を求めます。
for( n = 0 ; n < obox.h ; n++ )
{
	for( m = 0 ; m < obox.w ; m++ )
	{
		…
	}
}

if( err < merr )
{
	i0   = i;
	j0   = j;
	merr = err;
}
最後に、求めた矩形情報をset_result関数を用いて出力しています。
/* 移動物体を囲む矩形を設定 */
set_result( frameID, obox );
以上がサンプルプログラムが実装しているアルゴリズムの簡単な説明になります。

その他の関数

配布しているサンプルプログラムでは、必要に応じて以下の4つの関数を利用することができます。
/* 指定したフレームにおける移動物体を囲む矩形データを設定する */
int set_result( int frameID, bounding_box box );

/* 指定したフレームにおける移動物体を囲む矩形データを取得する */
int get_result( int frameID, bounding_box *box );

/* 画像をビットマップ形式で保存する関数 */
/* 保存に失敗すると 0 を返し,成功すると 1 を返す */
int save_bmp( const char *filename, unsigned char *image, int width, int height );

/* 矩形同士の重なり率を計算する関数 */
double overlap_ratio( const bounding_box *b1, const bounding_box *b2 );
set_result は frameID に対応する出力矩形を設定する関数であり、get_result は frameID に設定した出力矩形を取得する関数です。
また、関数の実行中に処理途中の画像を保存したい場合は、save_bmp 関数を利用することができます。 この関数は、ファイル名(filename)、画像へのポインタ(image)、画像の幅(width)、画像の高さ(height)、を引数とします。
最後に、overlap_ratio は矩形同士の重なり率を計算する関数であり、プログラムの精度評価に利用しています。

正解ファイルのフォーマット

正解ファイル「groundtruth.txt」のフォーマットは以下の通りです。 独自のテストデータを用意する場合の参考にしてみてください。
000,x0,y0,w0,h0
001,x1,y1,w1,h1

…

100,x100,y100,w100,h100
ファイルの各行は、左からフレーム番号、矩形のx座標、y座標、幅、高さ、の順に並んでいます。 このデータが、動画のフレーム順に000~100まで並んだものになります。
x0
フレーム0における移動物体の最小矩形の左上のx座標
y0
フレーム0における移動物体の最小矩形の左上のy座標
w0
フレーム0における移動物体の最小矩形の幅
h0
フレーム0における移動物体の最小矩形の高さ

MISTバージョン

MIST(Media Integration Standard Toolkit)は、音声と画像のメディア統合の支援を目的に開発されているライブラリです。 今年度のアルゴリズムコンテストでは、MISTを利用したサンプルプログラムをダウンロードのページで提供しています。 MISTを利用することで、今まで面倒だった画像処理の煩雑な処理を簡単な記述できるようになります。 ぜひ、この機会にMISTをお試しください。 以下では、MISTを利用したサンプルを読み進める上のヒントをいくつか紹介します。 MISTのより詳しい説明に関しては、MISTのホームページをご覧ください。 サンプルプログラムに関する質問やバグ等は、alcon2010@murase.m.is.nagoya-u.ac.jpまでお知らせください。

画像の確保

MISTはC++のテンプレート機能を利用したテンプレートライブラリです。 MISTを利用して画像を確保するためには、画像内の各画素がどのような表現になっているかをまず決める必要があります。 例えば、各画素がRGBからなり、RGBそれぞれが1バイトで表現される場合は
mist::rgb< unsigned char >
という画素クラスを利用します。 この画素クラスを利用して、2次元画像を確保する場合は次の様に記述します。
mist::array2< mist::rgb< unsigned char > > img( 幅, 高さ );
このように画像を確保した場合は、幅×高さの画像用メモリが自動的に確保されます。
一方、サンプルプログラムでは別途確保されたメモリ領域をMISTの画像オブジェクトに割り当てるため、
// 別メモリ領域に確保した画像データをMISTの画像コンテナにマッピングする
// 第1引数:画像の幅
// 第2引数:画像の高さ
// 第3引数:メモリ領域を指すポインタ
// 第4引数:メモリ領域のサイズ
image_type img( width, height, ( pixel_type * )image, width * height * 3 );
という記述をしています。 外部メモリを利用することを除けば、どちらの方法で画像を確保しても同じようにMISTのアルゴリズムを適用できます。

画素へのアクセス

MISTで確保した画像の各画素へのアクセスは次の様にして行うことができます。
img( X座標, Y座標 );
ここで、img の各画素が mist::rgb< unsigned char > の場合は、次の様にして各画素のRGB値を取得できます。
mist::rgb< unsigned char > &pix = img( X座標, Y座標 );
unsigned char R = pix.r;  // R成分
unsigned char G = pix.g;  // G成分
unsigned char B = pix.b;  // B成分
値の取得と同様、各画素に値を設定する場合は次の様にします。
mist::rgb< unsigned char > &pix = img( X座標, Y座標 );
pix.r = R;  // R成分
pix.g = G;  // G成分
pix.b = B;  // B成分
※画素 pix が C++ の参照になっている点に注意してください。

画像サイズの取得

MISTの画像コンテナは、画像の幅や高さの情報を内部で保持しています。 これらの情報を利用したい場合は、次のメンバ関数を呼び出してください。
size_t w = img.width( );   // 画像の幅を取得
size_t h = img.height( );  // 画像の高さを取得
size_t s = img.size( );    // 画像の画素数を取得

その他の情報

上で説明したもの以外にも、MISTには便利な機能が数多く実装されています。 一度、MISTのチュートリアルにトライしてみてください。 また、より詳しい使い方に関しては、MISTのドキュメントをご覧ください。
昨日: / 今日: / 合計: