• 検索結果がありません。

2 2 2 OpenGL Linux Linux Video for Linux(Video4Linux, v4l ) API Video4Linux USB IEEE1394 API Linux Video for Linux 2(Video4Linux2, v4l2 ) OpenCV API U

N/A
N/A
Protected

Academic year: 2021

シェア "2 2 2 OpenGL Linux Linux Video for Linux(Video4Linux, v4l ) API Video4Linux USB IEEE1394 API Linux Video for Linux 2(Video4Linux2, v4l2 ) OpenCV API U"

Copied!
24
0
0

読み込み中.... (全文を見る)

全文

(1)

1

平成

26

年度 機械情報工学科演習

コンピュータグラフィクス

(2)

動画やカメラを用いた

3DCG

の応用

担当:谷川 智洋 講師,鳴海 拓志 助教,中垣 好之 技官

TA

: 岡田 直弥,川瀬 佑司

2014

10

17

1

演習の目的

本日の演習では,前回学習したOpenGLの基礎を元に,USBカメラから取り込んだ動画を三次元コン ピュータグラフィックス(3DCG)に貼り込む演習を通して,OpenCVとの連携も学習する.また,CGとカ

メラ画像の連携によるAugmented Realityについてもふれ,ARToolKitを利用したプログラムの演習を通し

て3DCGへの理解を深める.

1.1

資料など

本日の演習の資料などは,   http://www.cyber.t.u-tokyo.ac.jp/~tani/class/mech_enshu/   においてある.本日使用するソースファイルも同じ場所からダウンロードすること.前回の資料を参照したい 場合も同じ場所を参照のこと.

1.2

出席・課題の確認について

出席の確認は,課題の確認によって行う.課題が終了したら,教員・TAを呼び,指示に従って実行して説 明せよ.

1.3

貸出機材について

(

重要

)

USB カメラは,「リアルワールド認識」(2014/11/10(月),11(火),13(木))「メディアインタフェース」 (2012/11/17(月), 18(火))でも使用するので,忘れずに持参すること. また,「ロボットシミュレーション」において貸出を行うBluetoothUSBアダプタは,「メディアイン タフェース(2)」(2012/11/18(火))で使用するので,忘れずに持参すること.

(2)

2

動画の取り扱い

前回の学習した画像の取り扱いを一歩進んで,OpenGLを用いて動画を取り扱うことについて説明する.

Linuxにおけるカメラ

Linuxにおいて,動画を利用するためには,Video for Linux(Video4Linux, v4lと略される)と呼ばれるカメ

ラデバイスを使うためのAPI仕様を利用する.Video4Linuxを用いることにより,USBカメラ,IEEE1394

カメラなどから画像を読み込むことができるとともに,ビデオキャプチャボードからの読み込みもできる.ま

た,チューナー操作のためのAPI仕様などもそろっている.最近のLinuxのカーネルでは,Video for Linux

2(Video4Linux2, v4l2と略される)が組み込まれており,OpenCVでもこのAPI仕様に基づいてキャプチャ を行っている.

なお,現在はUSBでカメラを扱う規格(USB Video Class, UVC)がUSB 2.0の規格の拡張として策定さ

れており,この規格に準拠するカメラは一つのドライバで扱えるようになりつつある.本演習で配布してい るカメラもこの規格に準拠しており,Linuxに用意されている共通ドライバで扱うことができる.Linuxの カーネルにVideo4Linuxのドライバがインストールされており,かつ,ビデオキャプチャ用のドライバ(モ ジュール)が正しくロードされていた場合,lsmodとコマンドで打ち込んだとき下記の様にロードされている ことが確認できるはずである.   uvcvideo 51204 0 compat_ioctl32 5569 1 uvcvideo videodev 30785 1 uvcvideo v4l1_compat 17349 2 uvcvideo,videodev v4l2_common 20801 2 uvcvideo,videodev  

2.1

動画を利用するプログラム

OpenCVについて 動画ファイルやカメラの利用は,Video4LinuxなどのAPIを利用しても,様々なパラメータの設定や読み

出しのための手順が不可欠である.OpenCV(Open Source Computer Vision Library)を利用することで,

複雑になりがちな動画の読み込みや動画像処理のプログラムの読みやすさや再利用性を向上させることがで きる.また,OpenCVはOpenGLと同様にマルチプラットフォームなライブラリであり,どのようなオペ レーティングシステムの上でも動作することを目指している.カメラを扱う場合でも,Video4Linuxのよう なAPIを利用すると,OSによって用意されている関数が異なるため,実行したい環境が変わるとプログラム を書き直す必要がある.OpenCVはOSの違いを吸収し,対応する全てのOSの上で同じ関数を用いて,動 画を取り扱うことが可能である. OpenCVとOpenGLは,それぞれ画像処理と3DCGのライブラリであり,連携することで3DCGの手法 でカメラ画像や動画ファイルを取り扱うことができる.本演習では,OpenCVでカメラ画像から取得したフ レーム画像をテクスチャとして貼り付け,ポリゴンとして自由に操作することを可能にすることを目指す. なお,OpenCVの各種情報はhttp://opencv.jp/を見るとよい.http://opencv.jp/sample/サンプルプロ

