Newer
Older
PrismSoftware / ECTrainer2 / ECTrainerGUI.cpp

#include "ECTrainer.h"
#include "ECTrainerGUI.h"

#define CVUI_IMPLEMENTATION
#include "cvui.h"

#ifdef _DEBUG
#include <iostream>
#endif

// コンストラクタ
ECTrainerGUI::ECTrainerGUI(ECTrainer* pEct) :BaseProcess(pEct) {
}

// 初期化
bool ECTrainerGUI::Init() {
	// 実行環境の情報取得
	GetDisplayInfo();
	// GUIウインドウ
	cvui::init(WIN_MAIN);
	_MainFrame.create(MAIN_FRAME_SIZE, CV_8UC3);
	// 刺激提示ウインドウ
	cv::namedWindow(WIN_DISP, cv::WINDOW_NORMAL | cv::WINDOW_OPENGL);
	if (_Displays.size() > 1) {
		// メインモニタの決定
		int mainMonitor = 0, subMonitor = 1;
		for (int i = 0; i < _Displays.size(); i++) {
			if (_Displays[i].left == 0 && _Displays[i].top == 0) mainMonitor = i;
			else subMonitor = i;
		}
		// マルチモニタの場合 サブ画面でフルスクリーン化
		cv::moveWindow(WIN_DISP, _Displays[subMonitor].left, _Displays[subMonitor].top);
		cv::setWindowProperty(WIN_DISP, cv::WND_PROP_FULLSCREEN, cv::WINDOW_FULLSCREEN);
		_DispBuffer.create(cv::Size(_Displays[subMonitor].right - _Displays[subMonitor].left,
			_Displays[subMonitor].bottom - _Displays[subMonitor].top), CV_8UC3);
		cv::moveWindow(WIN_MAIN, _Displays[mainMonitor].left + 100, _Displays[mainMonitor].top + 100);
	}
	else {
		// シングルモニタの場合
		cv::moveWindow(WIN_DISP, _Displays[0].left, _Displays[0].top);
		_DispBuffer.create(cv::Size(640, 480), CV_8UC3);
		cv::moveWindow(WIN_MAIN, _Displays[0].left + 100, _Displays[0].top + 100);
	}
	cv::Mat opening = cv::imread("../images/ECTrainerLogo640x91.png");
	SetDispBuffer(opening);
	_SceneBuffer.create(SCENE_BUFFER_SIZE, CV_8UC3);
	_SceneBuffer = CV_RGB(0, 0, 0);
	_Logo = cv::imread("../images/ECTrainerLogo640x91.png");

	return true;
}

// イベントループ
bool ECTrainerGUI::MainLoop() {
	while (_pEct->IsRunning() && cv::getWindowProperty(WIN_MAIN, 0) >= 0) {

		// メインウインドウフレーム生成
		_MainFrame = cv::Scalar(49, 52, 49);

		// マウスカーソルを注視点とする処理
		//cvui::rect(_MainFrame, SCENE_BUFFER_POS.x, SCENE_BUFFER_POS.y, 
		//	SCENE_BUFFER_SIZE.width, SCENE_BUFFER_SIZE.height, 0xFF0000);
		cv::Point mp = cvui::mouse(WIN_MAIN);
		if (cvui::iarea(SCENE_BUFFER_POS.x, SCENE_BUFFER_POS.y, SCENE_BUFFER_SIZE.width, SCENE_BUFFER_SIZE.height) == cvui::DOWN) {
			_pEct->SetGazeV(cv::Point(mp.x - SCENE_BUFFER_POS.x, mp.y - SCENE_BUFFER_POS.y));
		} else {
			_pEct->SetGazeV(cv::Point(-1, -1));
		}

		cvui::image(_MainFrame, 0, 0, _Logo);
		cvui::beginRow(_MainFrame, 10, 100, -1, -1, 10);
		cvui::beginColumn(120, -1, 10);
		if (cvui::button(120, 30, "Calibration")) _pEct->Calib();
		if (cvui::button(120, 30, "Start")) _pEct->Start();
		cvui::printf("Mouse %d,%d", mp.x, mp.y);
		cvui::printf("GazeV %d,%d", _pEct->GetGazeV().x, _pEct->GetGazeV().y);
		cvui::printf("GazeI %.2f,%.2f", _pEct->GetGazeI().x, _pEct->GetGazeI().y);
		if (cvui::button(120, 30, "Quit")) _pEct->Stop();
		cvui::endColumn();
		cvui::beginColumn();
		cvui::image(_SceneBuffer);
		cvui::space();
		cvui::text(_pEct->GetHomographyStatus() ? "Homography OK" : "No homography");
		cvui::endColumn();
		cvui::endRow();


		// 画面表示
		cvui::update();
		cv::imshow(WIN_MAIN, _MainFrame);
		cv::imshow(WIN_DISP, _DispBuffer);
		int key = cv::waitKey(1);
		if (key == KEY_ESC) _pEct->Stop();
	}
	return true;
}

// 視野画像バッファに画像を設定
void ECTrainerGUI::SetSceneBuffer(cv::Mat& img) {
	cv::resize(img, _SceneBuffer, SCENE_BUFFER_SIZE);
}

// 刺激画像バッファに画像を設定
void ECTrainerGUI::SetDispBuffer(cv::Mat& img) {
	_DispBuffer = cv::Scalar(0, 0, 0);
	cv::Rect roiRect;
	if (img.rows * _DispBuffer.cols / _DispBuffer.rows > img.cols) {
		roiRect.width = img.cols * _DispBuffer.rows / img.rows;
		roiRect.height = _DispBuffer.rows;
	} else {
		roiRect.width = _DispBuffer.cols;
		roiRect.height = img.rows * _DispBuffer.cols / img.cols;
	}
	roiRect.x = (_DispBuffer.cols - roiRect.width) / 2;
	roiRect.y = (_DispBuffer.rows - roiRect.height) / 2;
	if (roiRect.x + roiRect.width > _DispBuffer.cols) roiRect.width = _DispBuffer.cols - roiRect.x;
	if (roiRect.y + roiRect.height > _DispBuffer.rows) roiRect.height = _DispBuffer.rows - roiRect.y;
	cv::Mat roi(_DispBuffer, roiRect);
	cv::resize(img, roi, roi.size());
}

// 全ディスプレイの情報を取得
void ECTrainerGUI::GetDisplayInfo() {
	EnumDisplayMonitors(NULL, NULL, 
		(MONITORENUMPROC)MonitorEnumProc, (LPARAM)&_Displays);
#ifdef _DEBUG
	for (int i = 0; i < _Displays.size(); i++) {
		std::cout << "Monitor" << i << " : "
			<< _Displays[i].left << ","	<< _Displays[i].top << ","
			<< _Displays[i].right << "," << _Displays[i].bottom << std::endl;
	}
#endif // _DEBUG
}

// 各ディスプレイの情報を取得
BOOL CALLBACK ECTrainerGUI::MonitorEnumProc(
	HMONITOR hMon, HDC hdcMon, LPRECT lpMon, LPARAM dwData) {
	std::vector<RECT>* displays = (std::vector<RECT>*)dwData;
	displays->push_back(*lpMon);
	return TRUE;
}