opengaze/src/input_handler.cpp

185 lines
6.6 KiB
C++
Raw Permalink Normal View History

2019-01-10 13:26:03 +01:00
#include "input_handler.hpp"
#include <iostream>
#include <cstdlib>
using namespace cv;
using namespace std;
namespace opengaze {
#if WIN32
#include <windows.h>
#else
#include <X11/Xlib.h>
#endif
void InputHandler::getScreenResolution(int &width, int &height) {
#if WIN32
width = (int) GetSystemMetrics(SM_CXSCREEN);
height = (int) GetSystemMetrics(SM_CYSCREEN);
#else
Display* disp = XOpenDisplay(NULL);
Screen* scrn = DefaultScreenOfDisplay(disp);
width = scrn->width;
height = scrn->height;
#endif
}
InputHandler::InputHandler(){
input_type_ = InputType::Camera;// defualt input type
camera_id_ = 0;
getScreenResolution(screen_width_, screen_height_);
screen_width_ = screen_width_;
}
InputHandler::~InputHandler(){}
void InputHandler::initialize()
{
if (input_type_ == InputType::Camera){
cap_.open(camera_id_);
if(!cap_.isOpened()) { // open Camera
cout << "Could not open Camera with id " << camera_id_ << endl;
std::exit(EXIT_FAILURE);
}
setFrameSize(1280, 720); // 800*600, 1280*720, 1920*1080,
}
else if (input_type_ == InputType::Video){
cap_.open(input_file_video_name_);
if(!cap_.isOpened()) { // open Camera
cout << "Error: Could not open video file " << input_file_video_name_ << endl;
std::exit(EXIT_FAILURE);
}
}
else if (input_type_ == InputType::Directory) {
if (!boost::filesystem::is_directory(input_path_)){
cout << "Error: The input must be a directory, but it is " << input_path_ << endl;
std::exit(EXIT_FAILURE);
}
current_itr_ = boost::filesystem::directory_iterator(input_path_);
}
else if (input_type_ == InputType::Memory) {}
is_reach_end_ = false;
}
void InputHandler::setFrameSize(int frame_width, int frame_height){
cap_.set(cv::CAP_PROP_FRAME_HEIGHT, frame_height);//720 1080
cap_.set(cv::CAP_PROP_FRAME_WIDTH, frame_width);//1280 1980
double dWidth = cap_.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
double dHeight = cap_.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video
cout << "Input frame size is : " << dWidth << " x " << dHeight << endl;
}
Mat InputHandler::getNextSample() {
Mat frame;
if (input_type_ == InputType::Camera) cap_ >> frame;
else if (input_type_ == InputType::Video) {
cap_ >> frame;
if (frame.empty()) // we reach the end of video
is_reach_end_ = true;
}
else if (input_type_ == InputType::Directory) {
boost::filesystem::path file_path = current_itr_->path();
if (file_path.extension() != ".jpg" && file_path.extension() != ".png" && file_path.extension() != ".bmp"){
cout << "Error: The input file is not image file with extension of jpg, png or bmp!" << endl;
cout << "The input file name is: " << file_path.string() << endl;
std::exit(EXIT_FAILURE);
}
cout << "process image " << file_path << endl;
frame = imread(file_path.string());
if (current_itr_ == boost::filesystem::directory_iterator())
is_reach_end_ = true;
}
else if (input_type_ == InputType::Memory) {}
return frame;
}
bool InputHandler::closeInput() {
if (input_type_ == InputType::Camera || input_type_ == InputType::Video){
cap_.release();
is_reach_end_ = true;
}
return true;
}
void InputHandler::setInput(std::string input_path) {
if (input_type_ == InputType::Directory){
input_path_ = move(input_path);
}
else if (input_type_ == InputType::Video){
input_file_video_name_ = move(input_path);
}
}
void InputHandler::readScreenConfiguration(string calib_file) {
FileStorage fs_disp(calib_file, FileStorage::READ);
fs_disp["monitor_W"] >> monitor_W_;
fs_disp["monitor_H"] >> monitor_H_;
fs_disp["monitor_R"] >> monitor_R_;
fs_disp["monitor_T"] >> monitor_T_;
// compute monitor plane
Vec3f corners[4];
corners[0] = Vec3f(0.0, 0.0, 0.0);
corners[1] = Vec3f(monitor_W_, 0.0, 0.0);
corners[2] = Vec3f(0.0, monitor_H_, 0.0);
corners[3] = Vec3f(monitor_W_, monitor_H_, 0.0);
for(int i=0; i<4; i++){
Mat corners_cam = monitor_R_ * Mat(corners[i]) + monitor_T_;
corners_cam.copyTo(monitor_corners_[i]);
}
Vec3f normal = Vec3f(0.0, 0.0, 1.0); // normal direction
monitor_normal_ = monitor_R_ * Mat(normal);
monitor_normal_.convertTo(monitor_normal_, CV_32F);
}
void InputHandler::readCameraConfiguration(string calib_file){
cout << endl << "Reading calibration information from : " << calib_file << endl;
FileStorage fs;
fs.open(calib_file, FileStorage::READ);
fs["camera_matrix"] >> camera_matrix_;
fs["dist_coeffs"] >> camera_distortion_;
fs.release();
}
void InputHandler::projectToDisplay(std::vector<opengaze::Sample> &inputs, bool is_face_model) {
for(auto & sample : inputs) {
if (is_face_model) {
Vec3f face_center(sample.face_patch_data.face_center.at<float>(0), sample.face_patch_data.face_center.at<float>(1), sample.face_patch_data.face_center.at<float>(2));
sample.gaze_data.gaze2d = mapToDisplay(face_center, sample.gaze_data.gaze3d);
}
else {
Vec3f leye_pose(sample.eye_data.leye_pos.at<float>(0),sample.eye_data.leye_pos.at<float>(1),sample.eye_data.leye_pos.at<float>(2));
Vec3f reye_pose(sample.eye_data.reye_pos.at<float>(0),sample.eye_data.reye_pos.at<float>(1),sample.eye_data.reye_pos.at<float>(2));
sample.gaze_data.lgaze2d = mapToDisplay(leye_pose, sample.gaze_data.lgaze3d);
sample.gaze_data.rgaze2d = mapToDisplay(reye_pose, sample.gaze_data.rgaze3d);
float gaze_x = (sample.gaze_data.lgaze2d.x + sample.gaze_data.rgaze2d.x) / 2.0f;
float gaze_y = (sample.gaze_data.lgaze2d.y + sample.gaze_data.rgaze2d.y) / 2.0f;
sample.gaze_data.gaze2d.x = gaze_x;
sample.gaze_data.gaze2d.y = gaze_y;
}
}
}
cv::Point2f InputHandler::mapToDisplay(Vec3f origin, Vec3f gaze_vec) {
Point2f gaze_on_screen;
// compute intersection
float gaze_len = (float)(monitor_normal_.dot(Mat(monitor_corners_[0]-origin))/monitor_normal_.dot(Mat(gaze_vec)));
Vec3f gaze_pos_cam = origin + gaze_len * gaze_vec;
// convert to monitor coodinate system
Mat gaze_pos_ = monitor_R_.inv() * (Mat(gaze_pos_cam) - monitor_T_);
Vec3f gaze_pos_3d;
gaze_pos_.copyTo(gaze_pos_3d);
gaze_on_screen.x = gaze_pos_3d.val[0] / monitor_W_;
gaze_on_screen.y = gaze_pos_3d.val[1] / monitor_H_;
return gaze_on_screen;
}
}