(3)

2.1 動画を利用するプログラム 3

グラムが数多く載っている.

OpenCVにおける画像データ

OpenCVの画像データの基本的な構造体はIplImage構造体になり,OpenCVではこの構造体を各種関数 の引数として渡している.既に何度か説明しているように,コンピュータ上での画像の取り扱いは,画像を 微小長方形領域(ピクセル=画素という)に分割し,そのピクセル単位で処理を行う.現在,カメラ映像は 640*480のカラーピクセルの集合となっている場合が多く,配布しているカメラも同様である.カラー画像 の場合は,各画素には3つの値がデジタルデータとして入力され,三原色の赤緑青のRGBがそれぞれ8bit の値をとる.RGBの三原色をコンピュータのメモリにどのように格納するかにはさまざまな方法があるが, OpenCVの場合,始めのバイトが左上角のB,次が左上角のG,その次が左上角のRで,さらにその次が一 つ右隣のB,それから一つ右隣のG,一つ右隣のRというように格納されている.この場合3バイトごとに 1画素ずつが相当することになる. nSize IplImage構造体のサイズ nChannels チャンネル数 1,2,3,4のどれか depth 1画素あたりのビット数 origin 画像データの原点(基準) width 画像の幅(画素数) height 画像の高さ(画素数)

imageSize 画像データのサイズ(バイト数) (= widthStep * height)

imageData 画像データへのポインタ

widthStep 画像データの幅のバイト数(画素数ではない)

表1 IplImage構造体の主なメンバ変数

画像データをファイルから確保する場合は,cvLoadImage関数を呼ぶ.

 

IplImage* cvLoadImage( const char* filename, int flags=CV_LOAD_IMAGE_COLOR );

filename 読み込むファイル名. flags 読み込む画像がカラー/グレースケールのどちらか,とデプスを指定する.   画像を取り扱う構造体を新規に確保する場合は,cvCreateImage関数をよぶ.例えば,一般的によく使われ るRGB各8ビット,各画素24ビットの画像を取り扱う場合は,depthに符号無し8ビット整数を意味する

(4)

  IplImage* cvCreateImage( CvSize size, int depth, int channels );

size 画像の幅と高さ. depth 画像要素のビットデプス.以下の内のいずれか. IPL_DEPTH_8U - 符号無し 8 ビット整数 IPL_DEPTH_8S - 符号有り 8 ビット整数 IPL_DEPTH_16U - 符号無し 16 ビット整数 IPL_DEPTH_16S - 符号有り 16 ビット整数 IPL_DEPTH_32S - 符号有り 32 ビット整数 IPL_DEPTH_32F - 単精度浮動小数点数 IPL_DEPTH_64F - 倍精度浮動小数点数 channels 要素(ピクセル)毎のチャンネル数.1, 2, 3, 4 のいずれか.   また,プログラム終了時や対象とする構造体が不要になった場合は,cvReleaseImage関数をよぶことで必 ず解放する.  

void cvReleaseImage( IplImage** image );

image

確保した画像ヘッダへのポインタのポインタ.

 

なお,OpenGL では,左下角から,R,G,Bの順番に格納された画像データを前提としているため,

OpenCVで読み込んだ画像データをOpenGL使用する場合,OpenCV側で格納の順番を変換する処理を行 うか,OpenGLの関数引数の設定(GL BGR EXTやGL BGRAなど)や座標の変換による処理が必要に なる.OpenCV側で行う場合,cvCvtColor()関数の引数にCV BGR2RGBを指定することで,BGRから

RGBの順に配列を変換することができる.

 

void cvCvtColor( const CvArr* src, CvArr* dst, int code );

src 入力画像,8ビット(8u),16ビット(16u),あるいは単精度浮動小数点型(32f). dst 出力画像,入力画像と同じデータタイプ.チャンネル数は違うこともある. code CV_<src_color_space>2<dst_color_space> の定数を用いて色空間の変換を指定  

(5)

2.1 動画を利用するプログラム 5 カメラからのキャプチャ準備 OpenCVで動画像を扱うプログラムを記述する際には,準備のためにCvCapture構造体を初期化する必要 がある. カメラから動画を入力する場合,初期化は下記のように行う.cvCreateCameraCapture() はOpenCV内 でのキャプチャデバイスとしてのカメラを初期化する関数で,引数はカメラのインデックスを表している.カ メラが複数ある場合はこの引数を変えて指定する.0を指定した場合は自動で使用可能なカメラを判断する.

