diff --git a/ECTrainer2/DShowMovie.cpp b/ECTrainer2/DShowMovie.cpp index 2dd8ddd..9bcf75c 100644 --- a/ECTrainer2/DShowMovie.cpp +++ b/ECTrainer2/DShowMovie.cpp @@ -7,7 +7,7 @@ #define _WIN32_DCOM // CoInitializeEx�֐��̌Ăяo���ɕK�v // �R���X�g���N�^ -DShowMovie::DShowMovie() +DShowMovie::DShowMovie(HINSTANCE hInst) : _pD3D(NULL) , _pD3DDev(NULL) , _pGB(NULL) @@ -17,6 +17,7 @@ , _pMediaCont(NULL) , _pMediaEvent(NULL) , _pMediaPosition(NULL) + , _hInst(hInst) , _hWnd(NULL) { } @@ -36,17 +37,17 @@ } // DirectX�̏����� -bool DShowMovie::InitDx(HINSTANCE hInstance, RECT dispRect) { +bool DShowMovie::Init(RECT dispRect) { // �E�C���h�E�N���X�̐ݒ� TCHAR gName[100] = _T("Video Window"); - WNDCLASSEX wcex = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInstance, NULL, NULL, + WNDCLASSEX wcex = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, _hInst, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, (TCHAR*)gName, NULL }; if (!RegisterClassEx(&wcex)) return 0; // �t���X�N���[���p�Ƀ|�b�v�A�b�v�E�B���h�E���쐬 if (!(_hWnd = CreateWindow(gName, gName, WS_POPUPWINDOW, dispRect.left, dispRect.top, dispRect.right - dispRect.left, dispRect.bottom - dispRect.top, - NULL, NULL, hInstance, NULL))) + NULL, NULL, _hInst, NULL))) return false; // Direct3D�̏����� diff --git a/ECTrainer2/DShowMovie.h b/ECTrainer2/DShowMovie.h index 0ffc5f1..93a8c14 100644 --- a/ECTrainer2/DShowMovie.h +++ b/ECTrainer2/DShowMovie.h @@ -12,6 +12,7 @@ #define CHECK(x) { if(((HRESULT)(x)) < 0) return false; } class DShowMovie { + HINSTANCE _hInst; HWND _hWnd; LPDIRECT3D9 _pD3D; LPDIRECT3DDEVICE9 _pD3DDev; @@ -24,9 +25,9 @@ IMediaPosition* _pMediaPosition; public: - DShowMovie(); + DShowMovie(HINSTANCE hInst); ~DShowMovie(); - bool InitDx(HINSTANCE hInstance, RECT dispRect); + bool Init(RECT dispRect); bool PlayMovie(std::wstring movie); bool StopMovie(); bool IsPlaying(); diff --git a/ECTrainer2/ECTrainer.cpp b/ECTrainer2/ECTrainer.cpp index 2888865..263d07e 100644 --- a/ECTrainer2/ECTrainer.cpp +++ b/ECTrainer2/ECTrainer.cpp @@ -10,14 +10,13 @@ #include "BitalMonitor.h" #include "Worker.h" #include "KeepAlive.h" +#include "DShowMovie.h" #include "myWinUtils.h" // �R���X�g���N�^ ECTrainer::ECTrainer(HINSTANCE hInstance) - : _hInstance(hInstance) { - _pMarker = new Marker(); _pProcs[(int)PROC::GUI] = new ECTrainerGUI(this); _pProcs[(int)PROC::IMGPROC] = new ImageProc(this); _pProcs[(int)PROC::SCNCAM] = new SceneCamera(this); @@ -27,6 +26,8 @@ _pProcs[(int)PROC::REST] = new TobiiREST(this); _pProcs[(int)PROC::BITAL] = new BitalMonitor(this); _pProcs[(int)PROC::WORKER] = new Worker(this); + _pMarker = new Marker(); + _pDSMovie = new DShowMovie(hInstance); } // �f�X�g���N�^ @@ -47,13 +48,12 @@ for (int i = 0; i < (int)PROC::NUM; i++) { if (i != (int)PROC::GUI) _pProcs[i]->Launch(); } - PWorker()->PostMsg(ECTMSG::SOFTWARE_START); _pProcs[(int)PROC::GUI]->MainLoop(); // �X���b�h�I�� for (int i = (int)PROC::REST; i < (int)PROC::NUM; i++) { auto rv = _pProcs[i]->WaitForExit(); - mwut::DebugPrintf(_T("Process %d exit %s\n"), i, rv ? _T("ok") : _T("ng")); + //mwut::DebugPrintf(_T("Process %d exit %s\n"), i, rv ? _T("ok") : _T("ng")); } return true; diff --git a/ECTrainer2/ECTrainer.h b/ECTrainer2/ECTrainer.h index 89b7046..ae367dc 100644 --- a/ECTrainer2/ECTrainer.h +++ b/ECTrainer2/ECTrainer.h @@ -5,8 +5,8 @@ #include #define TOBII_ADDR "192.168.71.50" -//#define EYEDEVICE_GLASS2 -#define EYEDEVICE_NONE +#define EYEDEVICE_GLASS2 +//#define EYEDEVICE_NONE class BaseProcess; class ECTrainerGUI; @@ -43,6 +43,7 @@ FB_NICE, // �t�B�[�h�o�b�N�FNice FB_GREAT, // �t�B�[�h�o�b�N�FGreat FB_EXCELLENT, // �t�B�[�h�o�b�N�FExcellent + FB_GOOUT, // �t�B�[�h�o�b�N�F�����O�� }; // �A�v���P�[�V������� @@ -53,12 +54,11 @@ class ECTrainer { // �v���Z�X�ꗗ�i���������j GUI < REST << SCNCAM < ALIVE < EYETR << STIM - enum class PROC { GUI, REST, IMGPROC, SCNCAM, ALIVE, EYETR, BITAL, STIM, WORKER, NUM }; + enum class PROC { GUI, REST, WORKER, IMGPROC, SCNCAM, ALIVE, EYETR, BITAL, STIM, NUM }; BaseProcess* _pProcs[(int)PROC::NUM]; Marker* _pMarker; DShowMovie* _pDSMovie; - HINSTANCE _hInstance; public: ECTrainer(HINSTANCE hInstance); @@ -73,11 +73,12 @@ BitalMonitor* PBitalMonitor() { return (BitalMonitor*)_pProcs[(int)PROC::BITAL]; } Worker* PWorker() { return (Worker*)_pProcs[(int)PROC::WORKER]; } Marker* PMarker() { return _pMarker; } + DShowMovie* PDSMovie() { return _pDSMovie; } // ���C������ bool Process(); // �C���X�^���X�n���h���擾 - HINSTANCE GetInstance() { return _hInstance; } + //HINSTANCE GetInstance() { return _hInstance; } // �A�v���P�[�V�������~ void StopApp(); // ���b�Z�[�W�{�b�N�X�\�� diff --git a/ECTrainer2/ECTrainerGUI.cpp b/ECTrainer2/ECTrainerGUI.cpp index ed85480..0aa488b 100644 --- a/ECTrainer2/ECTrainerGUI.cpp +++ b/ECTrainer2/ECTrainerGUI.cpp @@ -21,9 +21,8 @@ , _DispImageHeight(0) , _SceneBufferScale(1.F) , _hWndMain(NULL) - , _dsm(NULL) + , _Booting(true) { - _dsm = new DShowMovie(); } // ������ @@ -58,7 +57,9 @@ _blank = cv::Mat(DISP_SIZE, CV_8UC3, cv::Scalar(0)); _Logo = cv::imread("../images/ECTLogo2_1480l.png"); - return _dsm->InitDx(_pEct->GetInstance(), displays[0]); + _pEct->PDSMovie()->Init(displays[0]); + + return true; } // ��{���� @@ -76,7 +77,7 @@ bool isNew = fTarget ? _pEct->PWorker()->IsNewTargetImg() : _pEct->PStimulus()->IsNewDisplay(); cv::Mat dispBuf = fTarget ? _pEct->PWorker()->GetTargetImg().clone() : _pEct->PStimulus()->GetDisplay().clone(); if (dispBuf.empty()) dispBuf = _blank; - if (isNew && !_dsm->IsPlaying()) this->MakeFullDispBuffer(dispBuf); + if (isNew && !_pEct->PDSMovie()->IsPlaying()) this->MakeFullDispBuffer(dispBuf); // �����_�̕\�� if (_pEct->PEyeTrack()->GetGazeV().x >= 0) { @@ -97,7 +98,7 @@ break; case APP_STATUS::STIM: if (cvui::button(140, 30, "STOP")) { - _dsm->StopMovie(); + _pEct->PDSMovie()->StopMovie(); ((BaseProcess*)_pEct->PWorker())->PostMsg(ECTMSG::EXP_STOP); } //cvui::trackbar(140, &targetSize, (float)0, (float)3.0); @@ -109,9 +110,9 @@ //cvui::printf("Img Gaze %.2f, %.2f", _pEct->GetGazeI().x, _pEct->GetGazeI().y); cvui::text(_pEct->PMarker()->IsDetected() ? "AR Markers OK" : "AR Markers NG"); cvui::printf("Battery %d %%", _pEct->PTobiiREST()->GetBatteryLevel()); - if (_dsm->IsPlaying()) { + if (_pEct->PDSMovie()->IsPlaying()) { cvui::printf("%s", _pEct->PStimulus()->GetStimFile().c_str()); - cvui::printf("Movie pos: %.1f", _dsm->GetPlayPos()); + cvui::printf("Movie pos: %.1f", _pEct->PDSMovie()->GetPlayPos()); } bool snapshot = cvui::button(140, 30, "SNAPSHOT"); if (cvui::button(140, 30, "QUIT")) { @@ -138,27 +139,27 @@ if (_pEct->PStimulus()->IsNewMovie()) { std::wstring movie = _pEct->PStimulus()->GetMovie(); if (movie.size() < 1 || movie == L"STOP") { - _dsm->StopMovie(); + _pEct->PDSMovie()->StopMovie(); mwut::DebugPrintf(_T("ECTMSG::MOVIE_STOP [%s]\n"), movie.c_str()); ((BaseProcess*)_pEct->PWorker())->PostMsg(ECTMSG::MOVIE_STOP); } else { - if (_dsm->PlayMovie(movie)) { + if (_pEct->PDSMovie()->PlayMovie(movie)) { ((BaseProcess*)_pEct->PWorker())->PostMsg(ECTMSG::MOVIE_START); } else { - _dsm->StopMovie(); + _pEct->PDSMovie()->StopMovie(); ((BaseProcess*)_pEct->PWorker())->PostMsg(ECTMSG::MOVIE_ERROR); } } } // ����̖����܂ōĐ��`�F�b�N - if (_dsm->IsReachToEnd()) { + if (_pEct->PDSMovie()->IsReachToEnd()) { ((BaseProcess*)_pEct->PWorker())->PostMsg(ECTMSG::MOVIE_END); } // ��ʕ\�� cvui::update(); cv::imshow(WIN_MAIN, _MainFrame); - if (!_dsm->IsPlaying()) cv::imshow(WIN_DISP, _FullDispBuf); + if (!_pEct->PDSMovie()->IsPlaying()) cv::imshow(WIN_DISP, _FullDispBuf); if (snapshot) cv::imwrite(SNAPSHOT_FILE, _MainFrame); // �E�C���h�E�~�{�^���ŕ‚����� @@ -166,14 +167,24 @@ ((BaseProcess*)_pEct->PWorker())->PostMsg(ECTMSG::SOFTWARE_END); } + // �����GUI�\�������������Ƃ���ŋN�����b�Z�[�W���M + if (_Booting) { + _Booting = false; + ((BaseProcess*)_pEct->PWorker())->PostMsg(ECTMSG::SOFTWARE_START); + } + return true; } // �C�x���g���� bool ECTrainerGUI::EventProc(MSG& msg) { switch (msg.message) { - case WM_ACTIVATE: - mwut::DebugPrintf(_T("Event Activate\n"), msg.message); + case WM_CHAR: + if (msg.wParam == 27) { +#ifdef _DEBUG + ((BaseProcess*)_pEct->PWorker())->PostMsg(ECTMSG::SOFTWARE_END); +#endif + } break; default: //mwut::DebugPrintf(_T("Event %04X\n"), msg.message); diff --git a/ECTrainer2/ECTrainerGUI.h b/ECTrainer2/ECTrainerGUI.h index 9400764..d158236 100644 --- a/ECTrainer2/ECTrainerGUI.h +++ b/ECTrainer2/ECTrainerGUI.h @@ -26,6 +26,7 @@ float _SceneBufferScale; int _DispImageHeight; HWND _hWndMain; // ���C���E�C���h�E�̃n���h�� + BOOL _Booting; // ��{���� bool Routine(); diff --git a/ECTrainer2/StimConfig.txt b/ECTrainer2/StimConfig.txt index 74440c6..e1b539e 100644 --- a/ECTrainer2/StimConfig.txt +++ b/ECTrainer2/StimConfig.txt @@ -1,2 +1 @@ -#2,../movies/visit01_004.avi,30,../movies/visit01_004.csv -2,../movies/visit01_004short.avi,30,../movies/visit01_004.csv +2,../movies/visit01_004.avi,30,../movies/visit01_004.csv diff --git a/ECTrainer2/Worker.cpp b/ECTrainer2/Worker.cpp index b374648..d25e18d 100644 --- a/ECTrainer2/Worker.cpp +++ b/ECTrainer2/Worker.cpp @@ -16,9 +16,12 @@ , _pExpTimer(NULL) , _pContactTimer(NULL) , _TargetImage() + , _FBLevel(1) + , _IsInside(false) { _pExpTimer = new mwut::HPTimer(); _pContactTimer = new mwut::HPTimer(); + _pNohitTimer = new mwut::HPTimer(); } // �f�X�g���N�^ @@ -27,6 +30,7 @@ if (_fpLogEvent) fclose(_fpLogEvent); mwut::SafeDelete((void**)&_pExpTimer); mwut::SafeDelete((void**)&_pContactTimer); + mwut::SafeDelete((void**)&_pNohitTimer); } // ������ @@ -55,6 +59,7 @@ //Sleep(0); if (!_pEct->PEyeTrack()->IsNewGazeV()) return true; cv::Point2f gazeV = (_pEct->PEyeTrack()->GetGazeV()); + int stimNo = _pEct->PStimulus()->GetStimNo(); // �����_���摜���W�ɕϊ� auto gazeI = gazeV.x < 0 ? cv::Point2f(-1, -1) : _pEct->PMarker()->ConvV2I(gazeV); @@ -62,7 +67,6 @@ // �^�[�Q�b�g�摜���� int hit = -1; double dtMin = 0; - int stimNo = _pEct->PStimulus()->GetStimNo(); int fb = 0; std::vector elems = _pEct->PStimulus()->GetMovieObject(); if (stimNo >= 0 && elems.size() > 0) { @@ -83,20 +87,29 @@ if (gazeI.x >= 0) { // �摜��̒����_�`�� cv::circle(stimImg, gazeI, 20, CV_RGB(0, 0, 255), 3); - if (hit < 0) { - _pContactTimer->Reset(); // �����擾�����^�[�Q�b�g���莞�ɃR���^�N�g���ԃ��Z�b�g - } else { - if (_pContactTimer->Elapse() > 3000.) { - fb = 1; - this->PostMsg(ECTMSG::FB_GOOD); + + if (hit >= 0) { + _pNohitTimer->Reset(); + if (!_IsInside) { // �����������Ă����u�� + _IsInside = true; _pContactTimer->Reset(); + } else { + if (_pContactTimer->Elapse() >= (double)(FEEDBACK_TIME * _FBLevel)) { + this->PostMsg((ECTMSG)((int)ECTMSG::FB_OK + _FBLevel - 1)); + fb = _FBLevel++; + if (_FBLevel > 5) this->ResetParams(); // �ŏIFB��Ƀ��Z�b�g + } + } + } else { + if (_IsInside && _pNohitTimer->Elapse() >= (double)NOHIT_TIME) { + if (_FBLevel > 1) PostMsg(ECTMSG::FB_GOOUT); + this->ResetParams(); // �����O�ꂪ��莞�Ԍo�߂���ƃ��Z�b�g + fb = -1; } } } _TargetImage.Put(stimImg); - } else { - _pContactTimer->Reset(); // ����������^�[�Q�b�g��ݒ莞�ɃR���^�N�g���ԃ��Z�b�g } // ���O�o�� @@ -107,7 +120,7 @@ _ftprintf(_fpLogData, _T(",%.1f,%.1f"), gazeV.x, gazeV.y); // �����_�i����J�������W�j _ftprintf(_fpLogData, _T(",%.1f,%.1f"), gazeI.x, gazeI.y); // �����_�i�摜���W�j _ftprintf(_fpLogData, _T(",%d"), hit + 1); // �^�[�Q�b�g���� - _ftprintf(_fpLogData, _T(",%.2f"), hit < 0 ? 0 : _pContactTimer->Elapse()/1000.); // �ڕW�R���^�N�g���� + _ftprintf(_fpLogData, _T(",%.2f"), hit < 0 ? -1 : _pContactTimer->Elapse()/1000.); // �ڕW�R���^�N�g���� _ftprintf(_fpLogData, _T(",%d"), fb); // �t�B�[�h�o�b�N _ftprintf(_fpLogData, _T(",%d"), _pEct->PBitalMonitor()->GetRR()); // �o�C�^���o��(RR�Ԋu�j // �z���O���t�B�s��o�� @@ -124,6 +137,14 @@ return true; } +// ����p�����[�^�����Z�b�g +void Worker::ResetParams() { + _pContactTimer->Reset(); + _FBLevel = 1; + _pNohitTimer->Reset(); + _IsInside = false; +} + // �C�x���g���� bool Worker::EventProc(MSG& msg) { switch (msg.message) { @@ -165,7 +186,7 @@ ((BaseProcess*)_pEct->PStimulus())->PostMsg(ECTMSG::EXP_START); this->EventLog(_T("Experiment Start")); _pExpTimer->Reset(); - _pContactTimer->Reset(); + this->ResetParams(); } break; @@ -187,6 +208,7 @@ case (int)ECTMSG::EXP_NEXT: // ���̎h���Ɉړ� this->EventLog(_T("Next stimulation")); + this->ResetParams(); break; case (int)ECTMSG::MOVIE_START: // ����Đ��J�n @@ -208,27 +230,31 @@ case (int)ECTMSG::FB_OK: // �t�B�[�h�o�b�N�FOK PlaySound(SOUND_OK, NULL, SND_FILENAME | SND_ASYNC); - this->EventLog(_T("Feedback OK")); + //this->EventLog(_T("Feedback OK")); break; case (int)ECTMSG::FB_GOOD: // �t�B�[�h�o�b�N�FGood PlaySound(SOUND_GOOD, NULL, SND_FILENAME | SND_ASYNC); - this->EventLog(_T("Feedback Good")); + //this->EventLog(_T("Feedback Good")); break; case (int)ECTMSG::FB_NICE: // �t�B�[�h�o�b�N�FNice PlaySound(SOUND_NICE, NULL, SND_FILENAME | SND_ASYNC); - this->EventLog(_T("Feedback Nice")); + //this->EventLog(_T("Feedback Nice")); break; case (int)ECTMSG::FB_GREAT: // �t�B�[�h�o�b�N�FGreat PlaySound(SOUND_GREAT, NULL, SND_FILENAME | SND_ASYNC); - this->EventLog(_T("Feedback Great")); + //this->EventLog(_T("Feedback Great")); break; case (int)ECTMSG::FB_EXCELLENT: // �t�B�[�h�o�b�N�FExcellent PlaySound(SOUND_EXCELLENT, NULL, SND_FILENAME | SND_ASYNC); - this->EventLog(_T("Feedback Excellent")); + //this->EventLog(_T("Feedback Excellent")); + break; + + case (int)ECTMSG::FB_GOOUT: // �t�B�[�h�o�b�N�F�����O�� + PlaySound(SOUND_GOOUT, NULL, SND_FILENAME | SND_ASYNC); break; } return true; diff --git a/ECTrainer2/Worker.h b/ECTrainer2/Worker.h index cbda379..c25111d 100644 --- a/ECTrainer2/Worker.h +++ b/ECTrainer2/Worker.h @@ -5,6 +5,7 @@ #include #include "GOpenCV.h" #include "RingBuffer.h" +#include "myWinUtils.h" namespace mwut { class HPTimer; @@ -25,14 +26,20 @@ const TCHAR* SOUND_NICE = _T("../voices/Nice_S.wav"); const TCHAR* SOUND_GREAT = _T("../voices/Great_S.wav"); const TCHAR* SOUND_EXCELLENT = _T("../voices/Excellent_S.wav"); + const TCHAR* SOUND_GOOUT = _T("../voices/KbdKeyTap.wav"); const TCHAR* DATA_LOG_FILE = _T("LogData.csv"); const TCHAR* EVENT_LOG_FILE = _T("LogEvent.txt"); + const int FEEDBACK_TIME = 3000; // �t�B�[�h�o�b�N�̎��ԁi1���x���jmsec + const int NOHIT_TIME = 100; // �������O�ꂽ�Ɣ��肷�鎞�� msec APP_STATUS _AppStatus; // �A�v���P�[�V������� FILE* _fpLogData; // �f�[�^���O�t�@�C���|�C���^ FILE* _fpLogEvent; // �C�x���g���O�t�@�C���|�C���^ mwut::HPTimer* _pExpTimer; // �����o�ߎ��� mwut::HPTimer* _pContactTimer; // �ڕW�R���^�N�g���� + mwut::HPTimer* _pNohitTimer; // �����O�ꎞ�� RingBuffer _TargetImage; // �^�[�Q�b�g�摜 + int _FBLevel; // �t�B�[�h�o�b�N���x�� 1�`5 + bool _IsInside; // �������^�[�Q�b�g�ɂ��邩 // �C�x���g���O�o�� void EventLog(const TCHAR* msg); @@ -40,6 +47,8 @@ bool Routine(); // �C�x���g���� bool EventProc(MSG& msg); + // ����p�����[�^�����Z�b�g + void ResetParams(); public: // �R���X�g���N�^ @@ -54,5 +63,4 @@ bool IsNewTargetImg() { return _TargetImage.IsNew(); } // �^�[�Q�b�g�摜�擾 cv::Mat GetTargetImg() { return _TargetImage.Get(); } - };