Tobii を使ってユーザの視線を実時間で読み取り,それに応じて動きを変えるアプリケーションを開発することを考えます.こじ研(小嶋研究室)では,Tobii による視線データをアプリケーションから簡単に読み出せるようにするため,TobiiServer という視線サーバを開発・運用しています.下図は TobiiServer の操作ウィンドウの様子です.
現在のところ,ここで説明する TobiiServer は,こじ研内部(Tobii 専用の Windows PC 上)での利用に限らせていただきます.TobiiServer を利用するための API(TobiiClient)は,各自の PC(Windows・Mac・Linux など)にインストールしてください.これで,各自の PC から TobiiServer に接続し,視線データを取得することができます.
視線サーバ TobiiServer は,Tobii を直接(TCP+UDP 接続で)制御することで,位置決め・キャリブレーション・視線計測を行ない,そしてアプリケーション(クライアント)に視線データを提供します.ユーザの位置決め,キャリブレーション,視線計測の開始・停止は,この操作ウィンドウを使って行ないます.アプリケーションは,TobiiServer にネットワーク接続することで,いつでも最新の視線データ(スクリーン上の X-Y 座標)を読み出すことができます.
アプリケーションは,TobiiClient API という C で書かれた関数群をとおして,TobiiServer のサービスを利用することができます.TobiiClient API はネットワーク(TCP/IP)をとおして TobiiServer と接続するため,アプリケーションのプラットフォーム(Mac・Linux・Windows など)を選びません.下図のように,アプリケーションが Windows で動作するものであれば,TobiiServer と同一ホストで動作させることができます.Windows 以外で動作するアプリケーションであれば,ネットワークをとおして TobiiServer と接続するようにします.(図中の "TET Server" は Tobii X120 の内蔵ソフトウェアです.)
下図は,3つの正方形領域をもつ視線応答アプリケーションの動作例です.TobiiServer に接続し,33ms ごとに視線データを読み込み,いずれかの正方形領域に視線が入ると,その正方形領域が決められた色で点灯するというものです.いたって単純なアプリケーションですが,視線応答するための基本機能を備えています.(緑色の点は,視線位置を表わすマーカです.TobiiServer の設定で非表示にすることができます.)
また,より実際的なアプリケーションとしては,広告画像を視線によって自動更新する商品推薦システム(左下図:落合達也, 2010年度卒業研究)や,視線が向けられているコマをアニメーションのように動かす漫画ブラウザ(右下図:西城龍紀, 2010年度卒業研究)などが,例としてあげられます.
TobiiServer は Windows 上で動作する視線サーバです.Tobii X120 に直接アクセス(TCP, UDP 接続)することで,アプリケーション(クライアント)はいつでも最新の視線データを取得することができます.ここでは,TobiiServer を運用するための準備・操作方法を順を追って説明していきます.
- 準備(電源投入・接続チェック・位置決め)
- ユーザ位置の調整
- キャリブレーション
- 視線計測
- クライアントへの視線データの提供
Tobii X120 の右側面には,下図のように,3つの接続端子があります.このうち Power 端子には電源アダプタからの DC 出力プラグを接続します.電源アダプタの AC 入力プラグをコンセントに差し込んでから,DC 出力プラグを Tobii に差し込んでください.一方,LAN 端子には一般的な LAN ケーブル(カテゴリ6などのツイステッドペアケーブル)を接続し,そのケーブルを PC の LAN 端子に接続します.Tobii と PC は,LAN(同じサブネット)に接続してもよいし,両者を1本の LAN ケーブル(ストレート)で直接接続してもよいです.なお,もうひとつの端子(Trig)は,ここでは使いません.
Tobii には "TX120-204-93500303.local." のような固有名(Bonjour ホスト名)が付けられていて,この名前は Tobii SDK に添付された Tobii Eyetracker Browser で調べることができます.PC 上で Tobii Eyetracker Browser を起動してください.こじ研の Tobii 専用 PC であれば,デスクトップにエイリアスがあるはずです.起動すると,つぎのようなウィンドウが出ます.
環境によっては複数の Tobii が LAN 上に見つかるかもしれません.使用する Tobii をリストから選択(クリック)してください.ウィンドウ下部に Tobii の固有名(たとえば "TX120-204-93500303.local.")が表示されるはずです.[Copy] ボタンを押して,この固有名(文字列)をクリップボードにコピーしておいてください.
つぎに Tobii とスクリーン(画面)の位置関係を実測・登録します.Tobii Eyetracker Browser のウィンドウ下部にある [X120 Config Tool...] ボタンを押すと,つぎのような位置決めツールが起動します.Tobii とスクリーンの位置関係を実測・入力してください.最後に [Save to Tracker] ボタンを押して,このデータを Tobii に登録します.2つのウィンドウ("Tobii X120 Configuration" と "EyeTracker Browser")を閉じてください.
これで準備は整いましたので,TobiiServer を起動します.こじ研の Tobii 専用 PC であれば,デスクトップにエイリアスがあるはずです.起動すると,つぎのようなウィンドウが出ます.
ウィンドウ最上段の "Positioning" にある "Name of Tobii" の入力欄に,接続する Tobii の固有名が入っていることを確認してください.もし異なる文字列が入っている場合は,上記「Tobii との接続チェック」でコピーした Tobii 固有名をここにペーストしてください.
正しい Tobii 固有名を与えたら,[Start] ボタンを押して,ユーザの眼球位置を計測します.下図のように,2つの「目玉」が見えるはずです.計測可能範囲(黒い背景の部分)の中央付近に「目玉」がくるように,また,Tobii 前面から被験者の目までの距離が 600mm 程度になるように,ユーザの姿勢を調整してください.(Tobii の位置や向きを変えた場合は「準備3:Tobii の位置決め」に戻って実測・登録しなおしてください.)
キャリブレーションとは,ユーザの眼球特性を計測・登録することです.ユーザ(あるいは被験者)ごとに行なう必要があります.まず,ウィンドウ2段目の "Calibration" で,キャリブレーション点の数を設定します.デフォルトは [5 points] です.状況に応じて,適切な点数を選択してください.(経験的に言って,ユーザに負担をかけない [5 points] あるいは [2 points] がよい結果をもたらすようです.)
以上の準備が整ったら,ユーザに「間もなくマーカが出てきます.それを目で追いかけてください」と教示します.心の準備ができたようなら [Calibrate] をクリックして,キャリブレーションを開始します.すると下図のようなマーカが出てきて,移動したり停留したりを何度か繰り返します.停留時にはマーカが伸縮し,凝視を促すようになっています.
キャリブレーションが終了すると,"Calibration" の右側にある表示領域(白い背景の部分)にキャリブレーション結果が表示されます.それぞれの小円の内部に視線がおおよそ収まっているようなら合格です.不合格の場合は [Calibrate] あるいは [Recalibrate] を押してキャリブレーションを再実行してください.
これで視線計測の準備が整いました.ウィンドウ3段目の "Gaze Tracking" にある [Start] を押して視線計測を開始します.視線計測が正常に行なわれているかを確認するために,その横にある "Show Marker" をオンにして,小さな四角いマーカをスクリーン上に表示してみてください.ユーザの視線の先にこのマーカが表示されれば成功です.Tobii からユーザ眼球までの距離に応じて,マーカの色が変化します.明るい緑色が「ベスト」な距離(600mm)を意味します.また,視線計測中に [Update] を押すことで,この距離を数値として表示できます.
もしマーカの位置が不正確だったり,動きが断続的であったりした場合は,キャリブレーションに戻って再調整してみてください.ユーザの眼球特性や周囲の照明条件・背景条件などに左右されますが,こじ研では,1m 先のスクリーン上で ±1cm 程度の誤差範囲にマーカが入っていれば合格と考えています.
視線計測を [Start] しただけでは,まだサーバ機能(クライアントへの視線データの提供)は開始していません.サーバ機能を開始するには,ウィンドウ最下段の "Server Status" の [Update] を押します.すると,TobiiServer が動作しているホストの IP アドレスが表示され,接続されたクライアントがあれば "connected",無ければ "no client" と表示されます.これら表示を更新するには [Update] を再び押してください.
なお,TobiiServer のサーバ機能を初めて利用するとき,Windows の設定(ファイアウォール)によっては,下のようなウィンドウが表示されることがあります.ポート 16439 への外部からの接続がブロックされているので,[ブロックを解除する] を押して接続可能にしてください.
クライアントからは,表示された IP アドレスのポート 16439 に接続することで,視線データを取得することができます.その方法については,次章「TobiiClient API の利用方法」で説明します.(TobiiClient API を利用するのであれば,ポート番号を意識する必要はありません.)
アプリケーション(クライアント)は,TobiiClient API という C で書かれた関数群をとおして TobiiServer と通信します.ここでは,TobiiClient API の組み込み方や各 API 関数の使い方について説明します.TobiiClient API は下記のリンクからダウンロードしてください.(TobiiServer については,現在のところ,こじ研内部のみで公開しています.)
- TobiiClient API ダウンロード
- TobiiClient.c (8KB):TobiiClient API ソースファイル
- TobiiClient.h (2KB):TobiiClient API ヘッダファイル
- TobiiData.h (2KB):TobiiClient API データ型定義ファイル
- sampler.c (2KB):TobiiClient API サンプルプログラム
最もシンプルなアプリケーション(クライアント)は,(1) TobiiServer に接続し,(2) 視線データを取得・表示し,(3) TobiiServer から切断する,というものです.このコンソールアプリケーション(sampler.c)はつぎのような C プログラムとなります.
#include <stdio.h> #include "TobiiClient.h" int main (int argc, char *argv[]) { int res, i; // (1) TobiiServer に接続(要アドレス設定) res = TobiiConnect("172.30.1.159"); if (res == -1) { // 接続失敗 fprintf(stderr, "** error: cannot connect to the server\n"); return 1; } printf("** connected to the server\n"); // 100ms ごとに視線データを取得・表示(50回繰り返す) for (i = 0; i < 50; i++) { TobiiGazeData gaze; // (2) TobiiServer から視線データを取得 TobiiGetData(&gaze); // 画面上の X-Y 座標を表示 printf("** got gaze %d (%f, %f)\n", i, (gaze.x_gazepos_lefteye + gaze.x_gazepos_righteye) / 2.0, (gaze.y_gazepos_lefteye + gaze.y_gazepos_righteye) / 2.0 ); // 時間調整(100ms 待つ) TobiiSleep(100); } // (3) TobiiServer から切断 TobiiDisconnect(); printf("** disconnected from the server\n"); return 0; }
TobiiClient API を組み込むには,sampler.c と TobiiClient.c を一緒にコンパイルすればよいでしょう.こじ研では TobiiServer を 32bit 環境で運用していますので,アプリケーション(クライアント)も同じく 32bit でコンパイルしてください.Mac・Linux では "-m32" というオプションを "cc" に与えればよいでしょう.Windows(Visual C++ など)では「Win32 コンソール アプリケーション」としてビルドしてください.
maclinux> cc -m32 sampler.c TobiiClient.c -o sampler maclinux> sampler ** connected to the server ** got gaze 0 (0.539938, 0.467909) ** got gaze 1 (0.543083, 0.449185) ** got gaze 2 (0.462024, 0.542860) ** got gaze 3 (0.560533, 0.454456) ** got gaze 4 (0.525900, 0.498549) ...(途中省略)... ** got gaze 95 (0.955135, 0.794099) ** got gaze 96 (0.928980, 0.835921) ** got gaze 97 (0.930002, 0.796484) ** got gaze 98 (0.905181, 0.839132) ** got gaze 99 (0.924465, 0.822460) ** disconnected from the server maclinux>
このように,100ms ごとにスクリーン上の視線座標が表示されます.得られる視線座標は,スクリーンの左上端を原点 (0, 0) ,右下端を (1.0, 1.0) とする X-Y 座標系によるものです.それぞれの成分にスクリーンの幅と高さ(ピクセル数あるいは物理的な長さ)をかけることで,使いやすい座標系に変換することができます.
TobiiClient API は,そのヘッダファイル TobiiClient.h に記述されているように,TobiiServer との接続・切断・データ取得などのための5つの関数から成ります.
#include "TobiiData.h" int TobiiConnect (char *server_name); void TobiiDisconnect (); int TobiiIsConnected (); void TobiiGetData (TobiiGazeData *gaze_data); void TobiiSleep (int msec);
- int TobiiConnect (char *server_name)
server_name で示されるホスト上で動作している TobiiServer に接続します.使用するポートは 16439 です.接続が成功するには,TobiiServer 側でクライアントへの視線データの提供準備が出来ている必要があります.接続が成功するとこの関数は 0 を返し,失敗すると −1 を返します.通常,アプリケーション(クライアント)の起動時に1回だけ呼び出します. - void TobiiDisconnect()
TobiiServer との接続を切ります.通常,アプリケーション(クライアント)の終了時に呼び出します. - int TobiiIsConnected()
TobiiServer と接続されているならば 1 を返し,切断されているならば 0 を返します. - void TobiiGetData (TobiiGazeData *gaze_data)
TobiiServer で計測された最新の視線データを取得し,ポインタ gaze_data によって参照される TobiiGazeData 型データに格納します.TobiiGazeData 型の詳細については後述します.Tobii X120 は,デフォルトで 60Hz,設定により最高 120Hz の周期で視線データを計測できます.視線計測よりも速い周期で TobiiGetData を呼び出すと,同じ視線データが複数回取得されることがあります. - void TobiiSleep(int msec)
msec で示された時間(単位は ms)だけスリープします.Windows 上の Sleep(int msec) と Mac・Linux 上の usleep(int usec) の単位差を解消するためのラッパ関数です.TobiiGetData を呼び出す周期を調整するために使います.
TobiiGetData によって取得される TobiiGazeData 型(TobiiData.h で定義されています)のデータは,下記の項目をもちます.よく利用するのは,左右の目が画面上のどこを見ているのかを表わす x_gazepos_lefteye, y_gazepos_lefteye, x_gazepos_righteye, y_gazepos_righteye の4つです.
struct _TobiiGazeData { // 時刻 int timestamp_sec; // 視線データの取得時刻(秒) int timestamp_microsec; // 視線データの取得時刻(マイクロ秒) // 左目 float x_gazepos_lefteye; // 画面上の視線位置(左目;X) float y_gazepos_lefteye; // 画面上の視線位置(左目;Y) float x_camerapos_lefteye; // Tobiiから見た目の位置(左目;X) float y_camerapos_lefteye; // Tobiiから見た目の位置(左目;Y) float diameter_pupil_lefteye; // 瞳の直径(左目;ミリ) float distance_lefteye; // 目までの直線距離(左目;ミリ) int validity_lefteye; // データ有効性(0=良,1-3=片,4=逸) // 右目 float x_gazepos_righteye; // 画面上の視線位置(右目;X) float y_gazepos_righteye; // 画面上の視線位置(右目;Y) float x_camerapos_righteye; // Tobiiから見た目の位置(右目;X) float y_camerapos_righteye; // Tobiiから見た目の位置(右目;Y) float diameter_pupil_righteye; // 瞳の直径(右目;ミリ) float distance_righteye; // 目までの直線距離(右目;ミリ) int validity_righteye; // データ有効性(0=良,1-3=片,4=逸) }; typedef struct _TobiiGazeData TobiiGazeData;
- timestamp_sec, timestamp_microsec
視線データが計測された時刻を表わします.前者が秒の単位,後者がマイクロ秒(1/100万秒)の単位です.前者が 123, 後者が 45678 であれば,123.045678 秒となります.アプリケーション側で基準となる時刻をあらかじめ取得して,それとの差をとることで,経過時間を計算してください. - x_gazepos_lefteye, y_gazepos_lefteye
左目がスクリーン上のどこを見ているのかを X座標・Y座標で表わします.スクリーンの左上が原点 (0.0, 0.0),右下が (1.0, 1.0) となります.それぞれにスクリーンの幅と高さ(ピクセル数あるいは物理的な長さ)をかけることで,使いやすい座標系に変換することができます. - x_camerapos_lefteye, y_camerapos_lefteye
Tobii からみた左目の方向(角度)を X座標・Y座標で表わします.Tobii のセンシング範囲の左上が原点 (0.0, 0.0),右下が (1.0, 1.0) となります. - diameter_pupil_lefteye
Tobii からみえる左目の瞳孔の大きさ(楕円をフィッティングしたときの長軸の長さ)を表わします.単位はミリメートル(mm)です.絶対値よりも相対的な変化のみの利用をおすすめします. - distance_lefteye
Tobii から左目までの距離を表わします.単位はミリメートル(mm)です.眼鏡の有無などに影響を受けるため,あくまで相対的な変化のみの利用をおすすめします. - validity_lefteye
視線データの有効性を符号化したものです.0 ならば計測に成功し,そのデータが左目のものであることが確実であることを表わしています.4 ならば左目の計測に失敗していることを表わしています.1〜3 は片目のみの計測データが得られていることを表わしています.1 はその計測データが左目のものであるとほぼ推定できることを表わしています.2 はその計測データがどちらの目のものか区別できないことを表わしています.3 はその計測データが反対側の目(右目)のものであるとほぼ推定できることを表わしています.
同様に,_righteye で終わる項目については,上の記述で「左目」と「右目」を入れ替えた意味をもちます.また,validity_lefteye と validity_righteye は,(0, 0), (4, 4), (4, 0), (0, 4), (1, 3), (3, 1), (2, 2) の7通りの値をとります.(0, 0) ならば左右の目それぞれに有効なデータが得られ,(4, 4) ならば両目とも有効なデータは得られていません.それ以外の場合は,左右の目について同じデータが得られています.