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

TA TA TA abcdefgh abcdefgh C PC Wii bluetooth 2.2 Bluetooth USB Princeton PTM-UBT3S 1 1

N/A
N/A
Protected

Academic year: 2021

シェア "TA TA TA abcdefgh abcdefgh C PC Wii bluetooth 2.2 Bluetooth USB Princeton PTM-UBT3S 1 1"

Copied!
22
0
0

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

全文

(1)

平成

22

年度 機械情報工学科 演習

メディアインタフェース

(2)

インタフェースデバイス

担当:西村 邦裕 助教,谷川 智洋 講師,中垣 好之 技官

TA:

梶波 崇,木村 健太郎,山崎 充彦

2010

12

13

1

演習の目的

本日の演習では,「コンピュータグラフィックス」で学習したOpenGLの基礎,画像の表示,テクスチャ マッピングを元に,三次元コンピュータグラフィックスとのインタラクションについて学ぶ. 一つは,インタフェースの一つであるWiiリモコンを用いて,三次元グラフィックスとのインタラクション 手法を学習する.Wiiリモコンは,人間の手の動きなどを取り込むことが可能であり,計算機の世界と実世界 をつなぐインタフェースになる.ボタンを押すことや腕ふりなどの動作とOpenGL内での動作を連携させる インタラクション手法を学習する. もう一つは,USBカメラを用いて,カメラから取り込んだ動画を三次元コンピュータグラフィックス (3DCG)に貼り込む手法を学習する.

1.1

資料など

本日の演習の資料などは, ¶ ³ http://www.cyber.t.u-tokyo.ac.jp/~kuni/enshu2010/ µ ´ においてある. 本日使用するソースファイルも同じ場所からダウンロードすること.「コンピュータグラフィックス」や前 回の「メディアインタフェース」の資料を参照したい場合も同じ場所を参照のこと.参考となるURLもリン クが貼ってあるため,参照のこと.ネットワークにつながらない者は,教員にUSBメモリを借りてデータを コピーすること.

(2)

1.2

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

出席の確認は,課題の確認によって行う.課題が終了したら,教員・TAを呼び,指示に従って実行して説 明せよ.演習時間終了後(16時15分以降)は,課題が全て終了せずとも退室は自由である.教員・TAの動 作確認が間に合わない場合は,出欠を取っているため,教員・TAに確認後,課題をメール提出せよ. メールは, mireport@cyber.t.u-tokyo.ac.jp 宛て件名は「メディアインタフェース演習20101213の課題メール:abcdefgh」とせよ.ただしabcdefghは 学籍番号(半角の数字列)に置き換えよ.適切な件名でないものは未提出扱いになる可能性があるので要注意. ただし,メールは明日中に提出のこと.

2

貸し出し物および動作確認

2.1

使用環境

演習室13C,ノートPCを使用.Wiiリモコン,bluetoothアダプタを毎回忘れないこと.

2.2

Bluetooth

USB

アダプタ

Princeton PTM-UBT3Sを1人1台貸し出す.小さくなくしやすいため,USBアダプタをさしたままにす るなど,なくさないように(個数に余裕がないため).テプラなどは外さないように注意.

2.3

Wii

リモコン

1人に1台を貸し出す.なくさないように.来年以降も使うので大切に取り扱いをする.

2.4

Bluetooth

USB

アダプタの動作確認

USBにさして青色のランプが点滅するか確認する.

2.5

Wii

リモコンの動作確認

CWiidのダウンロード. ¶ ³ http://www.cyber.t.u-tokyo.ac.jp/kuni/enshu2010/cwiid-0.5.03.tgz µ ´ CWiidを適切なフォルダでインストール.

(3)

tar xvzf cwiid-0.5.03.tgz ./configure

make

sudo make install

µ ´

CWiidの動作確認.下記の00:00:00:00:00:00には,WiiリモコンにかかれているBluetoothのアドレスを 入力する.

¶ ³

cd cwiid-0.5.03/wmgui ./wmgui 00:00:00:00:00:00

µ ´

wmguiの画面が立ち上がったら,「File」→「Connect」する.

図1 Connect画面

Connectしたら,「Settings」→「Acc Data」にチェックをする.Wiiリモコンを動かしてデータが動いて いるのが見ることができたら,動作確認終了.

(4)

図2 設定画面

3

三次元コンピュータグラフィックスとインタラクション

三次元コンピュータグラフィックスを操作するには,キーボード,マウスその他のインタフェースを用い る.本演習では,身体の動きも取得することができるWiiリモコンを用いたインタラクション手法の基礎に ついて学習する.任天堂Wiiは家庭用ゲーム機であり,体を動かしたり,腕を振ったり,という身体的動作ま で含めたインタフェースを提供しており,従来型のボタンや矢印キーなども含まれている.また,特徴として は,Bluetoothを用いた無線での操作が可能であり,Wiiリモコンにケーブルがついておらず,操作が容易と なっている点も特徴である.

