diff --git a/ECTrainer2/ECTrainer.h b/ECTrainer2/ECTrainer.h index 4dca2be..aafa61c 100644 --- a/ECTrainer2/ECTrainer.h +++ b/ECTrainer2/ECTrainer.h @@ -32,6 +32,9 @@ CALIB_OK, // キャリブレーション成功 CALIB_FAILED, // キャリブレーション失敗 CALIB_ERR, // キャリブレーションエラー + SOFTCALIB_START, // ソフトキャリブレーション開始 + SOFTCALIB_OK, // ソフトキャリブレーション成功 + SOFTCALIB_FAILED, // ソフトキャリブレーション失敗 EXP_START, // 実験開始 EXP_STOP, // 実験停止 EXP_END, // 実験終了 diff --git a/ECTrainer2/Stimulus.cpp b/ECTrainer2/Stimulus.cpp index f1adcff..b9d947a 100644 --- a/ECTrainer2/Stimulus.cpp +++ b/ECTrainer2/Stimulus.cpp @@ -7,6 +7,7 @@ // コンストラクタ Stimulus::Stimulus(ECTrainer* pEct) : BaseProcess(pEct) , _StimNo(-1) + , _SoftCalibNo(-1) , _pMovieObject(NULL) , _Display() , _Movie() @@ -24,11 +25,34 @@ bool Stimulus::Init() { _Display.Put(cv::imread(OPENING_FILE)); - // 設定ファイルをテーブルに読み込み + // Softcalib設定ファイルをテーブルに読み込み nkc::STR_TABLE table; + if (!nkc::wut::ReadTable(SOFTCALIB_CONFIG_FILE, table)) { + Ect()->PWorker()->EventLog(_T("Can't open softcalib config file")); + return false; + } + for (int r = 0; r < table.size(); r++) { + if (table[r].size() != 6 || atoi(table[r][0].c_str()) < 1) continue; + StimInfo st; + st.type = atoi(table[r][0].c_str()); + st.filepath = table[r][1]; + int idx = (int)st.filepath.find_last_of("/\\"); + st.filename = idx == std::string::npos ? st.filepath : st.filepath.substr(idx + 1); + st.dulation = (float)atof(table[r][2].c_str()); + st.accTime = 0; + st.csvfile = table[r][3]; + st.smallmovie = table[r][4]; + st.scene = atoi(table[r][5].c_str()); + if (st.filepath.size() > 0) { + _SoftCalibInfoSet.push_back(st); + } + } + + // 刺激設定ファイルをテーブルに読み込み + table.clear(); auto configFile = cv::format(STIM_CONFIG_FILE.c_str(), Ect()->Visit()); if (!nkc::wut::ReadTable(configFile, table)) { - std::cerr << "Can't open config file : " << configFile << std::endl; + Ect()->PWorker()->EventLog(_T("Can't open stim config file")); return false; } @@ -57,7 +81,7 @@ } } if (_StimInfoSet.size() < 1) { - std::cerr << "Config file error : " << configFile << std::endl; + Ect()->PWorker()->EventLog(_T("Stim config file error")); return false; } @@ -82,6 +106,13 @@ if (!frame.empty()) _Display.Put(frame); } } + if (_SoftCalibNo >= 0) { + double eTime = _StimTimer.Elapse(); + // 刺激切り替えタイムキーパー + if (eTime / 1000. > (double)_SoftCalibInfoSet[_SoftCalibNo].dulation) { + this->MoveNextSoftCalib(); + } + } Sleep(15); return true; @@ -94,7 +125,8 @@ this->SetImage(CALIB_FILE); break; - case (int)ECTMSG::CALIB_OK: // キャリブレーション成功 + case (int)ECTMSG::SOFTCALIB_OK: // キャリブレーション成功 + _SoftCalibNo = -1; this->SetImage(CALIB_COMPLETE_FILE); break; @@ -103,6 +135,10 @@ this->SetImage(CALIB_FAILED_FILE); break; + case (int)ECTMSG::SOFTCALIB_START: + this->StartSoftCalib(); + break; + case (int)ECTMSG::EXP_START: // 実験開始 this->StartExp(); break; @@ -167,7 +203,7 @@ _pMovieObject->Clear(); if (_StimInfoSet[newStimNo].csvfile[0] != '_') { - this->LoadMovieObject(newStimNo); + this->LoadMovieObject(_StimInfoSet[newStimNo].csvfile); } if (_StimInfoSet[newStimNo].type == StimInfo::TYPE_MOVIE) { @@ -210,11 +246,11 @@ } // 動画オブジェクトの読み込み -void Stimulus::LoadMovieObject(int stimNo) { - int nFrames = _pMovieObject->SetData(_StimInfoSet[stimNo].csvfile); +void Stimulus::LoadMovieObject(std::string csvfile) { + int nFrames = _pMovieObject->SetData(csvfile); nkc::wut::DebugPrintf(_T("Movie object '%s' - %d frames read.\n"), - nkc::wut::Multi2Wide(_StimInfoSet[stimNo].csvfile).c_str(), nFrames); + nkc::wut::Multi2Wide(csvfile).c_str(), nFrames); } // ターゲット情報を取得 @@ -228,6 +264,40 @@ nkc::wut::DebugPrintf(_T("[Stimulus] %.1f fps\n"), fps); } +// SoftCalib開始 +void Stimulus::StartSoftCalib() { + this->SetSoftCalib(0); +} + +// SoftCalibを設定 +bool Stimulus::SetSoftCalib(int newCalibNo) { + if (newCalibNo < 0 || newCalibNo >= _SoftCalibInfoSet.size()) return false; + + _pMovieObject->Clear(); + if (_SoftCalibInfoSet[newCalibNo].csvfile[0] != '_') { + this->LoadMovieObject(_SoftCalibInfoSet[newCalibNo].csvfile); + } + + this->SetImage(_SoftCalibInfoSet[newCalibNo].filepath); + + _StimTimer.Reset(); + _SoftCalibNo = newCalibNo; + return true; +} + +// 次の刺激へ移動 +bool Stimulus::MoveNextSoftCalib() { + if (_SoftCalibNo < 0) return false; + + if (_SoftCalibNo + 1 < (int)_SoftCalibInfoSet.size()) { + SetSoftCalib(_SoftCalibNo + 1); + //Ect()->PWorker()->PostMsg((int)ECTMSG::EXP_NEXT); + } else { + Ect()->PWorker()->PostMsg((int)ECTMSG::SOFTCALIB_OK); + } + return true; +} + // 画像にマーカーを描画 //void Stimulus::StimWithMarker() { diff --git a/ECTrainer2/Stimulus.h b/ECTrainer2/Stimulus.h index 097f68b..5b36159 100644 --- a/ECTrainer2/Stimulus.h +++ b/ECTrainer2/Stimulus.h @@ -32,6 +32,7 @@ static const int SMALL_MOVIE_WIDTH = 640; // 縮小動画の幅(px) 全画面表示抑制の判定に使う private: const std::string STIM_CONFIG_FILE = "../config/visit%02d.txt"; + const std::string SOFTCALIB_CONFIG_FILE = "../config/softcalib.txt"; const cv::String OPENING_FILE = "../images/StartPage.png"; const cv::String CALIB_FILE = "../images/TobiiCalib.png"; const cv::String CALIB_COMPLETE_FILE = "../images/CalibOK.png"; @@ -42,8 +43,10 @@ const cv::String EXP_DONE_FILE = "../images/ExpDone.png"; std::vector _StimInfoSet; // 実験設定 + std::vector _SoftCalibInfoSet; // SoftCalib設定 MovieObject* _pMovieObject; // ターゲット情報 int _StimNo; // 刺激データ番号 -1:停止 + int _SoftCalibNo; // SoftCalibデータ番号 -1:停止 nkc::HPTimer _StimTimer; // 刺激提示タイマー nkc::RingBuffer _Display; // 表示画像 nkc::RingBuffer _Movie; // 動画情報 @@ -59,7 +62,7 @@ // 刺激を設定 bool SetStimulus(int newStimNo); // 動画オブジェクトの読み込み - void LoadMovieObject(int stimNo); + void LoadMovieObject(std::string csvfile); // 基本処理 bool Routine(); // イベント処理 @@ -70,6 +73,12 @@ bool SetImage(cv::String imageFile); // FPS表示 void FPS(double fps); + // SoftCalib開始 + void StartSoftCalib(); + // SoftCalibを設定 + bool SetSoftCalib(int newCalibNo); + // 次のSoftCalibへ移動 + bool MoveNextSoftCalib(); // 画像にマーカーを描画 //void StimWithMarker(); diff --git a/ECTrainer2/Worker.cpp b/ECTrainer2/Worker.cpp index 2a7d1de..9d81338 100644 --- a/ECTrainer2/Worker.cpp +++ b/ECTrainer2/Worker.cpp @@ -186,9 +186,9 @@ break; case (int)ECTMSG::CALIB_OK: // キャリブレーション成功 - _AppStatus = APP_STATUS::IDLE; - Ect()->PStimulus()->PostMsg((int)ECTMSG::CALIB_OK); - this->EventLog(_T("Calibration Success")); +// _AppStatus = APP_STATUS::IDLE; + Ect()->PStimulus()->PostMsg((int)ECTMSG::SOFTCALIB_START); + this->EventLog(_T("Soft Calibration Start")); break; case (int)ECTMSG::CALIB_FAILED: // キャリブレーション失敗 @@ -198,6 +198,12 @@ this->EventLog(_T("Calibration Failed")); break; + case (int)ECTMSG::SOFTCALIB_OK: // キャリブレーション成功 + _AppStatus = APP_STATUS::IDLE; + Ect()->PStimulus()->PostMsg((int)ECTMSG::SOFTCALIB_OK); + this->EventLog(_T("Calibration OK")); + break; + case (int)ECTMSG::EXP_START: // 実験開始 if (_AppStatus == APP_STATUS::IDLE) { _DataLog.StartRecord(Ect()->Subject(), Ect()->Visit()); diff --git a/config/softcalib.txt b/config/softcalib.txt new file mode 100644 index 0000000..2c22899 --- /dev/null +++ b/config/softcalib.txt @@ -0,0 +1,5 @@ +種別,刺激(画像・動画),提示時間(秒),ターゲット情報,縮小動画,刺激番号 +3,../images/SoftCalib/SoftCalib1.png,3,../images/SoftCalib/SoftCalib1.csv,_,_ +3,../images/SoftCalib/SoftCalib2.png,3,../images/SoftCalib/SoftCalib2.csv,_,_ +3,../images/SoftCalib/SoftCalib3.png,3,../images/SoftCalib/SoftCalib3.csv,_,_ +3,../images/SoftCalib/SoftCalib4.png,3,../images/SoftCalib/SoftCalib4.csv,_,_