なお,接続可能なデバイスがない場合cvCreateCameraCapture()はNULLを返す.なお,OpenCVのサン

プルプログラムにはcvCaptureFromCAM()が用いられている場合もあるが,cvCreateCameraCapture()と

等価である.

 

CvCapture* cvCreateCameraCapture( int index );

index 使われるカメラのインデックス. 使用するカメラが1台のときか,何台のカメラを使うかが重要でないときは, -1でも問題ない場合もある.   また,動画ファイルから入力する場合は,初期化においてcvCreateCameraCapture()のかわりに cvCre-ateFileCapture()を呼び出す.プログラムの他の部分はそのままで,カメラ入力処理のプログラムを動画ファ イルから画像を読み込んで処理するプログラムとすることができる.  

CvCapture* cvCreateFileCapture( const char* filename );

filename ビデオファイル名.   関数cvSetCaptureProperty()により,ビデオキャプチャ構造体のプロパティをセットすることができる. 例えば,下記の様にすることによりキャプチャをおこなう際の画面サイズ(幅と高さ)を指定することができ る.ただし,実際のカメラがサポートしていないキャプチャサイズは指定できない.  

int cvSetCaptureProperty( CvCapture* capture, int property_id, double value ); capture: ビデオキャプチャ構造体. property_id プロパティID.  

(6)

同様に,関数cvGetCaptureProperty()により,ビデオキャプチャ構造体のプロパティを取得することがで きる.カメラのキャプチャ画面のサイズ(幅と高さ)を取得することができる.ただし,正しい値を取得する には,cvQueryFrame() などで一度画像を取得しておく必要がある.

 

double cvGetCaptureProperty( CvCapture* capture, int property_id );

capture ビデオキャプチャ構造体. property_id プロパティID.   なお,引数として与えられるプロパティIDは以下の通り.

CV CAP PROP POS MSEC ファイル中の現在の位置(ミリ秒単位)

CV CAP PROP POS FRAMES 次にデコード/キャプチャされるフレームのインデックス.

CV CAP PROP POS AVI RATIO ビデオファイル内の相対的な位置

CV CAP PROP FRAME WIDTH ビデオストリーム中のフレームの幅

CV CAP PROP FRAME HEIGHT ビデオストリーム中のフレームの高さ

CV CAP PROP FPS フレームレート

CV CAP PROP FOURCC コーデックを表す4文字

CV CAP PROP FRAME COUNT ビデオファイル中のフレーム数

表2 ビデオキャプチャ構造体のプロパティID キャプチャ処理 カメラやビデオファイルから1つのフレームを取り出して返す場合は,キャプチャデバイス(前項で取得し たCvCapture構造体)が有効な間,カメラや動画ファイルからフレーム(1枚の画像)を取り込むことがで きる.この処理にはcvQueryFrame() を呼び出す.この関数が呼び出されるとカメラ又はAVIファイルから 画像が1 枚取り込まれ,IplImage構造体へのポインタが返される.ここで返ってくる画像(IplImage 構造 体)はデバイスの初期化関数の内部で確保されているので,プログラムの途中で解放してはいけない.また, この返り値がNULLの場合,対象となるカメラと切断されたかファイルの最後まで処理されたことになるの で,終了処理を行う必要がある.  

IplImage* cvQueryFrame( CvCapture* capture );

capture

ビデオキャプチャ構造体.

(7)

2.2 簡単な例 7

キャプチャの終了処理

cvCreateCameraCapture(),又はcvCreateFileCapture()で取得したキャプチャデバイスは,デバイス使

用終了時(典型的にはプログラム終了時)にcvReleaseCapture()を呼びだして解放する必要がある.

 

void cvReleaseCapture( CvCapture** capture );

capture ビデオキャプチャ構造体へのポインタ.  

2.2

簡単な例

キャプチャをしたデータを表示すると,下記のようにWindow内に表示することが可能となる(図1). 図1 動画読み込みと描画 カメラキャプチャの初期化と解放 以下に,OpenGLでキャプチャ画像を表示する場合の,OpenCVによるキャプチャデバイスの初期化と解 放の例を示す. /* OpenGL */ #include <GL/glut.h> /* OpenCV */ #include <opencv/cv.h> #include <opencv/highgui.h>

(8)

IplImage *frame; /* Capture Imege from OpenCV */ CvCapture* capture = 0; /* Video Capture Structure */ int dev_index = 0; /* Capture Device ID */

void my_init(int argc, char **argv) {

// Initialization Part - OpenCV // Connect to Capture Device

capture = cvCreateCameraCapture(dev_index); if (capture) { frame = cvQueryFrame(capture); cap_width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH); cap_height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT); } else {

fprintf(stderr, "Found No Camera\n"); exit(-1);

}

