noteタイトル_アートボード_1

展示のためにTobii社の超高性能アイトラッカーをPythonで取得して遊んでみた

こんにちは、インタラクションデザインの渡邊研究室の代表の渡邊恵太です。
3月8日(金)、9日(土)の渡邊研プロトタイプ展2019 に向けて連載企画をはじめます。
展示で展示する作品や、考え方について紹介していきたいと思います。

第2回目は、学部3年生の相澤くんにPythonを用いたTobiiアイトラッカーの使用方法ついて紹介してもらいたいと思います。

Pythonを用いたTobiiアイトラッカーの使用方法

こんにちは、学部3年の相澤です。

私は、渡邊先生のダミーカーソル実験における視線の動きを分析する研究を行なっています。

この研究では1秒に300回も視線を取得する超高性能アイトラッカー「Tobii TX-300」を使用しました。視線には、固視(視線が止まった状態)とサッケード(視線が高速で動いている状態)の2種類があり、1秒に300回の視線取得では「サッケード」と判定されるにも関わらず、1秒に60回の視線取得では「固視」と判定されてしまうことがあります。アイトラッキングの研究では、実際の目の動きの状態を知りたいため、1秒間に多くの視線データを得ることができるアイトラッカーが必要不可欠となるのです。

ただ研究だけに使うのはもったいないと考えた私は、視線を使ったアート作品を作ってみました。

この作品はPythonを用いて アイトラッカーから視線データを取得し、Processingでアニメーションを描画しています。Tobii社はアイトラッカー開発用のSDKを提供しており、Pythonを用いて簡単にアイトラッカーを使用することができるようになっています。もちろんTobii TX-300以外のアイトラッカーでも使用することが可能です。そこで今回は、Pythonでのアイトラッキングプログラムの作成方法とライブラリの簡単な説明をしたいと思います。

今回の環境設定


OS: Windows10
Python環境: anaconda, Python3.5.6
アイトラッカー: Tobii TX-300

Pythonのバージョン

TobiiのPython SDKはPython2.7.xまたは3.5.xしかサポートしていません。今回使用したPCにはPython3.6.xしか入っていなかったので、Python3.5(2.7)の環境を作ってから、以下の作業を行なっています。anacondaで現在のPython環境を保ちつつ、Python3.5.x(2.7.x)の環境を作成する方法はこちらの記事をご覧ください。

サポートしているアイトラッカー

以下のアイトラッカーはTobii Pro SDKを使うことが可能です。

発売している(2019/3/1現在)
・Tobii Pro スペクトラム
・Tobii Pro TX300(今回使用したアイトラッカー)
・Tobii Pro T60 XL
・Tobii Pro X3-120
・Tobii Pro X2
・Tobii Pro VR Integration (HTC Vive ヘッドマウントディスプレイ(HMD))

発売していない(2019/3/1現在)
・Tobii T120
・Tobii T60
・Tobii X120
・Tobii X60

Python SDKのインストール方法

ここではSDKのインストール方法を紹介します。

1. prosdk-addons-pythonをGitHubからクローンまたはダウンロードする
まずGitHubからprosdk-addons-pythonをクローンまたはダウンロードしてください。場所はどこでも構いません。

2. SDKをインストールする
そのフォルダの中で次のコマンドを打ってください。

<C:¥yourpath¥prosdk-addons-python> pip install .

これでSDKのインストールが完了しました。

視線のキャリブレーション

ここでは視線キャリブレーションの方法とそのコード(calibration.py)の解説をします。

キャリブレーションの方法

視線のキャリブレーションは、上の図のように5つの点における目の向きを計測することで行います。この5つの点のうち1つでもキャリブレーションを失敗してしまうと、視線を正確に取得することができなくなります。
この5つの点は、画面の右上の座標を(0, 0)、画面の左下の座標を(1, 1)としたときに、(0.5, 0.5)、(0.1, 0.1)、(0.1, 0.9)、(0.9, 0.1)、(0.9, 0.9)の位置にそれぞれ設置してください。そして、体験者は各々の点を数秒凝視して、視線のキャリブレーションを行います。

calibration.py
ここではcalibration.pyの解説をします。calibration.pyは名前の通り、視線を調整(キャリブレーション)するプログラムです。

まずTobiiのPythonライブラリをインポートします。

import tobii_research as tr

そのあと接続されているアイトラッカーを取得し、その中から一台選びます。

found_eyetrackers = tr.find_all_eyetrackers()
my_eyetracker = found_eyetrackers[0]

次にキャリブレーションするモードに切り替えます。

calibration = tr.ScreenBasedCalibration(eyetracker)
calibration.enter_calibration_mode()

そしていよいよキャリブレーションを行います。

points_to_calibrate = [(0.5, 0.5), (0.1, 0.1),
                           (0.1, 0.9), (0.9, 0.1), (0.9, 0.9)]
