#include "input_handler.hpp" #include #include using namespace cv; using namespace std; namespace opengaze { #if WIN32 #include #else #include #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 &inputs, bool is_face_model) { for(auto & sample : inputs) { if (is_face_model) { Vec3f face_center(sample.face_patch_data.face_center.at(0), sample.face_patch_data.face_center.at(1), sample.face_patch_data.face_center.at(2)); sample.gaze_data.gaze2d = mapToDisplay(face_center, sample.gaze_data.gaze3d); } else { Vec3f leye_pose(sample.eye_data.leye_pos.at(0),sample.eye_data.leye_pos.at(1),sample.eye_data.leye_pos.at(2)); Vec3f reye_pose(sample.eye_data.reye_pos.at(0),sample.eye_data.reye_pos.at(1),sample.eye_data.reye_pos.at(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; } }