// Flip Captured Image if (frame->origin==0) {

cvFlip(frame, frame, 0); }

// Convert Color Alignment BGR -> RGB cvCvtColor(frame, frame, CV_BGR2RGB); win_width = cap_width; win_height = cap_height; } int my_exit(int e) {

/* Release Process - OpenCV */

if (capture) cvReleaseCapture(&capture);

exit(e); }

(9)

2.2 簡単な例 9

カメラ画像の取得

カメラからの画像の更新は,idle関数内においてcvQueryFrame()を呼び出すことで行う.また,OpenGL

で扱うために画像の上下反転処理をcvFlip(),BGRからRGB配列への変換処理をcvCvtColor()で行って いる. void idle(void) { if (capture) { frame = cvQueryFrame(capture); if (frame->origin==0) { cvFlip(frame, frame, 0 ); } cvCvtColor(frame, frame, CV_BGR2RGB); } glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glutPostRedisplay(); } 本演習ではキャプチャデバイスから取得したIplImage構造体の画像データを直接表示している.実際に画 像処理をした画像を表示する場合は,cvCloneImage()などで確保した構造体に処理結果を格納した上で,そ の画像データの表示を行う.  

IplImage* cvCloneImage( const IplImage* image );

image オリジナル画像.   読み込んだ動画の描画 「コンピュータグラフィックス」で学習したglDrawPixels()を呼び出して,キャプチャした画像を表示する ことができる.  

void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);

void glRasterPos{234}{sifd}(TYPE x, TYPE y, TYPE z, TYPE w);

(10)

void display(void) { glClear(GL_COLOR_BUFFER_BIT); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelZoom((GLdouble)(win_width-2)/(GLdouble)cap_width, (GLdouble)(win_height-2)/(GLdouble)cap_height); glRasterPos2i(-win_width/2+1, -win_height/2+1);

glDrawPixels(cap_width, cap_height, GL_RGB, GL_UNSIGNED_BYTE, frame->imageData); glFlush(); glutSwapBuffers(); }

2.3

カメラ画像のテクスチャマッピング

また,図2に示すように,読み込んだ画像データをテクスチャとしてマッピングすることで,動画を貼るこ とが可能である.テクスチャマッピングは通常の方法と同じである.参照: sample-texture.c 図2 動画:3次元ポリゴンへのテクスチャマッピング テクスチャを動画として動的に更新したい場合,あらかじめ確保したテクスチャ・オブジェクトの画像を上 書きして実現する方法を用いる.glTexImage2D()で設定したテクスチャ・オブジェクトの画像を更新するに は,2次元テクスチャ画像を上書きするglTexSubImage2D()関数を用いる.

(11)

2.3 カメラ画像のテクスチャマッピング 11

 

void glTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,

GLenum format, GLenum type, const GLvoid *pixels );

  下記に示すように,idle関数内において,カメラからの画像キャプチャを行い,glTexSubImage2D()関数 を用いてテクスチャ画像の更新を行う. void idle(void) { if (capture) { frame = cvQueryFrame(capture); if (frame->origin==0) { cvFlip(frame, frame, 0); } cvCvtColor(frame, frame, CV_BGR2RGB); } glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glBindTexture( GL_TEXTURE_2D, tex_index ); glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, frame->width, frame->height, GL_RGB, GL_UNSIGNED_BYTE, frame->imageData ); glutPostRedisplay(); } なお,テクスチャマッピングでは,画像を物体のポリゴン面などに対応づけ,各頂点に画像上の位置を対応 づけることで行われる.画像上の位置とポリゴンの頂点の対応付けには,glVertex()で頂点座標を指定する前 に,対応する画像の位置をglTexCoord()で指定を行う.なお,画像上の位置は画像の画素数ではなく,画像 全体をテクスチャ画像全体を0.0...1.0で正規化された座標系で位置を指定する.ただし,OpenGLにおける テクスチャ画像は,2の累乗である必要がある.そのため,テクスチャ画像は貼りたい画像のサイズより大き い2の累乗のサイズで確保する.例えば,今回の様に640*480の画像をテクスチャとしてマッピングした い場合,1024*512の画像として扱う. テクスチャ座標は確保したテクスチャ画像の大きさで正規化されているため,更新される動画像をテクス チャとして正しくマッピングするためには,それぞれ確保されたテクスチャ画像のサイズに対する貼りたい画 像のサイズの比率をかけた値を指定する必要がある.例えば,図3に示すように640*480の動画像をマッ ピングしたい場合,1024*512のテクスチャ画像として確保されているため,glTexCoord()で指定するテク スチャ座標には,横方向に0.625(=640/1024)倍,縦方向に0.9375(=480/512)倍した値を指定する.

