diff --git a/ECTrainer2/ECTrainer.h b/ECTrainer2/ECTrainer.h index 98731f4..8056413 100644 --- a/ECTrainer2/ECTrainer.h +++ b/ECTrainer2/ECTrainer.h @@ -36,6 +36,8 @@ MOVIE_STOP, // ����Đ���~ MOVIE_END, // ����Đ��I�� MOVIE_ERROR, // ����G���[ + FB_GOOD, // �t�B�[�h�o�b�N�FGood + FB_NICE, // �t�B�[�h�o�b�N�FNice }; // �A�v���P�[�V������� diff --git a/ECTrainer2/ECTrainerGUI.cpp b/ECTrainer2/ECTrainerGUI.cpp index 129bc8e..6ca8071 100644 --- a/ECTrainer2/ECTrainerGUI.cpp +++ b/ECTrainer2/ECTrainerGUI.cpp @@ -82,7 +82,7 @@ // �����_�̕\�� if (_pEct->PEyeTrack()->GetGazeV().x >= 0) { - cv::circle(sceneBuf, _pEct->PEyeTrack()->GetGazeV(), 10, CV_RGB(0, 0, 255), 2); + cv::circle(sceneBuf, _pEct->PEyeTrack()->GetGazeV(), 20, CV_RGB(0, 0, 255), 3); } // UI�`�� diff --git a/ECTrainer2/MovieObject.cpp b/ECTrainer2/MovieObject.cpp index b0f31c4..6f472d4 100644 --- a/ECTrainer2/MovieObject.cpp +++ b/ECTrainer2/MovieObject.cpp @@ -49,7 +49,13 @@ // �w�莞�ԈȑO�̗v�f�Q��Ԃ� std::vector MovieObject::GetElements(float sTime) { + if (this->IsEmpty()) { + std::vector elems; + return elems; + } + // �O�񌋉ʂ̎��Ԃ����łɑO���̏ꍇ�͍ŏ��ɖ߂� + if (_lastAccess < 0 || _lastAccess >= _frame.size()) _lastAccess = 0; if (_frame[_lastAccess].eTime > sTime) _lastAccess = 0; // �O�񌋉ʂ���O���ɒT�� diff --git a/ECTrainer2/MovieObject.h b/ECTrainer2/MovieObject.h index 39cee57..3fa832b 100644 --- a/ECTrainer2/MovieObject.h +++ b/ECTrainer2/MovieObject.h @@ -44,5 +44,5 @@ // �󂩂ǂ��� bool IsEmpty() { return _frame.size() < 1; } // ���� - void Clear() { _frame.clear(); } + void Clear() { _frame.clear(); _lastAccess = 0; } }; diff --git a/ECTrainer2/Stimulus.cpp b/ECTrainer2/Stimulus.cpp index 24abb77..4318c92 100644 --- a/ECTrainer2/Stimulus.cpp +++ b/ECTrainer2/Stimulus.cpp @@ -133,10 +133,6 @@ // �^�[�Q�b�g�����擾 std::vector Stimulus::GetMovieObject(float eTime) { - if (!_pMovieObject || _pMovieObject->IsEmpty()) { - std::vector elems; - return elems; - } if (eTime < 0) eTime = (float)_StimTimer.Elapse() / 1000.F; return _pMovieObject->GetElements(eTime); } diff --git a/ECTrainer2/Worker.cpp b/ECTrainer2/Worker.cpp index a963650..84c0ff6 100644 --- a/ECTrainer2/Worker.cpp +++ b/ECTrainer2/Worker.cpp @@ -13,16 +13,20 @@ , _AppStatus(APP_STATUS::BOOT) , _fpLogData(NULL) , _fpLogEvent(NULL) - , _pTimer(NULL) + , _pExpTimer(NULL) + , _pContactTimer(NULL) , _TargetImage(ECTrainer::RINGBUFSIZE) { + _pExpTimer = new mwut::HPTimer(); + _pContactTimer = new mwut::HPTimer(); } // �f�X�g���N�^ Worker::~Worker() { if (_fpLogData) fclose(_fpLogData); if (_fpLogEvent) fclose(_fpLogEvent); - mwut::SafeDelete((void**)&_pTimer); + mwut::SafeDelete((void**)&_pExpTimer); + mwut::SafeDelete((void**)&_pContactTimer); } // ������ @@ -31,7 +35,8 @@ _pEct->MsgBox(_T("Can't open data log file."), MB_ICONERROR); return false; } - _ftprintf(_fpLogData, _T("time,stimNo,stimTime,gazeVx,gazeVy,RR,H11,H12,H13,H21,H22,H23,H31,H32,H33\n")); + _ftprintf(_fpLogData, _T("time,stimNo,stimTime,gazeVx,gazeVy,gazeIx,gazeIy,target,contact time,Feedback,RR," + "H11,H12,H13,H21,H22,H23,H31,H32,H33\n")); if (_tfopen_s(&_fpLogEvent, EVENT_LOG_FILE, _T("w")) != 0) { _pEct->MsgBox(_T("Can't open event log file."), MB_ICONERROR); @@ -39,7 +44,6 @@ } _AppStatus = APP_STATUS::IDLE; - _pTimer = new mwut::HPTimer(); return true; } @@ -52,23 +56,59 @@ if (!_pEct->PEyeTrack()->IsNewGazeV()) return true; cv::Point2f gazeV = (_pEct->PEyeTrack()->GetGazeV()); + // �����_���摜���W�ɕϊ� + auto gazeI = gazeV.x < 0 ? cv::Point2f(-1, -1) : _pEct->PMarker()->ConvV2I(gazeV); + // �^�[�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) { cv::Mat stimImg = _pEct->PStimulus()->GetDisplay().clone(); for (int e = 0; e < elems.size(); e++) { - cv::circle(stimImg, cv::Point2f(elems[e].x, elems[e].y), (int)elems[e].d, CV_RGB(255, 0, 0), 2); + // �^�[�Q�b�g�`�� + auto target = cv::Point2f(elems[e].x, elems[e].y); + cv::circle(stimImg, target, (int)elems[e].d, CV_RGB(255, 0, 0), 2); + if (gazeI.x >= 0) { + // �^�[�Q�b�g���� + auto dt = cv::norm(gazeI - target); + if (dt < elems[e].d && (hit < 0 || dt < dtMin)) { + hit = e; + dtMin = dt; + } + } } + 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->Tell(ECTMSG::FB_GOOD); + _pContactTimer->Reset(); + } + } + } + _TargetImage.Put(stimImg); + } else { + _pContactTimer->Reset(); // ����������^�[�Q�b�g��ݒ莞�ɃR���^�N�g���ԃ��Z�b�g } // ���O�o�� - if (_AppStatus == APP_STATUS::STIM) { - _ftprintf(_fpLogData, _T("%.1f"), _pTimer->Elapse()); // �o�ߎ��� + if (stimNo >= 0) { + _ftprintf(_fpLogData, _T("%.3f"), _pExpTimer->Elapse() / 1000.); // �o�ߎ��� _ftprintf(_fpLogData, _T(",%d"), stimNo); // �h���f�[�^�ԍ� - _ftprintf(_fpLogData, _T(",%.1f"), _pEct->PStimulus()->GetStimTime()); // �h���񎦂̌o�ߎ��� + _ftprintf(_fpLogData, _T(",%.3f"), _pEct->PStimulus()->GetStimTime() / 1000.); // �h���񎦂̌o�ߎ��� _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(",%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�� cv::Mat h = _pEct->PMarker()->GetHomography(); @@ -114,7 +154,8 @@ _AppStatus = APP_STATUS::STIM; ((BaseProcess*)_pEct->PStimulus())->Tell(ECTMSG::EXP_START); this->EventLog(_T("Experiment Start")); - _pTimer->Reset(); + _pExpTimer->Reset(); + _pContactTimer->Reset(); } break; @@ -153,12 +194,17 @@ case (int)ECTMSG::MOVIE_ERROR: // ����G���[ this->EventLog(_T("Movie Error")); break; + + case (int)ECTMSG::FB_GOOD: // �t�B�[�h�o�b�N�FGood + PlaySound(_T("../voices/Good_S.wav"), NULL, SND_FILENAME | SND_ASYNC); + this->EventLog(_T("Feedback Good")); + break; } return true; } // �C�x���g���O�o�� void Worker::EventLog(const TCHAR* msg) { - _ftprintf(_fpLogEvent, _T("%.1f"), _pTimer->Elapse()); + _ftprintf(_fpLogEvent, _T("%.1f"), _pExpTimer->Elapse()); _ftprintf(_fpLogEvent, _T(" %s\n"), msg); } diff --git a/ECTrainer2/Worker.h b/ECTrainer2/Worker.h index 26e6c13..c33ff4e 100644 --- a/ECTrainer2/Worker.h +++ b/ECTrainer2/Worker.h @@ -25,7 +25,8 @@ 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* _pTimer; // ���O�p�̃^�C�}�[ + mwut::HPTimer* _pExpTimer; // �����o�ߎ��� + mwut::HPTimer* _pContactTimer; // �ڕW�R���^�N�g���� RingBuffer _TargetImage; // �^�[�Q�b�g�摜 // �C�x���g���O�o��