之前成功在 Ubuntu 下使用了 4C 眼动仪,但是不知道什么原因目前无法使用 TobiiProEyeTrackerManager 软件来进行眼动仪的标定,也就无法使用它的 gaze visualization 功能来查看注视点的位置。虽然程序里可以输出注视点的归一化坐标,但是这样还是不直观,所以尝试了一下用 tobii 检测到的注视点位置来控制鼠标光标的位置。
除了之前那个 github 工程,还参考了这个工程: https://github.com/lhy0403/TobiiMouse.讲道理这个应该可以直接用的,不过调通后怎么也检测不到设备,所以将其中控制鼠标的部分提出来和之前的结合。
其中和鼠标控制有关的部分在 mouse_integration 和 noise_cancellation 中
在主函数一开始添加
MouseIntegration::init();//get the width and height of current screen
MouseIntegration::SetWorkingMode(TOBII_MOUSE_MODE_ABSOLUTE);
在 gaze_point_callback 中添加
MouseIntegration::OnGaze(gaze_point->position_xy[0], gaze_point->position_xy[1]);
mouse_integration 如下, noise_cancellation 没有改
mouse_integration.h
#ifndef MOUSE_INTEGRATION_H
#define MOUSE_INTEGRATION_H
#include <tuple>
//#include "tobiimouse.h"
#include "noise_cancellation.h"
#include <X11/X.h>
#include "X11/Xlib.h"
#include <X11/extensions/Xrandr.h>
using namespace std;
enum MOUSEWORKINGMODE_E{
TOBII_MOUSE_MODE_ABSOLUTE,
TOBII_MOUSE_MODE_MOVE_BY_POSITION,
};
namespace MouseIntegration
{
void SetWorkingMode(MOUSEWORKINGMODE_E mode);
void init();
void MoveMouseTo(int x, int y);
void MoveMouseOffset(int x, int y);
tuple<int, int> ProcessGazePosition(float x, float y);
void OnGaze(float x, float y);
};
#endif // MOUSE_INTEGRATION_H
mouse_integration.cpp
#include "mouse.h"
#include <iostream>
#include <vector>
namespace MouseIntegration
{
static MOUSEWORKINGMODE_E WorkingMode;
static int ScreenHeight;
static int ScreenWidth;
static int LastX;
static int LastY;
static Display* _display;
static Window _root_window;
}
void MouseIntegration::init()
{
NoiseCancellation::init();//used to filter the data
// TODO: Multiple Display supports.
_display = XOpenDisplay(None);
_root_window = XRootWindow(_display, 0);
XRRScreenResources *screens = XRRGetScreenResources(_display, DefaultRootWindow(_display));
XRRCrtcInfo *info = XRRGetCrtcInfo(_display, screens, screens->crtcs[0]);
ScreenWidth = info->width;
ScreenHeight = info->height;
XRRFreeCrtcInfo(info);
XRRFreeScreenResources(screens);
}
void MouseIntegration::MoveMouseTo(int x, int y)
{
XSelectInput(_display, _root_window, KeyReleaseMask);
XWarpPointer(_display, None, _root_window, 0, 0, 0, 0, x, y);
XFlush(_display);
}
void MouseIntegration::SetWorkingMode(MOUSEWORKINGMODE_E mode)
{
WorkingMode = mode;
}
tuple<int, int> MouseIntegration::ProcessGazePosition(float x, float y)
{
float width = ScreenWidth;
float height = ScreenHeight;
auto realGazeX = width * x;
auto realGazeY = height * y;
auto filtered = NoiseCancellation::CancelNoise(realGazeX,realGazeY);
//auto count = ScreenCount(_display); //Get total screen count.
float gazeX_f = get<0>(filtered);
float gazeY_f = get<1>(filtered);
return tuple<int, int>(static_cast<int>(gazeX_f), static_cast<int>(gazeY_f));
}
void MouseIntegration::OnGaze(float x, float y)
{
auto data = ProcessGazePosition(x,y);
auto posiX = get<0>(data);
auto posiY = get<1>(data);
switch (WorkingMode) {
case TOBII_MOUSE_MODE_ABSOLUTE:
MoveMouseTo(posiX, posiY);
break;
case TOBII_MOUSE_MODE_MOVE_BY_POSITION:
MoveMouseOffset(posiX, posiY);
break;
}
LastX = posiX;
LastY = posiY;
}
使用的 IDE 是 Qt Creator,工程的 pro 文件如下
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += main.cpp\
mouse_integration.cpp\
noise_cancellation.cpp
HEADERS +=mouse_integration.h\
noise_cancellation.h
LIBS += -L$$PWD/lib/lib/x64/ -ltobii_stream_engine
LIBS += -L$$/lib/x86_64-linux-gnu/ -lpthread
LIBS += -L$$/usr/lib/x86_64-linux-gnu/ -lX11
LIBS += -L$$/usr/lib/x86_64-linux-gnu/ -lXrandr
开始编译的时候会出现链接库找不到的问题,主要是因为用到了 X11 这个库,但是没有链接,可以通过
locate libX11 libXrandr
找到 libX11、libXrandr 的位置,然后在 pro 文件中加上链接库的位置即可。