平成 21 年度機械情報工学科演習 メディアインタ …1 平成21...

23
1 21 メディアインタフェース (2) インタフェースデバイス 3DCG 衛, TA2009 12 17 1 演習の目的 ,「コンピュータグラフィックス」 した OpenGL ,テクスチャ マッピングを に, コンピュータグラフィックス インタラクションについて学 .一つ ,インタ フェース 一つ ある Wii リモコンを いて, グラフィックス インタラクション を学 する. Wii リモコン むこ あり, をつ ぐインタ フェースに る.ボタンを すこ ふり OpenGL させるインタラクショ を学 する. う一つ USB カメラを いて,カメラから んだ コンピュータグ ラフィックス (3DCG) を学 する. 1.1 資料など http://www.cyber.t.u-tokyo.ac.jp/~tani/class/mech_enshu/ においてある. するソースファイル からダ ンロードするこ .「コンピュータグラフィックス」 「メディアインタフェース」 したい URL リン クが ってあるため, .ネットワークにつ がら 員に USB メモリを りてデータを コピーするこ 1.2 出席・課題の確認について およびレポート によって う. 題が したら, 員・TA び, って して せよ.

Upload: others

Post on 02-Mar-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

1

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

メディアインタフェース (2)

インタフェースデバイスと 3DCG

担当:西村邦裕,谷川智洋,下坂正倫,森武俊,中村衛,田中雅行,中垣好之TA: 林織部,西坂信哉,鳥越祐輔,茂木厚憲

2009年 12月 17日

1 演習の目的

本日の演習では,「コンピュータグラフィックス」で学習した OpenGL の基礎,画像の表示,テクスチャ

マッピングを元に,三次元コンピュータグラフィックスとのインタラクションについて学ぶ.一つは,インタ

フェースの一つであるWiiリモコンを用いて,三次元グラフィックスとのインタラクション手法を学習する.

Wii リモコンは,人間の手の動きなどを取り込むことが可能であり,計算機の世界と実世界をつなぐインタ

フェースになる.ボタンを押すことや腕ふりなどの動作と OpenGL内での動作を連携させるインタラクショ

ン手法を学習する.もう一つは,USBカメラを用いて,カメラから取り込んだ動画を三次元コンピュータグ

ラフィックス (3DCG)に貼り込む手法を学習する.

1.1 資料など

本日の演習の資料などは,� �http://www.cyber.t.u-tokyo.ac.jp/~tani/class/mech_enshu/� �

においてある.

本日使用するソースファイルも同じ場所からダウンロードすること.「コンピュータグラフィックス」や前

回の「メディアインタフェース」の資料を参照したい場合も同じ場所を参照のこと.参考となる URLもリン

クが貼ってあるため,参照のこと.ネットワークにつながらない者は,教員に USBメモリを借りてデータを

コピーすること.

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

出席の確認は,課題の確認およびレポートの提出によって行う.課題が終了したら,教員・TAを呼び,指

示に従って実行して説明せよ.

Page 2: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

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

課題が全て終了したらメール課題に取り組み,「メール課題」を [email protected] 宛てに

ECC のアドレスからメールせよ.件名は「メディアインタフェース演習 20091217 の課題メール:abcdefgh」

とせよ.ただし abcdefgh は学籍番号( 半角の数字列)に置き換えよ.適切な件名でないものは未提出扱いに

なる可能性があるので要注意.メール提出後は退室してよい.演習時間終了後(16 時 15 分以降)は,課題が

全て終了せずとも退室は自由である.ただし,メール課題はできたところまでで良いので本日中に提出のこ

と.学外からメールを提出する場合も ECC のアドレスを利用のこと.ECC のアドレスからメールを送付で

きない場合,教員に相談せよ.

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/enshu2009/cwiid-0.5.03.tgz� �

CWiidを適切なフォルダでインストール.� �tar xvzf cwiid-0.5.03.tgz

./configure

make

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

入力する.