(12)

  void glTexCoord{1,2,3,4}{s,i,d,f}(TYPE coords);

void glTexCoord{1,2,3,4}{s,i,d,f}v(TYPE *coords);

  図3 ポリゴンへの動画テクスチャマッピング void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ... glColor3f(1.0, 1.0, 1.0); glEnable(GL_TEXTURE_2D);

glBindTexture( GL_TEXTURE_2D, tex_index );

glPushMatrix(); glBegin(GL_TRIANGLE_FAN); glTexCoord2f(0.0, 0.0); glVertex3f(-cap_width/2, -cap_height/2, 0.0); glTexCoord2f((float)cap_width/tex_width, 0.0); glVertex3f(cap_width/2, -cap_height/2, 0.0); glTexCoord2f((float)cap_width/tex_width, (float)cap_height/tex_height); glVertex3f(cap_width/2, cap_height/2, 0.0); glTexCoord2f(0.0, (float)cap_height/tex_height); glVertex3f(-cap_width/2, cap_height/2, 0.0); glEnd(); glPopMatrix(); }

(13)

2.3 カメラ画像のテクスチャマッピング 13 テクスチャマッピングを3次元コンピュータグラフィックス上に行うことで,動画を単純なポリゴンにマッ ピング(図2)するだけではなく,複雑な3次元局面にもマッピング(図4)することができる.それぞれの表 面上のテクスチャはカメラを接続しているので,リアルタイムに動画が変化する. ◇ 課題1◇   1. 解凍されたopencv-sampleディレクトリ内のプログラムをコンパイルせよ.またUSBカメ ラを接続した後実行し,カメラ画像が表示されるか確認せよ.また,v4l2-sample内のプロ グラムと比較してみよう. 2. opencv-textureディレクトリ内のプログラムを同様に実行し,図2と同じ実行結果がえられ ることを確認せよ. 3. opencv-divtexディレクトリ内のプログラムで,TODOを埋めて課題2.2と同じ結果がえら れることを確認せよ. 4. さらに,図4に示すように,複雑な面にカメラからの画像がテクスチャマッピングされるよ うに変更せよ. 5. opencv-dynamicディレクトリ内のプログラムを,時間経過に合わせてポリゴンが動的に変 化するようにせよ.(オプション)   図4 動画:3次元の複雑な面へのテクスチャマッピング

(14)

3

Augmented Reality

3.1

Augmented Reality

とは

現実環境とVR環境をシームレスに融合させ,現実環境の情報の豊かさとVR環境の柔軟性を兼ね備えた強

化された環境を実時間に提供する,拡張現実感(AR: AugmentedReality),あるいは複合現実感(MR: Mixed

Reality)と呼ばれる技術が注目されている.これはヘッドマウントディスプレイ(HMD: Head Mounted Display)などを用いて実世界の画像とVR物体を合成表示することにより,あたかも現実世界に仮想物体が そのまま出現したかのように見せる技術である. CG画像と実写画像の合成方法によって次の2つのタイプに分けられる. 光学シースルー(Optical See-Through)方式 ビデオシースルー(Video See-Through)方式 それぞれの原理と特徴を述べると,前者は現実空間をハーフミラーで直接見て,VR空間と重ね合わせる方 式であり,実時間で安定して動作するという特徴がある.VR物体による現実物体の遮蔽が困難であり,ハー フミラーを用いるために現実環境が若干暗く見え,VR物体が半透明に見えるなどの短所がある.一方後者 は,現実空間をビデオカメラで撮影してVR空間と合成したあとにディスプレイに表示するものである.実写 画像を一旦コンピュータに取り込んでから合成処理を施すため,シームレスな重ねあわせには有利である.し かし,処理の遅延により,船酔いや宇宙酔いのようなVR酔いを起こしやすい. 図5 光学シースルー(Optical See-Through)方式におけるHMD 図6 ビデオシースルー(Video See-Through)方式

(15)

15

4

ARToolKit

とは

ARToolKitとは,これまでOpenCVやOpenGLで実現してきた拡張現実感(AR:Augmented Reality)

