なにするの?
ノートパソコン(MacBook Pro)についているWebカメラ(FaceTime HD カメラ)を使って
自分がディスプレイのどこを見ているのか、つまり視線を推定する仕組みを作りたい。
視線検出って今まではどんなのがあるの?
アイトラッキングといえばTobii社なんですが、すごい機材にすごい値段でとても手が出ない。
www.tobiipro.com
性能は抜群らしい。
なんなら、こんな安いラインナップもある。
というわけで、どちらかと言うと内蔵Webカメラだと何が難しいのかをやってみることで知ろうというのが大きい。
どんな手順でやるの?
1, データセット作成アプリを作る→(今日はここ)
2, 自分の顔でデータセットを作る→(苦行)
3, 性能の良い画像解析系のCNNを流用(転移学習)して構築する→(先日までやってたやつ)
4, 色んな所を見ている顔のデータを学習する→(辛抱強く待つ)
5, 実際に稼働させて目線の座標がざっくり分かったら嬉しい
データセット作成アプリを作る
作ったアプリ
主な機能としては、「見るべき場所を表示する」「Webカメラの画像を切り出して保存する」の2つ
見るべき場所を表示するでは、全画面表示したところに黒い点を表示してそこに目線を合わせるようにする。
Webカメラの画像を切り出して保存するでは、HDから中心付近を切り出してちょうどいいサイズに縮めて保存する。
便利にする機能としては、チカチカ切り替わっても難しいので、開始前のディレイ(約3秒)で瞬きとかをする余裕ができるようにした。
ディレイのときには中心にWebカメラでキャプチャした映像が表示されて大まかな画角が把握できるようにした。
データのとり方
表示された黒点に目線を合わせながら首とか体とかを動かしていろんなタイプの注視画像を用意する。
アプリが使えることの確認のために20フレーム分ずつ作ってみた。
できました。無事オタクの顔が並んでいます。
(もう少し明るくしてやればよかった。本番ではもっと明るくしてやる)
コード
import processing.video.*; Capture cam; int r = 30; int col = 4; int row = 6; int area_w = 210; int area_h = 210; int xp = 0; int yp = 0; int count = 0; int wait = 0; void setup() { fullScreen(); frameRate(5); String[] cams = Capture.list(); cam = new Capture(this, cams[0]); cam.start(); } void draw() { //注視点を表示しているところ fill(255); noStroke(); rect(0, 0, width, height); fill(10); noStroke(); ellipse(width/(row) * xp, height/(col) * yp, r, r); // 注視点を更新するところ(ここで20回に制限している) if(count > 20){ count = 0; wait = 0; xp = xp + 1; if(xp > row){ xp = 0; yp = yp + 1; if(yp > col+1){ exit(); } } } // 次の注視点を表示しつつ待つところ if(wait < 15){ wait = wait + 1; if(cam.available()){ cam.read(); PImage img = cam.copy(); img.resize(img.width/2, img.height/2); img = img.get(img.width/2-area_w/2, img.height/2-area_h/2, area_w, area_h); set(width/2-img.width/2, height/2-img.height/2, img); } return; } // 目線画像を保存するところ if(cam.available()){ cam.read(); PImage img = cam.copy(); img.resize(img.width/2, img.height/2); img = img.get(img.width/2-area_w/2, img.height/2-area_h/2, area_w, area_h); String pos = xp + "_" + yp + "/"; String path = "/Users/ensekitt/dev/eye_datas/" + pos + count + ".jpg"; img.save(path); count++; } }
processing.videoは以下を入れると使える。
で、5までやったらできるの?
書き溜めとかじゃないのでまじでわからないけど、頑張ってみる。