動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的...

24
1 平成 27 年度 機械情報工学科演習 コンピュータグラフィクス (2) 動画やカメラを用いた 3DCG の応用 担当:谷川 智洋 准教授,鳴海 拓志 助教,中垣 好之 技官 TA: 岩崎 翔,野元 彰 2015 10 1 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 カメラは,「リアルワールド認識」(2015/10/15(),16(),19())「メディアインタフェース」 (2015/11/9(), 10()) でも使用するので,忘れずに持参すること. また,「ロボットシミュレーション」において貸出を行う Bluetooth USB アダプタは,「メディアイン タフェース (2)(2015/11/10()) で使用するので,忘れずに持参すること.

Transcript of 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的...

Page 1: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

1

平成 27年度 機械情報工学科演習

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

動画やカメラを用いた 3DCGの応用

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

TA: 岩崎 翔,野元 彰

2015年 10月 1日

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 カメラは,「リアルワールド認識」(2015/10/15(木),16(金),19(月))「メディアインタフェース」

(2015/11/9(月), 10(火))でも使用するので,忘れずに持参すること.

また,「ロボットシミュレーション」において貸出を行う BluetoothのUSBアダプタは,「メディアイン

タフェース (2)」(2015/11/10(火))で使用するので,忘れずに持参すること.

Page 2: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

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仕様に基づいてキャプチャ

を行っている.

なお,現在は 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/ サンプルプロ

Page 3: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

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ビット整数を意味する

IPL DEPTH 8Uを,channelsに 3を指定する.

Page 4: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

4 2 動画の取り扱い

� �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> の定数を用いて色空間の変換を指定� �

Page 5: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

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.� �

Page 6: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

6 2 動画の取り扱い

同様に,関数 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

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

Page 7: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

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>

Page 8: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

8 2 動画の取り扱い

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);

}

Page 9: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

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);� �

Page 10: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

10 2 動画の取り扱い

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() 関数を用いる.

Page 11: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

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)倍した値を指定する.

Page 12: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

12 2 動画の取り扱い

� �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();

}

Page 13: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

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次元の複雑な面へのテクスチャマッピング

Page 14: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

14 3 Augmented Reality

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)方式

Page 15: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

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はアプリケーションが終了

するまでずっと繰り返される.これらのステップに加え,アプリケーションはマウス、キーボードまたは他の

アプリケーションに特定のイベントの処理も行う.

Page 16: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

16 4 ARToolKitとは

初期設定 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の処理ステップと命令

プログラムの重要な部分は,main, init, mainLoop, draw, cleanupの 5つになる.

Page 17: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

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);

カメラパラメータのロード.カメラパラメータは現在の画像サイズに応じて変更する.

Page 18: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

18 4 ARToolKitとは

/* 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;

}

画面上にビデオ画像を表示.

Page 19: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

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に含まれる.

Page 20: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

20 4 ARToolKitとは

/* 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);

glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);

Page 21: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

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();

Page 22: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

22 4 ARToolKitとは

4.3 ARToolKitと OpenGLの座標変換

ARToolKit では,検出されたマーカの情報から,カメラ視点に対するマーカの 3 次元位置姿勢を計算し,

その情報に基づいてキャプチャした画像上に OpenGLで描画を行っている.

XcZc

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 =

r11 r12 r13 txr21 r22 r23 tyr31 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 txr21 r22 r23 tyr31 r32 r33 tz0 0 0 1

(2)

OpenGLにおいても原点はカメラの位置にあるが,この変換行列をモデルビュー行列として読み込むこと

により,マーカ中心を原点とした座標系になる.原点にオブジェクトを描画すれば,マーカ上に指定したオブ

ジェクトがレンダリングされることになる.Xc

Yc

Zc

1

=

r11 r12 r13 txr21 r22 r23 tyr31 r32 r33 tz0 0 0 1

Xm

Ym

Zm

1

(3)

また,ARにおいては,OpenGLのオブジェクトと実空間とのスケールの対応付けを行う必要がある.

Page 23: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

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ディレクトリの移動してから実行すること.

Page 24: 動画やカメラを用いた 3DCG - Kuzuoka Amemiya …2015年10月1日 1 演習の目的 本日の演習では,前回学習したOpenGL の基礎を元に,USB カメラから取り込んだ動画を三次元コン

24 4 ARToolKitとは

◇ 課題 2 ◇� �1. sampleLite.cをコンパイルし,カメラ画像が表示されること確認せよ.また,Hiroと書いて

あるパターンにオブジェクトが重ねられることを確認せよ.なお,マーカが曲がっていると

認識できないので,マーカを机に置いてカメラを動かすとよい.

2. 表示されているオブジェクトを変更してみよ.テクスチャを貼ってみるのもよい.

3. 表示されているオブジェクトをアニメーションさせよ.上下移動や回転でよい.

4. (オプション) 複数のパターンが認識され,それぞれ別のオブジェクトが表示できるようにせ

よ.(参考:http://www.hitl.washington.edu/artoolkit/documentation/devmulti.htm)

� �

図 10 参考課題 実行時の画面例 図 11 参考課題 実行時の画面例