の実現を容易にするためのライブラリ群である.ARToolKitはワシントン大学のHITL(Human Interface

Technology Lab)により開発され,現在までに非常に多くの拡張現実感プロジェクトにおいて利用されてい る.ARToolKit Home Page (http://www.hitl.washington.edu/artoolkit/)よりダウンロードすることがで きる. 通常、ARアプリケーションを構築するには,画像解析の演習などで行った通り,カメラ等で現実世界を取 り込んだ映像の解析,カメラや対象ビジュアルマーカの位置情報の解析,コンピュータグラフィックの生成及 び合成といった非常に複雑な処理が必要になる.ARToolKitを利用することによりこれらのビジュアルマー カの検出アルゴリズムやカメラ位置の計算アルゴリズムグラフィックの生成等を行ってくれるため,開発者は ビジュアルマーカ内の固有パターンの定義やグラフィックの動作等を定義することにより拡張現実感を実現す ることが出来る.

ARToolKitは現在SGI IRIX, PCリナックス,Mac OS X,およびPC Windows(95/98/NT/2000/XP)

のオペレーティングシステムで動作する.ARToolKitの最新バージョンはマルチプラットフォームであり, ツールキットのそれぞれのバージョンの機能性は同じである.(図) ARToolkitのビデオキャプチャモジュー ルは,内部でOSに応じたインタフェースを使うようになっている.画像の描画が3DCGにおける視点の設 定(グラフィック処理)には,OpenGLとGLUTを用いている. 図7 ARToolKitのアーキテクチャ

4.1

ARToolKit

の概要

ARToolKitを使用するアプリケーションの開発は,アプリケーションを記述する部分と,アプリケーショ ンで使用される実際のマーカー上の画像処理のトレーニング部に分かれる. アプリケーションの主な構成は以下の方法を取る. ステップ1と6はアプリケーションの初期化と閉鎖に実行され,ステップ2∼5はアプリケーションが終了 するまでずっと繰り返される.これらのステップに加え,アプリケーションはマウス、キーボードまたは他の アプリケーションに特定のイベントの処理も行う.

(16)

初期設定 1. ビデオキャプチャを初期化. マーカーパターンとカメラパラメタの読み込み. メインループ 2. ビデオ入力画像の取得. 3. ビデオ入力画像にマーカーと認識されたパターンの検出. 4. 検出されたパターンに比例してカメラパラメータを算出. 5. 検出されたパターンにVRオブジェクトの描画. 終了 6. ビデオキャプチャの終了 表3 ARToolKitの処理ステップ

4.2

ARToolKit

のプログラム例

まずは,簡単なARToolKitアプリケーションのソースコード(simpleTest(simple.c))を通して,プログラ ムの書き方を説明する. 図8 simpleTestの実行例

ARToolKit Step Functions 1. Initialize the application init

2. Grab a video input frame arVideoGetImage (called in mainLoop) 3. Detect the markers arDetectMarker (called in mainLoop) 4. Calculate camera transformation arGetTransMat (called in mainLoop) 5. Draw the virtual objects draw (called in mainLoop)

6. Close the video capture down cleanup

表4 ARToolKitの処理ステップと命令

(17)

4.2 ARToolKitのプログラム例 17

main関数main()

main関数では,主に初期化処理とメインループの起動を行う. argMainLoop()によってメインループが

起動される.

main(int argc, char *argv[]) {

init();

arVideoCapStart();

argMainLoop( NULL, keyEvent, mainLoop ); }

初期化ルーチンはマーカーとカメラパラメタを読み込み、ビデオキャプチャを始めるためのコード,および

ウィンドウのセットアップを含んでいる.ステップ1に対応.次に、ビデオへの呼び出しで,arVideoCapStart

呼び,リアルタイムキャプチャが開始する.続いて,argMainLoopは,レンダリングを行うrendering loop

を伴うmain program loopを始動する.

初期化init() 初期化ルーチンは,mainからコールされ,ビデオキャプチャの初期化,ARToolKitのアプリケーションパ ラメータの読み込みを行う.ARToolKitアプリケーションのための主要なパラメタは以下の通り. ビデオデバイスの設定(設定が記録されたXMLファイルの読み込み) カメラパラメータファイルの読み込み.デフォルト:Data/camera para.dat). パターンテンプレート照合に使用されるパターンの読み込み ウィンドウの作成 まず,ビデオデバイスを開き,ウインドウサイズの取得を行う.

/* open the video path */

if( arVideoOpen( vconf ) < 0 ) exit(0);

/* find the size of the window */

if( arVideoInqSize(&xsize, &ysize) < 0 ) exit(0); printf("Image size (x,y) = (%d,%d)\n", xsize, ysize);

(18)

/* set the initial camera parameters */

if( arParamLoad(cparaname, 1, &wparam) < 0 ) { printf("Camera parameter load error !!\n"); exit(0);

}

arParamChangeSize( &wparam, xsize, ysize, &cparam );

カメラパラメータの設定と表示.

arInitCparam( &cparam ); arParamDisp( &cparam );

パターンの定義を読み込む.(デフォルト:Data/patt.hiro)

if( (patt_id=arLoadPatt(patt_name)) < 0 ) { printf("pattern load error !!\n"); exit(0);

}

patt idは特定されたパターンのID.

/* open the graphics window */ argInit( &cparam, 1.0, 0, 0, 0, 0 );

最後に,ウィンドウを開く.2つめのパラメータは,ズームの比率.

メインループmailLoop()

表3のステップ2-5に対応する.まず,ビデオ画像はarVideoGetImageを使用することでキャプチャする.