Page 3: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

2.5 Wiiリモコンの動作確認 3

� �cd cwiid-0.5.03/wmgui

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

図 1 Connect画面

Connectしたら,「Settings」→「Acc Data」にチェックをする.Wiiリモコンを動かしてデータが動いて

いるのが見ることができたら,動作確認終了.

図 2 設定画面

Page 4: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

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

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

三次元コンピュータグラフィックスを操作するには,キーボード,マウスその他のインタフェースを用い

る.本演習では,身体の動きも取得することができるWiiリモコンを用いたインタラクション手法の基礎に

ついて学習する.任天堂Wiiは家庭用ゲーム機であり,体を動かしたり,腕を振ったり,という身体的動作ま

で含めたインタフェースを提供しており,従来型のボタンや矢印キーなども含まれている.また,特徴として

は,Bluetoothを用いた無線での操作が可能であり,Wiiリモコンにケーブルがついておらず,操作が容易と

なっている点も特徴である.

3.1 Wiiリモコン

Wiiのインタフェースとしては,従来型のクラシックコントローラ,Wiiリモコン,Wiiリモコンに接続す

るヌンチャク,Wii Fitなどが発売されている.その中でもWiiリモコンは,簡単な操作,直感的な操作を目

指して開発されており,誰でも容易に使えるインタフェースの一つである.

Wiiリモコンには,3 軸加速度センサ,スピーカ,スピーカ用アンプ,電源コントロール IC,サウンドデ

コーダ,Bluetooth 用 IC,振動モータ,ポインタ用 CMOS カメラ,似顔絵データ用メモリが搭載されてい

る.特に,Bluetoothが搭載されていることにより無線での利用が可能であり,3軸リニア加速度センサを搭

載していることによって,腕を振る動作や傾ける動作などを検出することが可能である.

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

3.2 CWiid

CWiid(http://abstrakraft.org/cwiid/)は,Linux用に Cで書かれたWiiリモコン(Wiimote)用のツー

ルであり,イベントの APIなどが含まれている.Wiiリモコンの APIやWiimoteライブラリ,GTKをベー

スにした GUI インタフェースなどが含まれている.詳細は,下記のフォルダに入っているので参考にする

こと.

Page 5: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

3.2 CWiid 5

� �/home/mechuser/ubuntu/manual_install/cwiid-0.5.03/� �

今回の演習では,センサーバーなどないため,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 oneは zeropointと 1Gpointの初期値である

Page 6: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

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

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

}

Wiiリモコンからのボタンの値は,下記の手法で取得できる.

Page 7: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

3.2 CWiid 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ライブラリを参照する.

Page 8: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

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

図 5 Yaw,Pitch,Roll(http://sorceryforce.com/programing/mdx/direct3d/stepup/quaternion.html)

CC = g++

COMMON = .

PACKAGE_VERSION = 0.5.03

WIIMOTE_DIR = /usr/local/src/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:

   ${RM} ${TARGET} *.o *~

Page 9: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

3.2 CWiid 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)動きを移動平均などをとることにより安定化させよ(オプション).

3. kadai3のフォルダに入っている sample.cをコンパイルし,Wiiリモコンを振ることによっ

て球の動く方向が変化することを確認せよ.disp flagによって,左向き,右向き,静止の状態

が変化する.ホームボタンを押すと位置がリセットされる.

(a)加速度のパラメータを変化させ,手の動きに敏感あるいは鈍感に変更させてみよ.

(b)壁面を書いて,ぶつかったら反対向きに動くように変更せよ.壁をある位置に設定し,

そこに来たら反対方向に動くようにさせる.これができると,壁にあたって帰ってきた

球を,Wiiリモコンを振ることによって打ち返せる感じになる.

(c)ぶつかった際に振動が起きるようにせよ(オプション).

(d)余裕があったら,壁あてゲームのように,球の速さが変わりながら,壁に当たって,戻っ

てきたら打ち返すようにせよ.(オプション).