3.1

Wii

リモコン

Wiiのインタフェースとしては,従来型のクラシックコントローラ,Wiiリモコン,Wiiリモコンに接続す るヌンチャク,Wii Fitなどが発売されている.その中でもWiiリモコンは,簡単な操作,直感的な操作を目 指して開発されており,誰でも容易に使えるインタフェースの一つである. Wiiリモコンには,3軸加速度センサ,スピーカ,スピーカ用アンプ,電源コントロールIC,サウンドデ コーダ,Bluetooth用IC,振動モータ,ポインタ用CMOSカメラ,似顔絵データ用メモリが搭載されてい る.特に,Bluetoothが搭載されていることにより無線での利用が可能であり,3軸リニア加速度センサを搭 載していることによって,腕を振る動作や傾ける動作などを検出することが可能である.

3.2

CWiid

CWiid(http://abstrakraft.org/cwiid/)は,Linux用にCで書かれたWiiリモコン(Wiimote)用のツー ルであり,イベントのAPIなどが含まれている.WiiリモコンのAPIやWiimoteライブラリ,GTKをベー スにしたGUIインタフェースなどが含まれている.詳細は,Downloadして解凍したフォルダに入っている ので参考にすること.

(5)

図3 Wiiリモコン(http://www.nintendo.co.jp/wii/features/wii remote.html)

今回の演習では,センサーバーなどないため,CMOSカメラなどは用いず,またヌンチャクなども用いず に行う.また,スピーカ部分も用いない.ボタンや加速度,振動を用いることとする.

コマンドの送信

Wiiリモコンへのコマンドを送信するには,wiimote commandを用いる.

stateが1でON,0でOFFになる.

commandでは,WIIMOTE CMD RUMBLEが振動,WIIMOTE CMD LEDがLEDである.

¶ ³

wiimote_command(wiimote, command, int state);

µ ´

設定としては,下記の部分を書く.

void set_report_mode(void) {

uint8_t rpt_mode;

rpt_mode = WIIMOTE_RPT_STATUS | WIIMOTE_RPT_BTN;

rpt_mode |= WIIMOTE_RPT_ACC;

wiimote_command(wiimote, WIIMOTE_CMD_RPT_MODE, rpt_mode); }

Wiiリモコンからのコールバック

Wiiリモコンからのコールバックとしては,unionwiimote mesgmesg arrayに入っている.mesg array-typeを用いて加速度とボタンの情報を識別する.acc zero, acc onezeropoint1Gpointの初期値である .

(6)

void wiimote_callback(int id, int mesg_count,

union wiimote_mesg *mesg_array[]) {

int i;

for (i=0; i < mesg_count; i++) { switch (mesg_array[i]->type) { case WIIMOTE_MESG_ACC: wiimote_acc(&mesg_array[i]->acc_mesg); break; case WIIMOTE_MESG_BTN: wiimote_btn(&mesg_array[i]->btn_mesg); break; default: break; } } } 加速度とボタン

Wiiリモコンからの値としては,mesg− > x, mesg− > y, mesg− > zに格納されているが,初期値との 差をとることによって,初期値の影響(重力など)を除くことができる(完全な加速度ではない).

void wiimote_acc(struct wiimote_acc_mesg *mesg) {

printf("x: %d, y: %d, z: %d\t", mesg->x, mesg->y, mesg->z); double a_x, a_y, a_z;

a_x = ((double)mesg->x - acc_zero.x) / (acc_one.x - acc_zero.x);

a_y = ((double)mesg->y - acc_zero.y) / (acc_one.y - acc_zero.y);

a_z = ((double)mesg->z - acc_zero.z) / (acc_one.z - acc_zero.z);

}

(7)

void wiimote_btn(struct wiimote_btn_mesg *mesg){

if(mesg->buttons & WIIMOTE_BTN_UP){

} ボタンは,下記の引数で取得できる. WIIMOTE BTN UP:十字キーの上ボタン WIIMOTE BTN DOWN:十字キーの下ボタン WIIMOTE BTN RIGHT:十字キーの右ボタン WIIMOTE BTN LEFT:十字キーの左ボタン WIIMOTE BTN PLUS:+ボタン WIIMOTE BTN MINUS:−ボタン WIIMOTE BTN A:Aボタン WIIMOTE BTN B:Bボタン

WIIMOTE BTN HOME:HOMEボタン

WIIMOTE BTN 1:1ボタン

WIIMOTE BTN 2:2ボタン

Wiiリモコンの軸

Wiiリモコンの軸は下記の通りである.

図4 Wiiリモコンの軸(http://wiibrew.org/images/9/9e/Wiimote axis2.png)

Yaw, Pitch, Roll

参考までに,Yaw, Pitch, Rollについて図5に示す.クォータニオン(四元数)を用いることで簡単に計算 できるようになるが,今回は省略する.

CWiidを用いたサンプルプログラム

CWiidライブラリを使用するMakefileの例は下記の通りである.cwiid-0.5.03/wiimoteのフォルダを参照 し,wiimoteライブラリを参照する.

(8)

図5 Yaw,Pitch,Roll(http://sorceryforce.com/programing/mdx/direct3d/stepup/quaternion.html) CC = g++ COMMON = . PACKAGE_VERSION = 0.5.03 WIIMOTE_DIR = ../../cwiid-0.5.03/wiimote (適切なフォルダ) RM = rm -f TARGET = sample OBJS = sample.o

CFLAGS = -Wall -I${WIIMOTE_DIR} \ #-DCWIID_VERSION=\"${PACKAGE_VERSION}\" LDFLAGS = -L${WIIMOTE_DIR}

LDLIBS = -lglut -lGL -lGLU -lwiimote

.c.o:

   ${CC} -c ${CFLAGS} $<

${TARGET}: ${OBJS}

   ${CC} -o ${TARGET} ${OBJS} ${LDLIBS} ${LDFLAGS}

clean:

(9)

◇ 課題1

³

1. kadai.tar.gzをダウンロードせよ.kadai1のフォルダに入っているsample.cをコンパイル し,実行せよ.実行方法はBluetoothのアドレス00:00:00:00:00:00を引数にとり,実行す る.Bluetoothのアドレスは貸し出したWiiリモコンに書かれている. 例:./sample 00:00:00:00:00:00 (a)Wiiリモコンを傾けてして,赤いボールが移動することを確認せよ.また,十字キー,+ ボタン,−ボタンで赤いボールが動くことを確認せよ.また,Aボタン,Bボタンなど でボールの色が変化することを確認せよ. (b)キーボードの「1」と「!」,「2」と「”」を押して,WiiリモコンのLEDの1番,2番が光 る,消えることを確認せよ.また「r」と「R]を押して,Wiiリモコンの振動が始まる・ 止まることを確認せよ. (c)ボタンを押すことによって,表示されているWireCubeの回転がスタート,ストップで きるようにせよ.

2. kadai2のフォルダに入っているsample.cをコンパイルし,Wiiリモコンを傾けることで,そ れに応じてTeapotが傾くことを確認せよ.

(a)十字キーを用いて大きさを変更できるようにせよ. (b)Bボタンを押しながら傾けると移動できるようにせよ.

(c)センサーの値の移動平均などをとることにより動きを安定化させよ(オプション). (d)ホームボタンを押すことで初期状態に戻るようにせよ(オプション).

3. kadai3のフォルダに入っているsample.cをコンパイルし,Wiiリモコンを振ることによっ て球の動く方向が変化することを確認せよ.disp flagによって,左向き,右向き,静止の状態 が変化する.ホームボタンを押すと位置がリセットされる. (a)加速度のパラメータを変化させ,手の動きに敏感あるいは鈍感に変更させてみよ. (b)壁面を書いて,ボールが壁にぶつかったら反対向きに動くように変更せよ.適切な位置 に壁を設定し,そこにボールが来たら反対方向に動くようにさせる.これができると, 壁にあたって帰ってきた球を,Wiiリモコンを振ることによって打ち返せる感じになる. ボールの位置によって当たり判定を行うことで実装ができる. (c)ぶつかった際に振動が起きるようにせよ(オプション). (d)余裕があったら,壁あてゲームのように,球の速さが変わりながら,壁に当たって,戻っ てきたら打ち返すようにせよ.(オプション). µ ´

(10)

図6 球がWiiリモコンの傾きにより動く例

図7 TeapotがWiiリモコンの向きにより動く例

(11)

4

動画の取り扱い

夏学期の計算機演習や「コンピュータフラフィックス」演習で学習したUSBカメラを用いた画像の取り扱 いを一歩進んで,OpenGLを用いて動画を取り扱うことについて説明する.

Linuxにおけるカメラ

既に演習で行ったように,Linuxにおいて,動画を利用するためには,Video for Linux(Video4Linux, v4l

と略される)と呼ばれるカメラデバイスを使うためのAPI仕様を利用する.Video4Linuxを用いることによ り,USBカメラ,IEEE1394カメラなどから画像を読み込むことができるとともに,ビデオキャプチャボー ドからの読み込みもできる.また,チューナー操作のためのAPI仕様などもそろっている.最近のLinuxの カーネルでは,Video for Linux 2(Video4Linux2, v4l2と略される)が組み込まれており,夏の計算機演習で はこのAPI仕様に基づいてキャプチャを行った.

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

4.1

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

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

(12)

OpenCV http://opencv.jp/ http://opencv.jp/sample/

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

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

(13)

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

(14)

カメラからのキャプチャ準備 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 µ ´

(15)

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

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

(16)

キャプチャの終了処理

cvCreateCameraCapture(),又はcvCreateFileCapture()で取得したキャプチャデバイスは,デバイス使 用終了時(典型的にはプログラム終了時)にcvReleaseCapture()を呼びだして解放する必要がある.

¶ ³

void cvReleaseCapture( CvCapture** capture );

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

4.2

簡単な例

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

(17)

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

(18)

カメラ画像の取得

カメラからの画像の更新は,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);

(19)

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

4.3

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

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

(20)

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の画像として扱う. テクスチャ座標は確保したテクスチャ画像の大きさで正規化されているため,更新される動画像をテクス チャとして正しくマッピングするためには,それぞれ確保されたテクスチャ画像のサイズに対する貼りたい画 像のサイズの比率をかけた値を指定する必要がある.例えば,図11に示すように640*480の動画像をマッ ピングしたい場合,1024*512のテクスチャ画像として確保されているため,glTexCoord()で指定するテク スチャ座標には,横方向に0.625(=640/1024)倍,縦方向に0.9375(=480/512)倍した値を指定する.

(21)

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

µ ´ 図11 ポリゴンへの動画テクスチャマッピング 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(); }

(22)

3 ピング(図10)するだけではなく,複雑な3次元局面にもマッピング(図12)することができる.それぞれの 表面上のテクスチャはカメラを接続しているので,リアルタイムに動画が変化する. ◇ 課題2 ³ 1. opencv-sample.tar.gzをダウンロードし,コンパイルせよ.USBカメラを接続した後,実行 し,カメラ画像が表示されるか確認せよ. 2. opencv-texture.tar.gzをダウンロードし,図10と同じ結果がえられることを確認せよ. 3. opencv-divtex.tar.gzをダウンロードし,TODOを埋めて課題2.3と同じ結果がえられるこ とを確認せよ. 4. さらに,図12に示すように,複雑な面にカメラからの画像がテクスチャマッピングされるよ うに変更せよ.それをスクリーンキャプチャせよ.画像を1枚テクスチャとしてそのまま貼 る方法と,テクスチャを分割して貼る方法がある.ソースを良く読み,テクスチャを分割し て貼る方法を利用した方がうまくいく. 5. opencv-dynamic.tar.gzをダウンロードし,時間経過に合わせてポリゴンが動的に変化する ようにせよ.(オプション) µ ´ 図12 動画:3次元の複雑な面へのテクスチャマッピング

付録

A

参考文献

図 1 Connect 画面
図 2 設定画面 3 三次元コンピュータグラフィックスとインタラクション 三次元コンピュータグラフィックスを操作するには,キーボード,マウスその他のインタフェースを用い る.本演習では,身体の動きも取得することができる Wii リモコンを用いたインタラクション手法の基礎に ついて学習する.任天堂 Wii は家庭用ゲーム機であり,体を動かしたり,腕を振ったり,という身体的動作ま で含めたインタフェースを提供しており,従来型のボタンや矢印キーなども含まれている.また,特徴として は, Bluetooth を用い
図 3 Wii リモコン( http://www.nintendo.co.jp/wii/features/wii remote.html )
図 4 Wii リモコンの軸( http://wiibrew.org/images/9/9e/Wiimote axis2.png )
+4

参照

関連したドキュメント

255 語, 1 語 1 意味であり, Lana の居住室のキーボー

FEED キーを押しながら LINE キーを押します FEED キーを押し. ながら LINE

レジメン名: EPD療法1,2クール目 投与スケジュール: 4週間毎 抗癌剤(一般名) エロツズマブ ポマリドミド デキサメタゾン..

その後、時計の MODE ボタン(C)を約 2 秒間 押し続けて時刻モードにしてから、時計の CONNECT ボタン(D)を約 2 秒間押し続けて

CD u ボタン SOURCE ボタン ソース.

Jabra Talk 15 SE の操作は簡単です。ボタンを押す時間の長さ により、ヘッドセットの [ 応答 / 終了 ] ボタンはさまざまな機

これはつまり十進法ではなく、一進法を用いて自然数を表記するということである。とは いえ数が大きくなると見にくくなるので、.. 0, 1,

管理画面へのログイン ID について 管理画面のログイン ID について、 希望の ID がある場合は備考欄にご記載下さい。アルファベット小文字、 数字お よび記号 「_ (アンダーライン)