/* grab a video frame */

if( (dataPtr = (ARUint8 *)arVideoGetImage()) == NULL ) { arUtilSleep(2);

return; }

(19)

4.2 ARToolKitのプログラム例 19

argDrawMode2D();

argDispImage( dataPtr, 0,0 );

arDetectMarkerはビデオ画像から正しいマーカパターンを持つ正方形を検出する.

発見されたマーカの数は,marker numに含まれる.marker infoにはマーカの座標情報は,認識時の信頼

度,IDが含まれる構造体のポインタが入る.marker info[j].idはj番目に検出されたマーカに対するマーカ

ID,marker info[j].cfはどれだけ近いかを示す一致度(0.0∼1.0)が格納される.

if( arDetectMarker(dataPtr, thresh, &marker_info, &marker_num) < 0 ) { cleanup(); exit(0); }); 次のカメラ画像を取得. arVideoCapNext(); 検出されたマーカのすべての信頼度を比較し,どのIDと相関が高いか調べる.どのパターンも見つからな かった場合(k==-1),SwapBuffersのみ.

/* check for object visibility */ k = -1;

for( j = 0; j < marker_num; j++ ) { if( patt_id == marker_info[j].id ) {

if( k == -1 ) k = j;

else if( marker_info[k].cf < marker_info[j].cf ) k = j; } } if( k == -1 ) { argSwapBuffers(); return; } arGetTransMat()関数により,マーカーとカメラの間の座標変換行列を求める.マーカiに対応したカメ ラ位置と方向が3x4マトリクスpatt transに含まれる.

(20)

/* get the transformation between the marker and the real camera */ arGetTransMat(&marker_info[k], patt_center, patt_width, patt_trans);

ここで,draw()関数が呼ばれ,実際の3Dオブジェクトの描画を行う.

draw();

argSwapBuffers();

描画処理draw()

draw関数では,レンダリングの初期化, マトリックスのセットアップ, 物体のレンダリングに分かれる.

ARToolKitに問い合わせを行い3Dレンダリングの初期化を行う.argDrawMode3D()関数でOpenGLのモ

デルビュー行列を初期化し,argDraw3dCamera()関数で3D空間の視野範囲を設定する. argDrawMode3D(); argDraw3dCamera( 0, 0 ); glClearDepth( 1.0 ); glClear(GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL);

argConvGlparaにより,ARToolKitで算出された3x4行列を,OpenGL形式(4x4行列)に変換する.こ

の値は,実際のカメラの位置と方向を表し,OpenGLのカメラ位置に設定することで,マーカー上にオブジェ

クトをレンダリングすることができる.

/* load the camera transformation matrix */ argConvGlpara(patt_trans, gl_para); glMatrixMode(GL_MODELVIEW); glLoadMatrixd( gl_para ); OpenGLの関数によりオブジェクトの描画.この場合,白色光の下の青い立方体を描画.原点から25.0mm 浮かしてあることに注意すること. glEnable(GL_LIGHTING); glEnable(GL_LIGHT0);

glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT, ambi);

(21)

4.2 ARToolKitのプログラム例 21

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash);

glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

glMatrixMode(GL_MODELVIEW); glTranslatef( 0.0, 0.0, 25.0 ); glutSolidCube(50.0); OpenGLパラメータをデフォルトに戻す. glDisable( GL_LIGHTING ); glDisable( GL_DEPTH_TEST ); 終了処理cleanup()

cleenupでは,他のアプリケーションのため,ビデオプロセッシングを終了しvideo pathを閉じる.

arVideoCapStop(); arVideoClose(); argCleanup();

(22)

4.3

ARToolKit

OpenGL

の座標変換

ARToolKitでは,検出されたマーカの情報から,カメラ視点に対するマーカの3次元位置姿勢を計算し, その情報に基づいてキャプチャした画像上にOpenGLで描画を行っている. Xc Zc Yc Xm Ym Zm カメラ座標系 マーカ座標系 4x4 変換行列 gl_para[16] 図9 ARToolKitにおける座標変換

arGetTransMat()関数を実行すると,回転成分と並進成分を含む座標変換行列patt trans(3x4行列)が得 られる.r11∼r33が回転成分,tx, ty, tzが並進成分となっている.ただし,この行列はARToolKit上での記 述になっているので,OpenGLにおいて3次元物体の描画位置を検出するには,OpenGLの座標系に変換す る必要がある. patt trans =  rr1121 rr1222 rr1323 ttxy r31 r32 r33 tz   (1)

argConvGlpara()関数でこの変換を行い,OpenGL形式の座標変換行列gl para(4x4行列)が得られる.