� �

Page 10: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

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

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

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

図 8 Wiiリモコンを大きく振るとボールの動く向きが変更になる例

Page 11: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

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とコマンドで打ち込んだとき下記の様にロードされている

ことが確認できるはずである.� �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でカメラ画像から取得したフ

レーム画像をテクスチャとして貼り付け,ポリゴンとして自由に操作することを可能にすることを目指す.

Page 12: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

12 4 動画の取り扱い

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

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

Page 13: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

4.1 動画を利用するプログラム 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> の定数を用いて色空間の変換を指定� �

Page 14: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

14 4 動画の取り扱い

カメラからのキャプチャ準備

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 15: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

4.1 動画を利用するプログラム 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

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

Page 16: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

16 4 動画の取り扱い

キャプチャの終了処理

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>

Page 17: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

4.2 簡単な例 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);

}

Page 18: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

18 4 動画の取り扱い

カメラ画像の取得

カメラからの画像の更新は,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 19: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

4.3 カメラ画像のテクスチャマッピング 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() 関数を用いる.

Page 20: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

20 4 動画の取り扱い

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

Page 21: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

4.3 カメラ画像のテクスチャマッピング 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();

}

Page 22: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

22 4 動画の取り扱い

テクスチャマッピングを 3次元コンピュータグラフィックス上に行うことで,動画を単純なポリゴンにマッ

ピング (図 10)するだけではなく,複雑な 3次元局面にもマッピング (図 12)することができる.それぞれの

表面上のテクスチャはカメラを接続しているので,リアルタイムに動画が変化する.

◇ 課題 2 ◇� �1. v4l2-sample.tar.gz をダウンロードし,コンパイルせよ.USB カメラを接続した後実行し,

図 9のようにカメラ画像が表示されるか確認せよ.

2. opencv-sample.tar.gzをダウンロードし,コンパイルせよ.同様にカメラ画像が表示される

か確認せよ.また課題 2.1のプログラムと比較してみよう.

3. opencv-texture.tar.gzをダウンロードし,図 10と同じ結果がえられることを確認せよ.

4. opencv-divtex.tar.gzをダウンロードし,TODOを埋めて課題 2.3と同じ結果がえられるこ

とを確認せよ.

5. さらに,図 12に示すように,複雑な面にカメラからの画像がテクスチャマッピングされるよ

うに変更せよ.それをスクリーンキャプチャして,課題メールとして提出せよ.

6. opencv-dynamic.tar.gzをダウンロードし,時間経過に合わせてポリゴンが動的に変化する

ようにせよ.(オプション)

� �

図 12 動画:3次元の複雑な面へのテクスチャマッピング

Page 23: 平成 21 年度機械情報工学科演習 メディアインタ …1 平成21 年度機械情報工学科演習 メディアインタフェース(2) インタフェースデバイスと3DCG

23

◇ 課題メール ◇� � 上記の課題について教員・TAに動作確認を受けたら,以下の課題メールに取り組むこと.課題

メールを提出したら 16 時 15 分より前でも演習は終了.教員(TA)は 18 時頃までは 13B 室にい

る予定である.16 時 15 分以降はプログラムの動作確認が終えてなくとも,出来た範囲で課題メー

ルを書いて提出し,演習を終えても良い.

1. 自分の名前と学籍番号をを書く.

2. 課題 1.3 をスクリーンキャプチャしてメールに貼付せよ.メールにファイル名も記述せよ.

ファイル名を kadai1 3.pngあるいは kadai1 3.jpgなどのようにせよ.

3. 課題 2.5 をスクリーンキャプチャしてメールに添付せよ.メールにファイル名も記述せよ.

ファイル名を kadai2 5.pngあるいは kadai2 5.jpgなどのようにせよ.

� �付録 A 参考文献

伊藤邦朗,福田隆宏,”Wiiリモコン”,日本機械学会誌,2007.12, Vol.110, No.1069, pp.6-7,2007.