for point in points_to_calibrate:
    print(("Show a point on screen at {0}.").format(point))
    draw_caribration_points(point)
        
    print(("Collecting data at {0}.").format(point))
        
    if calibration.collect_data(point[0], point[1]) != tr.CALIBRATION_STATUS_SUCCESS:
        calibration.collect_data(point[0], point[1])

キャリブレーションが終わると、5つの点のうち、いくつの点のキャリブレーションに成功したかを表示します。5つともキャリブレーションを成功したときは「calibration_status_success」と表示しますが、どれか一つでもキャリブレーションを失敗すると、「calibration_status_failure」と表示します。

calibration_result = calibration.compute_and_apply()
print(("Compute and apply returned {0} and collected at {1} points.").
      format(calibration_result.status, len(calibration_result.calibration_points)))
      
# 成功していたときは「5points」と表記される
# Compute and apply returned calibration_status_success and collected at 5 points.
	
# 失敗した時は「0points」や「3points」など5以下の数字が出てくる
# Compute and apply returned calibration_status_failure and collected at 0 points.
	

最後にキャリブレーションモードを終了します。

calibration.leave_calibration_mode()

視線の取得

ここでは視線を取得するコード(get_gaze_data.py)の解説をします。

get_gaze_data.py
get_gaze_data.pyは、実際にアイトラッカーで取得した視線データを取得するプログラムです。Tobiiのライブラリでは、アイトラッカーから視線データを送られたときに、 gaze_data_callback() というコールバック関数が呼び出されて視線データを取得します。

def gaze_data_callback(gaze_data):
    # 視線データ一覧を参照
    for key in gaze_data:
	print(key + ':')
	print(gaze_data[key])
	# Example
	# right_gaze_point_on_display_area: 
	# {0.5, 0.4}

得られる視線データには視線の位置だけでなく、HMD型のアイトラッカーにおける視線の奥行き情報や、そのデータを取得した時のタイムスタンプ、さらには瞳孔の大きさなどが載っています。今回は、2Dディスプレイでの視線データ(right_gaze_point_on_display_area, right_gaze_point_on_display_area)を使います。

right_gaze_data = gaze_data['right_gaze_point_on_display_area']
left_gaze_data = gaze_data['left_gaze_point_on_display_area']
print('right_gaze_x = ' + str(right_gaze_data[0]))
print('right_gaze_y = ' + str(right_gaze_data[1]))
print('left_gaze_x = ' + str(left_gaze_data[0]))
print('left_gaze_y = ' + str(left_gaze_data[1]))


gaze_data['right_gaze_point_on_display_area']は二次元配列になっていて、0番目にx座標、1番目にy座標が格納されています。気をつけて欲しいのは、それらの値は0から1の値を返します。これは先ほどのキャリブレーションのときに、画面左上の座標を(0, 0)で右下の座標を(1, 1)と設定しているためです。また左右両方の目のx, y座標のデータがあるので、実際の視線座標を導き出すには以下のような処理が必要になります。

real_gaze_x = (right_gaze_data[0] + left_gaze_data[0]) / 2.0 * SCREEN_WIDTH
real_gaze_y = (right_gaze_data[1] + left_gaze_data[1]) / 2.0 * SCREEN_HEIGHT
                 
print('real_gaze_x = ' + str(real_gaze_x))     
print('real_gaze_y = ' + str(real_gaze_y))            

SCREEN_WIDTHとSCREEN_HEIGHTは使用しているディスプレイの解像度です。今回だと解像度が1920x1080のディスプレイを使っているので、SCREEN_WIDTH = 1920でSCREEN_HEIGHT = 1080となります。

これで視線の座標データを取得することが可能になりました。

Processingを使った可視化

この取得した視線の座標データを用いて、視線の可視化を行いました。Pythonで視線を可視化するのは難しかったので、アニメーション描画が得意なProcessingにTCP通信で座標データを渡すことで可視化しました。

この可視化したコードと今回解説したコードは、全て以下のGitHubに載せています。

展示会作品


さて、タイトルにもありましたがこの技術は展示会で出展している作品にも使用しています。

ダミーカーソルゲームは、ダミーカーソル実験を応用した作品です。たった一つだけあるマウスと連動した本物のカーソルを発見し、画面中央にあるターゲットをクリックするとクリアになります。果たして皆さんは何秒で本物を見つけることができるでしょうか。

また、ゲーム終了後のリプレイで、本物を探している時の視線の動きを見ることができます。そこには自分でも気づかなかった意外な視線の動きが見られると思います。ぜひ展示会でダミーカーソルゲームを体験してみてください。


参考記事・参考サイト

- 公式リファレンス
Windows で,隔離された Python 3.5 環境を作る(Anaconda を利用)
prosdk-addons-python
- TobiiProSetup
Tobii eye-tracking with Psychopy 3?
- Tobii Pro SDK Python API

著者プロフィール

相澤裕貴
明治大学総合数理学部先端メディアサイエンス学科 3年
ポートフォリオ: https://www.resume.id/zawa_works
Twitter: https://twitter.com/Zawa_works

この記事が気に入ったらサポートをしてみませんか?