argConvGlpara(patt_trans, gl_para); glMatrixMode(GL_MODELVIEW); glLoadMatrixd( gl_para ); gl para =     r11 r12 r13 tx r21 r22 r23 ty r31 r32 r33 tz 0 0 0 1     (2) OpenGLにおいても原点はカメラの位置にあるが,この変換行列をモデルビュー行列として読み込むこと により,マーカ中心を原点とした座標系になる.原点にオブジェクトを描画すれば,マーカ上に指定したオブ ジェクトがレンダリングされることになる.     Xc Yc Zc 1     =     r11 r12 r13 tx r21 r22 r23 ty r31 r32 r33 tz 0 0 0 1         Xm Ym Zm 1     (3) また,ARにおいては,OpenGLのオブジェクトと実空間とのスケールの対応付けを行う必要がある.

(23)

4.4 ARToolKitのインストール 23 double patt_width = 80.0 上記ではマーカの一辺の長さをmm単位で指定しており,実際に印刷したマーカのサイズと一致させるこ とで,CGオブジェクトのサイズもmm単位で正確に配置することが可能になる.一辺50mmの立方体を配 置したければglutSolidCube(50.0)とすればよい. glMatrixMode(GL_MODELVIEW); glTranslatef( 0.0, 0.0, 25.0 ); glutSolidCube(50.0);

4.4

ARToolKit

のインストール

演習用のノートには,ARToolKitがインストールされていない.Linux上でコンパイルが通るようにパッ チを当てたARToolKitが演習のページにあるので,ダウンロードしてコンパイルすること.手順は以下の 通り.   $ cd ARToolkit $ ./Configure   Configureの質問に対し,1つめの質問は”3”,2つめの質問以降,すべて”n”と答えること.終了後,make することでライブラリやサンプルプログラムがコンパイルされる.   $ make   ライブラリは(解凍先ディレクトリ)/ARToolkit/libに,サンプルの実行プログラムは(解凍先ディレクト リ)/ARToolkit/bin,サンプルのソースコードは(解凍先ディレクトリ)/ARToolkit/examplesにある.実行 ファイルを実行する際は,必ずbinディレクトリの移動してから実行すること.

(24)

◇ 課題2◇   1. sampleLite.cをコンパイルし,カメラ画像が表示されること確認せよ.また,Hiroと書いて あるパターンにオブジェクトが重ねられることを確認せよ.なお,マーカが曲がっていると 認識できないので,マーカを机に置いてカメラを動かすとよい. 2. 表示されているオブジェクトを変更してみよ.テクスチャを貼ってみるのもよい. 3. 表示されているオブジェクトをアニメーションさせよ.上下移動や回転でよい. 4. (オプション)複数のパターンが認識され,それぞれ別のオブジェクトが表示できるようにせ よ.(参考:http://www.hitl.washington.edu/artoolkit/documentation/devmulti.htm)   図10 参考課題 実行時の画面例 図11 参考課題 実行時の画面例

表 1 IplImage 構造体の主なメンバ変数
表 2 ビデオキャプチャ構造体のプロパティ ID キャプチャ処理 カメラやビデオファイルから 1 つのフレームを取り出して返す場合は,キャプチャデバイス(前項で取得し た CvCapture 構造体)が有効な間,カメラや動画ファイルからフレーム( 1 枚の画像)を取り込むことがで きる.この処理には cvQueryFrame() を呼び出す.この関数が呼び出されるとカメラ又は AVI ファイルから 画像が 1 枚取り込まれ, IplImage 構造体へのポインタが返される.ここで返ってくる画像( IplIm
表 4 ARToolKit の処理ステップと命令
表 3 のステップ 2-5 に対応する.まず,ビデオ画像は arVideoGetImage を使用することでキャプチャする.

参照

関連したドキュメント

SVF Migration Tool の動作を制御するための設定を設定ファイルに記述します。Windows 環境 の場合は「SVF Migration Tool の動作設定 (p. 20)」を、UNIX/Linux

Linux Foundation とハーバード大学による CensusⅡプロジェクトの予備的レポート ~アプリケーシ ョンに最も利用されている

本節では本研究で実際にスレッドのトレースを行うた めに用いた Linux ftrace 及び ftrace を利用する Android Systrace について説明する.. 2.1

SUSE® Linux Enterprise Server 15 for AMD64 &amp; Intel64 15S SLES SUSE® Linux Enterprise Server 12 for AMD64 &amp; Intel64 12S. VMware vSphere® 7

ESET Server Security for Windows Server、ESET Mail/File/Gateway Security for Linux は

サーバー API 複雑化 iOS&amp;Android 間で複雑な API

本資料は Linux サーバー OS 向けプログラム「 ESET Server Security for Linux V8.1 」の機能を紹介した資料です。.. ・ESET File Security

R_DMACn_Suspend R_DMACn_Resume R_DMACnm_Create R_DMACnm_Start R_DMACnm_Stop.