diff --git a/ECTrainer2/BaseProcess.cpp b/ECTrainer2/BaseProcess.cpp index 0984e93..56bc67b 100644 --- a/ECTrainer2/BaseProcess.cpp +++ b/ECTrainer2/BaseProcess.cpp @@ -1,8 +1,8 @@ -#include "BaseProcess.h" +#include "BaseProcess.h" #include "ECTrainer.h" #include "MyWinUtils.h" -// �R���X�g���N�^ +// コンストラクタ BaseProcess::BaseProcess(ECTrainer* pEct) : _pEct(pEct) , _messageQueReady(false) @@ -12,26 +12,26 @@ { } -// �X���b�h�N�� +// スレッド起動 bool BaseProcess::Launch() { _threadHandle = ::CreateThread(NULL, 0, ThreadEntry, this, 0, &_threadID); return true; } -// ������ +// 初期化 bool BaseProcess::Init() { return true; } -// �X���b�h�{�� +// スレッド本体 bool BaseProcess::MainLoop() { if (_threadID == 0) { _mainThread = true; - _threadID = ::GetCurrentThreadId(); // ���C���X���b�hID�擾 + _threadID = ::GetCurrentThreadId(); // メインスレッドID取得 } //mwut::DebugPrintf(_T("Thread %d start\n"), _threadID); - // ���b�Z�[�W���[�v + // メッセージループ MSG msg; mwut::HPTimer timer; int fpsCounter = 0; @@ -41,13 +41,13 @@ if (!::GetMessage(&msg, NULL, 0, 0)) break; if (!this->EventProc(msg)) break; - if (_mainThread) { // ���C���X���b�h�ł̓E�C���h�E�v���V�[�W���Ƀf�B�X�p�b�`���� + if (_mainThread) { // メインスレッドではウインドウプロシージャにディスパッチする ::TranslateMessage(&msg); ::DispatchMessage(&msg); } } else { if (this->Routine() && this->ClassName().size() > 0) { - // FPS���� + // FPS処理 if (++fpsCounter >= fpsCount) { fpsCounter = 0; double fps = fpsCount * 1000.0 / timer.Interval(); @@ -61,25 +61,25 @@ return true; } -// �񃁃b�Z�[�W���̏��� +// 非メッセージ時の処理 bool BaseProcess::Routine() { return true; } -// ���b�Z�[�W���� +// メッセージ処理 bool BaseProcess::EventProc(MSG &msg) { //mwut::DebugPrintf(_T("BaseProcess::EventProc Thread %d msg %d\n"), _threadID, msg.message); return true; } -// �X���b�h�N���_ +// スレッド起動点 DWORD WINAPI BaseProcess::ThreadEntry(LPVOID lpParameter) { if (!((BaseProcess*)lpParameter)->MainLoop()) return 1; return 0; } -// �X���b�h�I���҂��@����I���Ńn���h���‚��� +// スレッド終了待ち 正常終了でハンドル閉じる bool BaseProcess::WaitForExit(DWORD timeOut) { if (!_threadHandle) return false; bool rv = (::WaitForSingleObject(_threadHandle, timeOut) == WAIT_OBJECT_0); @@ -87,9 +87,9 @@ return rv; } -// ���b�Z�[�W�𑗂�i�񓯊��j +// メッセージを送る(非同期) bool BaseProcess::PostMsg(ECTMSG msg, WPARAM wp, LPARAM lp) { - if (!_messageQueReady || !_threadID) return false; // ���b�Z�[�W�L���[�̏����m�F + if (!_messageQueReady || !_threadID) return false; // メッセージキューの準備確認 ::PostThreadMessage(_threadID, (int)msg, wp, lp); return true; } diff --git a/ECTrainer2/BaseProcess.h b/ECTrainer2/BaseProcess.h index 440d90b..a6339e4 100644 --- a/ECTrainer2/BaseProcess.h +++ b/ECTrainer2/BaseProcess.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -7,36 +7,36 @@ enum class ECTMSG; -// �����̊�{�N���X +// 処理の基本クラス class BaseProcess { protected: ECTrainer* _pEct; - bool _messageQueReady; // ���b�Z�[�W�L���[�̏����� - HANDLE _threadHandle; // �X���b�h�n���h�� - DWORD _threadID; // �X���b�hID - bool _mainThread; // ���C��(GUI)�X���b�h���ǂ��� + bool _messageQueReady; // メッセージキューの準備状況 + HANDLE _threadHandle; // スレッドハンドル + DWORD _threadID; // スレッドID + bool _mainThread; // メイン(GUI)スレッドかどうか - // �X���b�h�G���g���|�C���g + // スレッドエントリポイント static DWORD WINAPI ThreadEntry(LPVOID lpParameter); - // �񃁃b�Z�[�W���̏��� + // 非メッセージ時の処理 virtual bool Routine(); - // ���b�Z�[�W���� + // メッセージ処理 virtual bool EventProc(MSG& msg); - // �N���X���擾�i�h���N���X�ŃI�[�o�[���C�h�����FPS�\���j - virtual std::string ClassName() { return ""; } // FPS�\�� + // クラス名取得(派生クラスでオーバーライドすればFPS表示) + virtual std::string ClassName() { return ""; } // FPS表示 public: - // �R���X�g���N�^ + // コンストラクタ BaseProcess(ECTrainer* pEct); - // �X���b�h�N�� + // スレッド起動 virtual bool Launch(); - // ������ + // 初期化 virtual bool Init(); - // �X���b�h�{�� + // スレッド本体 virtual bool MainLoop(); - // �X���b�h�I���҂��@����I���Ńn���h���‚��� + // スレッド終了待ち 正常終了でハンドル閉じる virtual bool WaitForExit(DWORD timeOut = 3000); - // ���b�Z�[�W�𑗂�i�񓯊��j + // メッセージを送る(非同期) virtual bool PostMsg(ECTMSG msg, WPARAM wp = 0, LPARAM lp = 0); }; diff --git a/ECTrainer2/BitalMonitor.cpp b/ECTrainer2/BitalMonitor.cpp index 7ec02a7..131cba0 100644 --- a/ECTrainer2/BitalMonitor.cpp +++ b/ECTrainer2/BitalMonitor.cpp @@ -1,9 +1,9 @@ -#include "BitalMonitor.h" +#include "BitalMonitor.h" #include "ECTrainer.h" #include "Worker.h" #include "myWinUtils.h" -// �R���X�g���N�^ +// コンストラクタ BitalMonitor::BitalMonitor(ECTrainer* pEct) :BaseProcess(pEct) , _rrInterval() @@ -14,15 +14,15 @@ _rrInterval.Put(0); } -// ������ +// 初期化 bool BitalMonitor::Init() { - // �f�o�C�X�̒T�� - for (int com = 1; com <= GComPort::COM_SEARCH_MAX; com++) { + // デバイスの探索 + for (int com = 1; com <= COM_SEARCH_MAX; com++) { if (!_Com.Open(com, _T("baud=19200 parity=N data=8 stop=1"))) continue; - // �|�[�g�`�F�b�N + // ポートチェック char comBuf[BUF_LEN] = { '\0' }; DWORD readBytes = _Com.Receive((BYTE*)comBuf, BUF_LEN - 1); if (readBytes < 1) continue; @@ -39,7 +39,7 @@ return true; } -// ���[�v +// ループ bool BitalMonitor::Routine() { if (!_useDevice) { @@ -47,9 +47,9 @@ return true; } - // �o�C�^�� + // バイタル char comBuf[BUF_LEN] = { '\0' }; - DWORD readBytes = _Com.Receive((BYTE*)comBuf, BUF_LEN / 2); // �O��̎c�蕶����ɒlj����邽�ߓǂݍ��ݗʂ�}������ + DWORD readBytes = _Com.Receive((BYTE*)comBuf, BUF_LEN / 2); // 前回の残り文字列に追加するため読み込み量を抑制する if (readBytes > 0) { //std::cout << "readBytes:" << readBytes << std::endl; comBuf[readBytes] = '\0'; @@ -79,7 +79,7 @@ //std::cout << "lastBuf2:" << lastBuf << std::endl; } - // ���M�����o + // 無信号検出 if (_lastRR > 0 && timeGetTime() - _lastRR > NO_SIGNAL_TIMEOUT) { _rrInterval.Put(0); _lastRR = 0; diff --git a/ECTrainer2/BitalMonitor.h b/ECTrainer2/BitalMonitor.h index fc11379..1ba3ed5 100644 --- a/ECTrainer2/BitalMonitor.h +++ b/ECTrainer2/BitalMonitor.h @@ -1,23 +1,24 @@ -#pragma once +#pragma once #include "BaseProcess.h" -#include "GComPort.h" +#include "ComPort.h" #include "RingBuffer.h" class BitalMonitor : public BaseProcess { const char LF = 10; - const DWORD NO_SIGNAL_TIMEOUT = 5000; // ���M���Ɣ��肷�鎞�� (ms) + const DWORD NO_SIGNAL_TIMEOUT = 5000; // 無信号と判定する時間 (ms) static const int BUF_LEN = 256; + const int COM_SEARCH_MAX = 20; - GComPort _Com; + nkc::ComPort _Com; RingBuffer _rrInterval; bool _useDevice; - DWORD _lastRR; // �O���RR�擾���ԁi�^�C���A�E�g�� 0�j + DWORD _lastRR; // 前回のRR取得時間(タイムアウト時 0) char lastBuf[BUF_LEN]; - //std::string ClassName() { return "BitalMonitor"; } // FPS�\�� + //std::string ClassName() { return "BitalMonitor"; } // FPS表示 public: diff --git a/ECTrainer2/ComPort.cpp b/ECTrainer2/ComPort.cpp new file mode 100644 index 0000000..1e03c20 --- /dev/null +++ b/ECTrainer2/ComPort.cpp @@ -0,0 +1,132 @@ +#include "ComPort.h" + +namespace nkc { + +// コンストラクタ +ComPort::ComPort(void) : + _ComHandle(INVALID_HANDLE_VALUE) +{ +} + +// デストラクタ(終了処理) +ComPort::~ComPort(void) +{ + this->Close(); +} + +// ポートを探して開く(sendStrを送信して,checkStrを返すポートを探す) +// TCHAR* config : シリアルポート設定文字列 例)"" +// char* sendStr : 送信文字列(バイナリデータ可) +// int sendLen : 送信文字列の長さ (byte) +// char* checkStr : チェック文字列(バイナリデータ可) +// int checkLen : チェック文字列の長さ (byte) +// 戻り値 : 発見したポート番号(未発見時は0) +int ComPort::Open(TCHAR* config, char* sendStr, int sendLen, char* checkStr, int checkLen) +{ + for (int findPort = 1; findPort <= COM_SEARCH_MAX; findPort++) { + if (this->Open(findPort, config)) { + this->Send((BYTE*)sendStr, sendLen); + ::Sleep(100); // 少し待つ + BYTE buf[256]; + this->Receive(buf, 256); + if (!::strncmp((char*)buf, checkStr, checkLen)) return findPort; + } + } + return 0; +} + +// ポートを開く +bool ComPort::Open(int port, const TCHAR* config) +{ + this->Close(); + + // ポート番号文字列生成 + if (port < 1) return false; + TCHAR portStr[16]; + ::wsprintf(portStr, _T("\\\\.\\COM%d"), port); + + // Comポートを開く + _ComHandle = ::CreateFile(portStr, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (_ComHandle == INVALID_HANDLE_VALUE) return false; + + // ポート設定 + DCB dcb; + ::GetCommState(_ComHandle, &dcb); + ::BuildCommDCB(config, &dcb); + dcb.fRtsControl = RTS_CONTROL_DISABLE; + dcb.fOutxDsrFlow = FALSE; + dcb.fDsrSensitivity = FALSE; + dcb.fAbortOnError = FALSE; + ::SetCommState(_ComHandle, &dcb); + + // タイムアウト設定 + COMMTIMEOUTS timeout; + ::GetCommTimeouts(_ComHandle, &timeout); + timeout.ReadIntervalTimeout = MAXDWORD; + timeout.ReadTotalTimeoutMultiplier = 1; + timeout.ReadTotalTimeoutConstant = 500; + timeout.WriteTotalTimeoutMultiplier = 1; + timeout.WriteTotalTimeoutConstant = 500; + ::SetCommTimeouts(_ComHandle, &timeout); + + return true; +} + +// ポートを閉じる +void ComPort::Close() +{ + if (_ComHandle != INVALID_HANDLE_VALUE) + { + ::CloseHandle(_ComHandle); + _ComHandle = INVALID_HANDLE_VALUE; + } +} + +// データ送信 +DWORD ComPort::Send(const BYTE* data, DWORD dataLen) +{ + if (_ComHandle == INVALID_HANDLE_VALUE) return 0; + + DWORD sendSize; // 送信したバイト数 + ::WriteFile(_ComHandle, data, dataLen, &sendSize, NULL); + + return sendSize; +} + +// データ受信 +DWORD ComPort::Receive(BYTE* buffer, DWORD bufferLen) +{ + if (_ComHandle == INVALID_HANDLE_VALUE) return 0; + + DWORD errors; + COMSTAT stat; + ::ClearCommError(_ComHandle, &errors, &stat); + + DWORD queSize = stat.cbInQue; + if (queSize < 1) return 0; + if (bufferLen < queSize) queSize = bufferLen; + + // バッファのクリア + ::memset(buffer, 0, bufferLen); + + // 受信 + DWORD receiveSize; // 受信したバイト数 + ::ReadFile(_ComHandle, buffer, queSize, &receiveSize, NULL); + + return receiveSize; +} + +// タイムアウト付きデータ受信 +DWORD ComPort::WaitReceive(BYTE* buffer, DWORD bufferLen, const int timeout) +{ + if (_ComHandle == INVALID_HANDLE_VALUE) return 0; + + int receiveSize; + for (int i = 0; i < timeout && + (receiveSize = this->Receive(buffer, bufferLen)) < 1; i++) ::Sleep(1); + + return receiveSize; +} + +}; // namespace nkc diff --git a/ECTrainer2/ComPort.h b/ECTrainer2/ComPort.h new file mode 100644 index 0000000..673e18f --- /dev/null +++ b/ECTrainer2/ComPort.h @@ -0,0 +1,27 @@ +// シリアルポートクラス + +#pragma once + +#include +#include + +namespace nkc { + +class ComPort +{ + const int COM_SEARCH_MAX = 20; + HANDLE _ComHandle; + +public: + + ComPort(void); + ~ComPort(void); + int Open(TCHAR* config, char* sendStr, int sendLen, char* checkStr, int checkLen); + bool Open(int port, const TCHAR* config); + void Close(); + DWORD Send(const BYTE* data, DWORD dataLen); + DWORD Receive(BYTE* buffer, DWORD bufferLen); + DWORD WaitReceive(BYTE* buffer, DWORD bufferLen, int timeout); +}; + +}; // namespace nkc diff --git a/ECTrainer2/DShowMovie.cpp b/ECTrainer2/DShowMovie.cpp index 9bcf75c..a0a682d 100644 --- a/ECTrainer2/DShowMovie.cpp +++ b/ECTrainer2/DShowMovie.cpp @@ -1,12 +1,12 @@ -#include "DShowMovie.h" +#include "DShowMovie.h" #include "myWinUtils.h" #pragma comment(lib, "dxguid.lib") #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "Strmiids.lib") -#define _WIN32_DCOM // CoInitializeEx�֐��̌Ăяo���ɕK�v +#define _WIN32_DCOM // CoInitializeEx関数の呼び出しに必要 -// �R���X�g���N�^ +// コンストラクタ DShowMovie::DShowMovie(HINSTANCE hInst) : _pD3D(NULL) , _pD3DDev(NULL) @@ -22,7 +22,7 @@ { } -// �f�X�g���N�^ +// デストラクタ DShowMovie::~DShowMovie() { SAFE_RELEASE(_pMediaPosition); SAFE_RELEASE(_pMediaEvent); @@ -36,24 +36,24 @@ CoUninitialize(); } -// DirectX�̏����� +// DirectXの初期化 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, _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, _hInst, NULL))) return false; - // Direct3D�̏����� + // Direct3Dの初期化 if (!(_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) return false; - // �t���X�N���[���p�ɏ������p�����[�^��ݒ� + // フルスクリーン用に初期化パラメータを設定 D3DPRESENT_PARAMETERS d3dpp = { (UINT)(dispRect.right - dispRect.left), (UINT)(dispRect.bottom - dispRect.top), D3DFMT_A8R8G8B8, 0, D3DMULTISAMPLE_NONE, 0, D3DSWAPEFFECT_DISCARD, _hWnd, FALSE, 0, D3DFMT_UNKNOWN, D3DPRESENT_RATE_DEFAULT, 0 }; @@ -68,61 +68,61 @@ mwut::DebugPrintf(_T("Hardware DirectX\n")); } - // COM�̏����� + // COMの初期化 CHECK(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)); return true; } -// ����Đ� +// 動画再生 bool DShowMovie::PlayMovie(std::wstring movie) { this->StopMovie(); - // �t�B���^�O���t�}�l�[�W���̍쐬 + // フィルタグラフマネージャの作成 CHECK(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&_pGB)); - // VRM9�t�B���^�̍쐬�Ɠo�^ + // VRM9フィルタの作成と登録 CHECK(CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&_pVMR9)); - CHECK(_pGB->AddFilter(_pVMR9, L"VMR9")); // �t�B���^�O���t�ɓo�^ + CHECK(_pGB->AddFilter(_pVMR9, L"VMR9")); // フィルタグラフに登録 - // VRM9���E�B���h�E���X���[�h�ɂ��� + // VRM9をウィンドウレスモードにする IVMRFilterConfig* pVMRCfg = NULL; CHECK(_pVMR9->QueryInterface(IID_IVMRFilterConfig9, (void**)&pVMRCfg)); CHECK(pVMRCfg->SetRenderingMode(VMRMode_Windowless)); - pVMRCfg->Release(); // IVMRFilterConfig�͂����K�v�Ȃ� + pVMRCfg->Release(); // IVMRFilterConfigはもう必要ない - // �`��E�B���h�E�̎w�� + // 描画ウィンドウの指定 IVMRWindowlessControl9* pVMRWndCont = NULL; CHECK(_pVMR9->QueryInterface(IID_IVMRWindowlessControl9, (void**)&pVMRWndCont)); CHECK(pVMRWndCont->SetVideoClippingWindow(_hWnd)); - // �\�[�X�t�B���^�̐����Ɠo�^ + // ソースフィルタの生成と登録 CHECK(_pGB->AddSourceFilter(movie.c_str(), movie.c_str(), &_pSource)); - // CaptureGraphBuilder2�C���^�[�t�F�C�X�̎擾 + // CaptureGraphBuilder2インターフェイスの取得 CHECK(CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&_pCGB2)); CHECK(_pCGB2->SetFiltergraph(_pGB)); - // �t�B���^�̐ڑ� + // フィルタの接続 CHECK(_pCGB2->RenderStream(0, 0, _pSource, 0, _pVMR9)); CHECK(_pCGB2->RenderStream(0, &MEDIATYPE_Audio, _pSource, 0, 0)); - // �`��̈�̐ݒ�i�ڑ���łȂ��ƃG���[�ɂȂ�j + // 描画領域の設定(接続後でないとエラーになる) LONG W, H; CHECK(pVMRWndCont->GetNativeVideoSize(&W, &H, NULL, NULL)); RECT SrcR, DestR; SetRect(&SrcR, 0, 0, W, H); GetClientRect(_hWnd, &DestR); CHECK(pVMRWndCont->SetVideoPosition(&SrcR, &DestR)); - pVMRWndCont->Release(); // �E�B���h�E���X�R���g���[���͂����K�v�Ȃ� + pVMRWndCont->Release(); // ウィンドウレスコントロールはもう必要ない - // ���f�B�A�R���g���[���C���^�[�t�F�C�X�̎擾 + // メディアコントロールインターフェイスの取得 CHECK(_pGB->QueryInterface(IID_IMediaControl, (void**)&_pMediaCont)); - // ���f�B�A�C�x���g�C���^�[�t�F�C�X�̎擾 + // メディアイベントインターフェイスの取得 CHECK(_pGB->QueryInterface(IID_IMediaEvent, (void**)&_pMediaEvent)); - // ���f�B�A�|�W�V�����C���^�[�t�F�C�X�̎擾 + // メディアポジションインターフェイスの取得 CHECK(_pGB->QueryInterface(IID_IMediaPosition, (void**)&_pMediaPosition)); ShowWindow(_hWnd, SW_SHOWNORMAL); @@ -131,7 +131,7 @@ return true; } -// �����~ +// 動画停止 bool DShowMovie::StopMovie() { if (_pMediaCont) _pMediaCont->Stop(); SAFE_RELEASE(_pMediaPosition); @@ -145,12 +145,12 @@ return true; } -// �Đ���Ԃ̊m�F +// 再生状態の確認 bool DShowMovie::IsPlaying() { return (_pGB != NULL); } -// �Đ���Ԃ̎擾 +// 再生状態の取得 FILTER_STATE DShowMovie::GetMovieState() { if (!_pMediaCont) return State_Stopped; FILTER_STATE fs; @@ -158,7 +158,7 @@ return fs; } -// �Đ����Ō�܂œ��B������ +// 再生が最後まで到達したか bool DShowMovie::IsReachToEnd() { if (!_pMediaEvent) return false; long eventCode; @@ -167,7 +167,7 @@ return (eventCode == EC_COMPLETE); } -// �Đ��ʒu�̎擾 +// 再生位置の取得 double DShowMovie::GetPlayPos() { if (!_pMediaPosition) return -1.0; REFTIME tm; @@ -175,7 +175,7 @@ return tm; } -// �E�B���h�E�v���V�[�W�� +// ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg == WM_DESTROY) { PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); diff --git a/ECTrainer2/DShowMovie.h b/ECTrainer2/DShowMovie.h index 93a8c14..f8d04f6 100644 --- a/ECTrainer2/DShowMovie.h +++ b/ECTrainer2/DShowMovie.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include diff --git a/ECTrainer2/ECTrainer.cpp b/ECTrainer2/ECTrainer.cpp index 0fa1082..fc684f1 100644 --- a/ECTrainer2/ECTrainer.cpp +++ b/ECTrainer2/ECTrainer.cpp @@ -1,4 +1,4 @@ - + #include "ECTrainer.h" #include "ECTrainerGUI.h" #include "SceneCamera.h" @@ -14,7 +14,7 @@ #include "myWinUtils.h" -// �R���X�g���N�^ +// コンストラクタ ECTrainer::ECTrainer(HINSTANCE hInstance) { _pProcs[(int)PROC::GUI] = new ECTrainerGUI(this); @@ -30,32 +30,32 @@ _pDSMovie = new DShowMovie(hInstance); } -// �f�X�g���N�^ +// デストラクタ ECTrainer::~ECTrainer() { for (int i = 0; i < (int)PROC::NUM; i++) { if (_pProcs[i]) delete _pProcs[i]; } } -// ������ +// 初期化 bool ECTrainer::Process() { PWorker()->EventLog(_T("")); PWorker()->EventLog(_T("Software Start")); - // �v���Z�X������ + // プロセス初期化 for (int i = 0; i < (int)PROC::NUM; i++) { if (!_pProcs[i]->Init()) return false; //mwut::DebugPrintf(_T("Thread %d initialized.\n"), i); } - // �X���b�h�J�n + // スレッド開始 for (int i = 0; i < (int)PROC::NUM; i++) { if (i != (int)PROC::GUI) _pProcs[i]->Launch(); //mwut::DebugPrintf(_T("Thread %d start.\n"), i); } _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")); @@ -64,12 +64,12 @@ return true; } -// �A�v���P�[�V�������~ +// アプリケーションを停止 void ECTrainer::StopApp() { for (int i = 0; i < (int)PROC::NUM; i++) _pProcs[i]->PostMsg(ECTMSG::QUIT); } -// ���b�Z�[�W�{�b�N�X�\�� +// メッセージボックス表示 void ECTrainer::MsgBox(LPCWSTR msg, UINT icon) { ::MessageBox(PECTrainerGUI()->GetMainHWnd(), msg, _T("Eye Communication Trainer"), MB_OK | icon); diff --git a/ECTrainer2/ECTrainer.h b/ECTrainer2/ECTrainer.h index 963f2d5..5a6aa9f 100644 --- a/ECTrainer2/ECTrainer.h +++ b/ECTrainer2/ECTrainer.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -22,39 +22,39 @@ class Marker; class DShowMovie; -// ���b�Z�[�W�ꗗ +// メッセージ一覧 enum class ECTMSG { QUIT = WM_QUIT, - SOFTWARE_START = WM_USER, // �\�t�g�E�F�A�N�� - SOFTWARE_END, // �\�t�g�E�F�A�I�� - SYSTEM_ERROR, // �V�X�e���G���[ - CALIB_START, // �L�����u���[�V�����J�n - CALIB_OK, // �L�����u���[�V�������� - CALIB_FAILED, // �L�����u���[�V�������s - CALIB_ERR, // �L�����u���[�V�����G���[ - EXP_START, // �����J�n - EXP_STOP, // ������~ - EXP_END, // �����I�� - EXP_NEXT, // ���̎h���Ɉړ� - MOVIE_START, // ����Đ��J�n - MOVIE_STOP, // ����Đ���~ - MOVIE_END, // ����Đ��I�� - FB_OK, // �t�B�[�h�o�b�N�FOK - FB_GOOD, // �t�B�[�h�o�b�N�FGood - 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�� + SOFTWARE_START = WM_USER, // ソフトウェア起動 + SOFTWARE_END, // ソフトウェア終了 + SYSTEM_ERROR, // システムエラー + CALIB_START, // キャリブレーション開始 + CALIB_OK, // キャリブレーション成功 + CALIB_FAILED, // キャリブレーション失敗 + CALIB_ERR, // キャリブレーションエラー + EXP_START, // 実験開始 + EXP_STOP, // 実験停止 + EXP_END, // 実験終了 + EXP_NEXT, // 次の刺激に移動 + MOVIE_START, // 動画再生開始 + MOVIE_STOP, // 動画再生停止 + MOVIE_END, // 動画再生終了 + FB_OK, // フィードバック:OK + FB_GOOD, // フィードバック:Good + FB_NICE, // フィードバック:Nice + FB_GREAT, // フィードバック:Great + FB_EXCELLENT, // フィードバック:Excellent + FB_GOOUT, // フィードバック:視線外れ }; -// �A�v���P�[�V������� +// アプリケーション状態 enum class APP_STATUS { BOOT, IDLE, CALIB, STIM }; class ECTrainer { - // �v���Z�X�ꗗ�i���������j GUI < REST << SCNCAM < ALIVE < EYETR << STIM + // プロセス一覧(初期化順) GUI < REST << SCNCAM < ALIVE < EYETR << STIM enum class PROC { GUI, REST, WORKER, IMGPROC, SCNCAM, ALIVE, EYETR, BITAL, STIM, NUM }; BaseProcess* _pProcs[(int)PROC::NUM]; @@ -76,12 +76,12 @@ Marker* PMarker() { return _pMarker; } DShowMovie* PDSMovie() { return _pDSMovie; } - // ���C������ + // メイン処理 bool Process(); - // �C���X�^���X�n���h���擾 + // インスタンスハンドル取得 //HINSTANCE GetInstance() { return _hInstance; } - // �A�v���P�[�V�������~ + // アプリケーションを停止 void StopApp(); - // ���b�Z�[�W�{�b�N�X�\�� + // メッセージボックス表示 void MsgBox(LPCWSTR msg, UINT icon = 0); }; diff --git a/ECTrainer2/ECTrainer2.vcxproj b/ECTrainer2/ECTrainer2.vcxproj index 3619b6b..f823434 100644 --- a/ECTrainer2/ECTrainer2.vcxproj +++ b/ECTrainer2/ECTrainer2.vcxproj @@ -145,11 +145,11 @@ + - @@ -166,12 +166,12 @@ + - diff --git a/ECTrainer2/ECTrainer2.vcxproj.filters b/ECTrainer2/ECTrainer2.vcxproj.filters index 73ca240..b1c4cf4 100644 --- a/ECTrainer2/ECTrainer2.vcxproj.filters +++ b/ECTrainer2/ECTrainer2.vcxproj.filters @@ -48,9 +48,6 @@ ソース ファイル - - ソース ファイル - ソース ファイル @@ -72,6 +69,9 @@ ソース ファイル + + ソース ファイル + @@ -107,9 +107,6 @@ ヘッダー ファイル - - ヘッダー ファイル - ヘッダー ファイル @@ -137,6 +134,9 @@ ヘッダー ファイル + + ヘッダー ファイル + diff --git a/ECTrainer2/ECTrainerGUI.cpp b/ECTrainer2/ECTrainerGUI.cpp index 359151d..87761e2 100644 --- a/ECTrainer2/ECTrainerGUI.cpp +++ b/ECTrainer2/ECTrainerGUI.cpp @@ -1,4 +1,4 @@ - + #include "DShowMovie.h" #include "ECTrainerGUI.h" #include "ECTrainer.h" @@ -15,33 +15,33 @@ #define CVUI_IMPLEMENTATION #include "cvui.h" -// �R���X�g���N�^ +// コンストラクタ ECTrainerGUI::ECTrainerGUI(ECTrainer* pEct) : BaseProcess(pEct) , _hWndMain(NULL) { } -// ������ +// 初期化 bool ECTrainerGUI::Init() { - // GUI�E�C���h�E + // GUIウインドウ cvui::init(WIN_MAIN); _MainFrame.create(MAIN_FRAME_SIZE, CV_8UC3); - // �h���񎦃E�C���h�E - std::vector displays = mwut::GetDisplayInfo(); // ���s�‹��̏��擾 + // 刺激提示ウインドウ + std::vector displays = mwut::GetDisplayInfo(); // 実行環境の情報取得 if (displays.size() > 1 && !FORCE_SINGLE_MONITOR) { - // �}���`���j�^�̏ꍇ - // �T�u��ʂɑ���p�l���\�� + // マルチモニタの場合 + // サブ画面に操作パネル表示 cv::moveWindow(WIN_MAIN, displays[1].left, displays[1].top); - // ���C����ʂɔ팱�҉f���񎦁iDirectShow���悪�T�u��ʂɏo�͂ł��Ȃ����߁j + // メイン画面に被験者映像提示(DirectShow動画がサブ画面に出力できないため) cv::namedWindow(WIN_DISP, cv::WINDOW_NORMAL | cv::WINDOW_OPENGL); cv::moveWindow(WIN_DISP, displays[0].left, displays[0].top); cv::resizeWindow(WIN_DISP, cv::Size(640, 400)); cv::setWindowProperty(WIN_DISP, cv::WND_PROP_FULLSCREEN, cv::WINDOW_FULLSCREEN); } else { - // �V���O�����j�^�̏ꍇ + // シングルモニタの場合 cv::moveWindow(WIN_MAIN, displays[0].left + 100, displays[0].top + 100); displays[0].right /= 2; @@ -61,28 +61,28 @@ return true; } -// ��{���� +// 基本処理 bool ECTrainerGUI::Routine() { - // ���C���E�C���h�E�t���[���N���A + // メインウインドウフレームクリア _MainFrame = cv::Scalar(49, 52, 49); - // ����摜�o�b�t�@���� + // 視野画像バッファ生成 cv::Mat sceneBuf = _pEct->PImageProc()->GetImage(); if (sceneBuf.empty()) sceneBuf = _blank; - // �\���o�b�t�@�����i��������Worker�N���X�̐����摜�C���������Stimulus�N���X�̉摜���g���j + // 表示バッファ生成(実験中はWorkerクラスの生成画像,非実験中はStimulusクラスの画像を使う) //bool fTarget = _pEct->PWorker()->GetAppStatus() == APP_STATUS::STIM; //bool isNew = fTarget ? : _pEct->PStimulus()->IsNewDisplay(); cv::Mat dispBuf = _pEct->PWorker()->GetTargetImg().clone(); if (dispBuf.empty()) dispBuf = _blank; - // �����_�̕\�� + // 注視点の表示 if (_pEct->PEyeTrack()->GetGazeV().x >= 0) { cv::circle(sceneBuf, _pEct->PEyeTrack()->GetGazeV(), 20, CV_RGB(0, 0, 255), 3); } - // �w�b�_�[�`�� + // ヘッダー描画 cv::Mat header = _Logo.clone(); double contactTime = _pEct->PWorker()->GetContactTime() / 1000.0; double expTime = _pEct->PWorker()->GetExpTime() / 1000.0; @@ -95,7 +95,7 @@ (int)_pEct->PStimulus()->GetTotalExpTime()/60, (int)_pEct->PStimulus()->GetTotalExpTime() % 60), 0.6, 0); cvui::text(_MainFrame, 880, 58, cv::format("%5.1f sec", contactTime), 0.6, 0); - // UI�`�� + // UI描画 cvui::beginColumn(_MainFrame, 10, 100, 140, -1, 10); switch (_pEct->PWorker()->GetAppStatus()) { case APP_STATUS::IDLE: @@ -140,7 +140,7 @@ } cvui::endColumn(); - // �摜�\�� + // 画像表示 cvui::text(_MainFrame, SCENE_BUFFER_POS.x, 100, "SCENE CAMERA"); cv::Mat sceneResized = gocv::KeepAspectResize(sceneBuf, DISP_SIZE.width); cvui::image(_MainFrame, SCENE_BUFFER_POS.x, SCENE_BUFFER_POS.y, sceneResized); @@ -149,25 +149,25 @@ cv::Mat dispResized = gocv::KeepAspectResize(dispBuf, DISP_SIZE.width); cvui::image(_MainFrame, DISP_IMAGE_POS.x, DISP_IMAGE_POS.y, dispResized); - // ����̖����܂ōĐ��`�F�b�N + // 動画の末尾まで再生チェック if (_pEct->PDSMovie()->IsReachToEnd()) { ((BaseProcess*)_pEct->PWorker())->PostMsg(ECTMSG::MOVIE_END); } - // ���C����ʕ\�� + // メイン画面表示 cvui::update(); cv::imshow(WIN_MAIN, _MainFrame); - // �S��ʕ\�� + // 全画面表示 if (_pEct->PWorker()->IsNewFullScreenImg() && !_pEct->PDSMovie()->IsPlaying()) { this->MakeFullDispBuffer(_pEct->PWorker()->GetFullScreenImg()); cv::imshow(WIN_DISP, _FullDispBuf); } - // �X�i�b�v�V���b�g�ۑ� + // スナップショット保存 if (snapshot) cv::imwrite(SNAPSHOT_FILE, _MainFrame); - // �E�C���h�E�~�{�^���ŕ‚����� + // ウインドウ×ボタンで閉じた時 if (_hWndMain != ::FindWindowA(NULL, WIN_MAIN.c_str())) { ((BaseProcess*)_pEct->PWorker())->PostMsg(ECTMSG::SOFTWARE_END); } @@ -177,11 +177,11 @@ return true; } -// �C�x���g���� +// イベント処理 bool ECTrainerGUI::EventProc(MSG& msg) { switch (msg.message) { - case WM_CHAR: // �L�[���� + case WM_CHAR: // キー入力 if (msg.wParam == 27) { #ifdef _DEBUG ((BaseProcess*)_pEct->PWorker())->PostMsg(ECTMSG::SOFTWARE_END); @@ -210,7 +210,7 @@ return true; } -// �h���摜�o�b�t�@�ɉ摜��ݒ� +// 刺激画像バッファに画像を設定 void ECTrainerGUI::MakeFullDispBuffer(cv::Mat img) { cv::Mat buf(_FullDispBuf.size(), CV_8UC3, cv::Scalar(0)); cv::Rect roiRect; diff --git a/ECTrainer2/ECTrainerGUI.h b/ECTrainer2/ECTrainerGUI.h index 723315d..f52950e 100644 --- a/ECTrainer2/ECTrainerGUI.h +++ b/ECTrainer2/ECTrainerGUI.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "BaseProcess.h" #include "GOpenCV.h" @@ -15,32 +15,32 @@ const cv::String WIN_MAIN = "Eye Contact Trainer"; const cv::String HEADER_FILE = "../images/Header.png"; const cv::String SNAPSHOT_FILE = "snapshot.jpg"; - const cv::Size MAIN_FRAME_SIZE = cv::Size(1480, 620); // ���C���E�C���h�E�̃T�C�Y - const cv::Point SCENE_BUFFER_POS = cv::Point(170, 120); // ����摜�\���ʒu - const cv::Point DISP_IMAGE_POS = cv::Point(820, 120); // �h���摜�\���ӎv - const int IMAGE_WIDTH = 640; // ���C���E�C���h�E�ɕ\������摜�� - const cv::Size DISP_SIZE = cv::Size(IMAGE_WIDTH, 480); // ���C���E�C���h�E�ɕ\������摜�T�C�Y + const cv::Size MAIN_FRAME_SIZE = cv::Size(1480, 620); // メインウインドウのサイズ + const cv::Point SCENE_BUFFER_POS = cv::Point(170, 120); // 視野画像表示位置 + const cv::Point DISP_IMAGE_POS = cv::Point(820, 120); // 刺激画像表示意思 + const int IMAGE_WIDTH = 640; // メインウインドウに表示する画像幅 + const cv::Size DISP_SIZE = cv::Size(IMAGE_WIDTH, 480); // メインウインドウに表示する画像サイズ - cv::Mat _MainFrame; // ���C���E�C���h�E�t���[�� - cv::Mat _FullDispBuf; // �h����ʁi�팱�җp�j - cv::Mat _Logo; // ���S - cv::Mat _blank; // �u�����N - HWND _hWndMain; // ���C���E�C���h�E�̃n���h�� + cv::Mat _MainFrame; // メインウインドウフレーム + cv::Mat _FullDispBuf; // 刺激画面(被験者用) + cv::Mat _Logo; // ロゴ + cv::Mat _blank; // ブランク + HWND _hWndMain; // メインウインドウのハンドル - // ��{���� + // 基本処理 bool Routine(); - // �C�x���g���� + // イベント処理 bool EventProc(MSG& msg); - // �S��ʕ\���o�b�t�@�̐��� + // 全画面表示バッファの生成 void MakeFullDispBuffer(cv::Mat img); - std::string ClassName() { return "GUI"; } // FPS�\�� + std::string ClassName() { return "GUI"; } // FPS表示 public: - // �R���X�g���N�^ + // コンストラクタ ECTrainerGUI(ECTrainer* pEct); - // ������ + // 初期化 bool Init(); - // ���C����ʂ̃E�C���h�E�n���h����Ԃ� + // メイン画面のウインドウハンドルを返す HWND GetMainHWnd() { return _hWndMain; } }; diff --git a/ECTrainer2/EyeTrack.cpp b/ECTrainer2/EyeTrack.cpp index 46432dd..0b9e49f 100644 --- a/ECTrainer2/EyeTrack.cpp +++ b/ECTrainer2/EyeTrack.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "EyeTrack.h" #include "ECTrainer.h" @@ -8,7 +8,7 @@ #include -// �R���X�g���N�^ +// コンストラクタ EyeTrack::EyeTrack(ECTrainer* pEct) : BaseProcess(pEct) , _GazeV() , _lastGidx(0) @@ -18,17 +18,17 @@ { } -// ���C�����[�v +// メインループ bool EyeTrack::Routine() { #if defined(EYEDEVICE_GLASS2) - // �ŏ���KeepAlive���M�҂� + // 最初のKeepAlive送信待ち if (!_pEct->PKeepAlive()->IsSent()) { Sleep(1); return true; } - // �f�[�^��M + // データ受信 int slen = _pEct->PKeepAlive()->GetSocketAddrLen(); char buf[KeepAlive::SOCKET_BUF_LEN]; memset(buf, '\0', KeepAlive::SOCKET_BUF_LEN); @@ -40,7 +40,7 @@ } //std::cout << buf << std::endl; - // ��M�f�[�^��� + // 受信データ解析 bool rv = false; GazeData gd(buf); if (gd.gidx > _lastGidx) { diff --git a/ECTrainer2/EyeTrack.h b/ECTrainer2/EyeTrack.h index 2187ea4..50d0a6b 100644 --- a/ECTrainer2/EyeTrack.h +++ b/ECTrainer2/EyeTrack.h @@ -1,11 +1,11 @@ -#pragma once +#pragma once #include "BaseProcess.h" #include "GOpenCV.h" #include "RingBuffer.h" #include "MeanBuffer.h" -// LR�e���v���[�g +// LRテンプレート template class LR { public: @@ -15,37 +15,37 @@ class EyeTrack : public BaseProcess { - static const int MEAN_BUF_SIZE = 20; // �����_�f�[�^�ړ����σT�C�Y + static const int MEAN_BUF_SIZE = 20; // 注視点データ移動平均サイズ - RingBuffer _GazeV; // ����摜���̒����_���W + RingBuffer _GazeV; // 視野画像中の注視点座標 LR _pupilD; - int _lastGidx; // �O��̃f�[�^�C���f�b�N�X + int _lastGidx; // 前回のデータインデックス cv::Point2f _gazePoint; - MeanBuffer _gpCx, _gpCy; // �ړ����σo�b�t�@ + MeanBuffer _gpCx, _gpCy; // 移動平均バッファ - //std::string ClassName() { return "EyeTrack"; } // FPS�\�� + //std::string ClassName() { return "EyeTrack"; } // FPS表示 public: - // �R���X�g���N�^ + // コンストラクタ EyeTrack(ECTrainer* pEct); - // ���C�����[�v + // メインループ bool Routine(); - // �����_�̍X�V�� + // 注視点の更新状況 bool IsNewGazeV() { return _GazeV.IsNew(); } - // �����_���擾 + // 注視点を取得 cv::Point2f GetGazeV() { return _GazeV.Get(); } }; -// �g���b�J�[�f�[�^��̓N���X +// トラッカーデータ解析クラス struct GazeData { long ts = 0; int s = 0; int gidx = 0; int l = 0; - cv::Point2f gp; // �����_ - cv::Point3f gdr, gdl; // �����x�N�g�� L,R - float pdr, pdl; // ���E�a L,R + cv::Point2f gp; // 注視点 + cv::Point3f gdr, gdl; // 視線ベクトル L,R + float pdr, pdl; // 瞳孔径 L,R bool isGP = false; bool isGDR = false; bool isGDL = false; diff --git a/ECTrainer2/GComPort.cpp b/ECTrainer2/GComPort.cpp deleted file mode 100644 index dd3c463..0000000 --- a/ECTrainer2/GComPort.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "GComPort.h" - -// �R���X�g���N�^ -GComPort::GComPort(void) : - mComHandle(INVALID_HANDLE_VALUE) -{ -} - -// �f�X�g���N�^(�I������) -GComPort::~GComPort(void) -{ - this->Close(); -} - -// �|�[�g��T���ĊJ�� -int GComPort::Open(TCHAR* config) -{ - for (int findPort = 1; findPort < COM_SEARCH_MAX; findPort++) { - if (this->Open(findPort, config)) { - this->Send((BYTE*)"s", 1); - Sleep(100); - BYTE buf[256]; - this->Receive(buf, 256); - // TRACE("port %d recv %s\n", findPort, (char*)buf); - if (!strncmp((char*)buf, "OK", 2)) return findPort; - } - } - return 0; -} - -// �|�[�g���J�� -bool GComPort::Open(int port, const TCHAR* config) -{ - if (mComHandle != INVALID_HANDLE_VALUE) this->Close(); - - // �|�[�g�ԍ������񐶐� - if (port < 1) return false; - TCHAR portStr[256]; - wsprintf(portStr, _T("\\\\.\\COM%d"), port); - - // Com�|�[�g���J�� - mComHandle = CreateFile(portStr, - GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - if (mComHandle == INVALID_HANDLE_VALUE) return false; - - // �|�[�g�ݒ� - DCB dcb; - GetCommState(mComHandle, &dcb); - BuildCommDCB(config, &dcb); - dcb.fRtsControl = RTS_CONTROL_DISABLE; - dcb.fOutxDsrFlow = FALSE; - dcb.fDsrSensitivity = FALSE; - dcb.fAbortOnError = FALSE; - SetCommState(mComHandle, &dcb); - - COMMTIMEOUTS timeout; - GetCommTimeouts(mComHandle, &timeout); - timeout.ReadIntervalTimeout = MAXDWORD; - timeout.ReadTotalTimeoutMultiplier = 1; - timeout.ReadTotalTimeoutConstant = 500; - timeout.WriteTotalTimeoutMultiplier = 1; - timeout.WriteTotalTimeoutConstant = 500; - SetCommTimeouts(mComHandle, &timeout); - - return true; -} - -// �|�[�g��‚��� -void GComPort::Close() -{ - if (mComHandle != INVALID_HANDLE_VALUE) - { - CloseHandle(mComHandle); - mComHandle = INVALID_HANDLE_VALUE; - } -} - -// �f�[�^���M -DWORD GComPort::Send(const BYTE* data, DWORD dataLen) -{ - if (mComHandle == INVALID_HANDLE_VALUE) return 0; - - DWORD sendSize; // ���M�����o�C�g�� - WriteFile(mComHandle, data, dataLen, &sendSize, NULL); - // TRACE("COM SEND: %s", (char*)data); - - return sendSize; -} - -// �f�[�^��M -DWORD GComPort::Receive(BYTE* buffer, DWORD bufferLen) -{ - if (mComHandle == INVALID_HANDLE_VALUE) return 0; - - DWORD errors; - COMSTAT stat; - ClearCommError(mComHandle, &errors, &stat); - DWORD queSize = stat.cbInQue; - if (queSize < 1) return 0; - - if (bufferLen < queSize) queSize = bufferLen; - DWORD receiveSize; // ��M�����o�C�g�� - ReadFile(mComHandle, buffer, queSize, &receiveSize, NULL); - if (receiveSize < bufferLen) buffer[receiveSize] = '\0'; // ��M�f�[�^�ɏI�[������lj� - - // TRACE("COM RECV: %s", (char*)buffer); - - return receiveSize; -} - -// �^�C���A�E�g�t���f�[�^��M -DWORD GComPort::WaitReceive(BYTE* buffer, DWORD bufferLen, const int timeout) -{ - if (mComHandle == INVALID_HANDLE_VALUE) return 0; - - int receiveSize; - for (int i = 0; i < timeout && - (receiveSize = this->Receive(buffer, bufferLen)) < 1; i++) Sleep(1); - - return receiveSize; -} diff --git a/ECTrainer2/GComPort.h b/ECTrainer2/GComPort.h deleted file mode 100644 index 61c88ee..0000000 --- a/ECTrainer2/GComPort.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include -#include - -class GComPort -{ - HANDLE mComHandle; - -public: - static const int COM_SEARCH_MAX = 20; - - GComPort(void); - ~GComPort(void); - int Open(TCHAR* config); - bool Open(int port, const TCHAR* config); - void Close(); - DWORD Send(const BYTE* data, DWORD dataLen); - DWORD Receive(BYTE* buffer, DWORD bufferLen); - DWORD WaitReceive(BYTE* buffer, DWORD bufferLen, int timeout); -}; diff --git a/ECTrainer2/GOpenCV.cpp b/ECTrainer2/GOpenCV.cpp index 286b1eb..079c1d3 100644 --- a/ECTrainer2/GOpenCV.cpp +++ b/ECTrainer2/GOpenCV.cpp @@ -1,9 +1,9 @@ -#include "GOpenCV.h" +#include "GOpenCV.h" #include namespace gocv { -// �҂��Ȃ�waitKey() +// 待たないwaitKey() int noWaitKey() { MSG msg; while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { @@ -21,12 +21,12 @@ return -1; } -// �����摜���c���ɘA���\�� +// 複数画像を縦横に連結表示 void imShowMulti( - cv::String winname, std::vector& imgs, // �S�Ă̕\���摜�i8bit 3ch or 8bit 1ch�̂�) - unsigned int cols, // ���̘A���� - unsigned int rows, // �c�̘A���� - cv::Size imgsize, // �\������摜�T�C�Y + cv::String winname, std::vector& imgs, // 全ての表示画像(8bit 3ch or 8bit 1chのみ) + unsigned int cols, // 横の連結数 + unsigned int rows, // 縦の連結数 + cv::Size imgsize, // 表示する画像サイズ unsigned int border) { if (imgs.size() < 1 || cols < 1 || rows < 1) return; @@ -54,25 +54,25 @@ imshow(winname, board); } -// �c�����ۂ������T�C�Y +// 縦横比を保ったリサイズ cv::Mat KeepAspectResize(cv::Mat& img, int width, int height) { cv::Size outputSize; if (width > 0) { if (height > 0) { - // �c���w��i���T�C�Y�Ɏ��܂�悤�ɂ���j + // 縦横指定(両サイズに収まるようにする) outputSize = cv::Size(height * img.cols / img.rows, width * img.rows / img.cols); if (outputSize.width > width) outputSize.width = width; else outputSize.height = height; } else { - // �����w�� + // 横幅指定 outputSize = cv::Size(width, width * img.rows / img.cols); } } else { if (height > 0) { - // �c���w�� + // 縦幅指定 outputSize = cv::Size(height * img.cols / img.rows, height); } else { - // �c���ǂ�����w�薳���ꍇ�͓��͂̃R�s�[��Ԃ� + // 縦横どちらも指定無い場合は入力のコピーを返す return img.clone(); } } diff --git a/ECTrainer2/GOpenCV.h b/ECTrainer2/GOpenCV.h index 860052e..3232a4d 100644 --- a/ECTrainer2/GOpenCV.h +++ b/ECTrainer2/GOpenCV.h @@ -1,37 +1,37 @@ - -// OpenCV 3�n, 4�n ���ʃw�b�_�[�t�@�C�� + +// OpenCV 3系, 4系 共通ヘッダーファイル // T.Nakaguchi, CFME, Chiba Univ., 2019 #pragma once -// �w�b�_�[�t�@�C�� +// ヘッダーファイル #pragma warning(disable: 4819) #include #include #pragma warning(default: 4819) -// �o�[�W�����擾 +// バージョン取得 #define CV_VERSION_STR CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION) -// �r���h���[�h +// ビルドモード #ifdef _DEBUG #define CV_EXT_STR "d.lib" #else #define CV_EXT_STR ".lib" #endif -// ���C�u�����̃����N�i�s�v�ȕ��̓R�����g�A�E�g�j -#define PRE_COMPILE 0 // �C���X�g�[���łȂ� 1 �•ʃ��C�u�����g�p���� 0 +// ライブラリのリンク(不要な物はコメントアウト) +#define PRE_COMPILE 0 // インストール版なら 1 個別ライブラリ使用時は 0 #define PREHEAD "opencv_" #if PRE_COMPILE -// OpenCV3 �C���X�g�[���� -#pragma comment(lib, PREHEAD "world" CV_VERSION_STR CV_EXT_STR) // �S�� -#pragma comment(lib, PREHEAD "ts" CV_VERSION_STR CV_EXT_STR) // �f���֘A +// OpenCV3 インストール版 +#pragma comment(lib, PREHEAD "world" CV_VERSION_STR CV_EXT_STR) // 全て +#pragma comment(lib, PREHEAD "ts" CV_VERSION_STR CV_EXT_STR) // 映像関連 #else -// �•ʂ̃��C�u�����w�� �iCmake��Static�Ŏg�p���Ȃǁj -// ��{���W���[�� +// 個別のライブラリ指定 (CmakeやStatic版使用時など) +// 基本モジュール #pragma comment(lib, PREHEAD "core" CV_VERSION_STR CV_EXT_STR) // Core functionality #pragma comment(lib, PREHEAD "imgproc" CV_VERSION_STR CV_EXT_STR) // Image processing #pragma comment(lib, PREHEAD "imgcodecs" CV_VERSION_STR CV_EXT_STR) // Image file reading and writing @@ -63,7 +63,7 @@ //#pragma comment(lib, PREHEAD "videostab" CV_VERSION_STR CV_EXT_STR) // Video Stabilization //#pragma comment(lib, PREHEAD "viz" CV_VERSION_STR CV_EXT_STR) // 3D Visualizer -// �g�����W���[�� +// 拡張モジュール #pragma comment(lib, PREHEAD "aruco" CV_VERSION_STR CV_EXT_STR) // ArUco Marker Detection //#pragma comment(lib, PREHEAD "bgsegm" CV_VERSION_STR CV_EXT_STR) // Improved Background-Foreground Segmentation Methods //#pragma comment(lib, PREHEAD "bioinspired" CV_VERSION_STR CV_EXT_STR) // Biologically inspired vision models and derivated tools @@ -105,19 +105,19 @@ namespace gocv { -// �҂��Ȃ�waitKey() -// �߂�l�F���̓L�[�R�[�h�C�L�[���͂Ȃ� -1�CWM_QUIT��M 0 +// 待たないwaitKey() +// 戻り値:入力キーコード,キー入力なし -1,WM_QUIT受信 0 int noWaitKey(); -// �����摜���c���ɘA���\�� +// 複数画像を縦横に連結表示 void imShowMulti( - cv::String winname, std::vector& imgs, // �S�Ă̕\���摜�i8bit 3ch or 8bit 1ch�̂�) - unsigned int cols, // ���̘A���� - unsigned int rows, // �c�̘A���� - cv::Size imgsize, // �\������摜�T�C�Y + cv::String winname, std::vector& imgs, // 全ての表示画像(8bit 3ch or 8bit 1chのみ) + unsigned int cols, // 横の連結数 + unsigned int rows, // 縦の連結数 + cv::Size imgsize, // 表示する画像サイズ unsigned int border); -// �c�����ۂ������T�C�Y +// 縦横比を保ったリサイズ cv::Mat KeepAspectResize(cv::Mat& img, int width = 0, int height = 0); }; // namespace gocv diff --git a/ECTrainer2/ImageProc.cpp b/ECTrainer2/ImageProc.cpp index 6e4ec5c..c623983 100644 --- a/ECTrainer2/ImageProc.cpp +++ b/ECTrainer2/ImageProc.cpp @@ -1,18 +1,18 @@ - + #include "ECTrainer.h" #include "ImageProc.h" #include "SceneCamera.h" #include "Marker.h" -// �R���X�g���N�^ +// コンストラクタ ImageProc::ImageProc(ECTrainer* pEct) : BaseProcess(pEct) , _OutputBuf() { } -// ���[�v +// ループ bool ImageProc::Routine() { - // �V�[���J�����̃t���[���X�V�҂� + // シーンカメラのフレーム更新待ち if (!_pEct->PSceneCamera()->IsNew()) { Sleep(1); return false; diff --git a/ECTrainer2/ImageProc.h b/ECTrainer2/ImageProc.h index 908ab63..0d09f5c 100644 --- a/ECTrainer2/ImageProc.h +++ b/ECTrainer2/ImageProc.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "GOpenCV.h" #include "BaseProcess.h" @@ -10,11 +10,11 @@ { RingBuffer _OutputBuf; - //std::string ClassName() { return "ImageProc"; } // FPS�\�� + //std::string ClassName() { return "ImageProc"; } // FPS表示 public: ImageProc(ECTrainer* pEct); bool Routine(); - // �o�̓o�b�t�@������o�� + // 出力バッファから取り出し cv::Mat GetImage() { return _OutputBuf.Get(); } }; diff --git a/ECTrainer2/KeepAlive.cpp b/ECTrainer2/KeepAlive.cpp index d64551d..d15423b 100644 --- a/ECTrainer2/KeepAlive.cpp +++ b/ECTrainer2/KeepAlive.cpp @@ -1,11 +1,11 @@ -#include +#include #include #include #include "KeepAlive.h" #include "ECTrainer.h" #include "myWinUtils.h" -// �R���X�g���N�^ +// コンストラクタ KeepAlive::KeepAlive(ECTrainer* pEct) : BaseProcess(pEct) , _sent(false) , _socket(NULL) @@ -14,7 +14,7 @@ memset((char*)&_socketAddr, 0, _socketAddrLen); } -// ������ +// 初期化 bool KeepAlive::Init() { #if defined(EYEDEVICE_GLASS2) // Initialize winsock @@ -40,7 +40,7 @@ return true; } -// ���C�����[�v +// メインループ bool KeepAlive::Routine() { #if defined(EYEDEVICE_GLASS2) const std::string KA_DATA_MSG = "{\"type\": \"live.data.unicast\", \"key\": \"some_GUID\", \"op\": \"start\"}"; diff --git a/ECTrainer2/KeepAlive.h b/ECTrainer2/KeepAlive.h index 29c34e3..7a55773 100644 --- a/ECTrainer2/KeepAlive.h +++ b/ECTrainer2/KeepAlive.h @@ -1,34 +1,34 @@ -#pragma once +#pragma once #include "BaseProcess.h" class KeepAlive : public BaseProcess { const int PORT = 49152; // The port on which to listen for incoming data - const int KEEP_ALIVE_WAIT_COUNT = 20; // ���M�Ԋu x100ms + const int KEEP_ALIVE_WAIT_COUNT = 20; // 送信間隔 x100ms - SOCKET _socket; // �\�P�b�g - struct sockaddr_in _socketAddr; // �ڑ���A�h���X - bool _sent; // �V�O�i�����M��� true: ���M�� false: �����M - int _socketAddrLen; // �A�h���X���̃T�C�Y - int _count; // ���[�v�J�E���g + SOCKET _socket; // ソケット + struct sockaddr_in _socketAddr; // 接続先アドレス + bool _sent; // シグナル発信状態 true: 発信済 false: 未発信 + int _socketAddrLen; // アドレス情報のサイズ + int _count; // ループカウント - //std::string ClassName() { return "KeepAlive"; } // FPS�\�� + //std::string ClassName() { return "KeepAlive"; } // FPS表示 public: - static const int SOCKET_BUF_LEN = 512; // Socket�ʐM�o�b�t�@�T�C�Y + static const int SOCKET_BUF_LEN = 512; // Socket通信バッファサイズ - // �R���X�g���N�^ + // コンストラクタ KeepAlive(ECTrainer* pEct); - // ������ + // 初期化 bool Init(); - // ���C�����[�v + // メインループ bool Routine(); - // �V�O�i�����M��Ԏ擾 + // シグナル発信状態取得 bool IsSent() { return _sent; }; - // �\�P�b�g�擾 + // ソケット取得 SOCKET GetSocket() { return _socket; } - // �\�P�b�g�A�h���X�擾 + // ソケットアドレス取得 struct sockaddr* GetSocketAddr() { return (struct sockaddr*)&_socketAddr; } - // �\�P�b�g�A�h���X���擾 + // ソケットアドレス長取得 int GetSocketAddrLen() { return _socketAddrLen; } }; diff --git a/ECTrainer2/Marker.cpp b/ECTrainer2/Marker.cpp index daa4983..89ac6b2 100644 --- a/ECTrainer2/Marker.cpp +++ b/ECTrainer2/Marker.cpp @@ -1,9 +1,9 @@ - + #include "Marker.h" #include "ECTrainer.h" #include "myWinUtils.h" -// �R���X�g���N�^ +// コンストラクタ Marker::Marker() : _detected(false) , _HomographyV2I() @@ -13,12 +13,12 @@ _HomographyV2I.Put(cv::Mat::zeros(3, 3, CV_64F)); } -// �}�[�J�[���W�̌v�Z +// マーカー座標の計算 void Marker::CalcMarkerCorners(cv::Size imgsize) { - // �萔�̌v�Z + // 定数の計算 int itvX = imgsize.width - (SIZE.x + MARGIN.x * 2); int itvY = (imgsize.height - (SIZE.x + MARGIN.x * 2)) / 3; - // ���W�v�Z + // 座標計算 _Corners.clear(); for (int ix = 0; ix < 2; ix++) { for (int iy = 0; iy < 4; iy++) { @@ -41,16 +41,16 @@ } } -// �}�[�J�[�̌��o +// マーカーの検出 void Marker::Detect(cv::Mat& img) { - // �}�[�J�[�̌��o + // マーカーの検出 std::vector markerIds; std::vector> corners; cv::Ptr parameters = cv::aruco::DetectorParameters::create(); cv::aruco::detectMarkers(img, _Dictionary, corners, markerIds, parameters); cv::aruco::drawDetectedMarkers(img, corners, markerIds); - // �Ή��_�̗� + // 対応点の列挙 std::vector cornerI, cornerV; for (int i = 0; i < corners.size(); i++) { if (markerIds[i] - 1 < _Corners.size()) { @@ -65,7 +65,7 @@ return; } - // �z���O���t�B�s��̎Z�o + // ホモグラフィ行列の算出 cv::Mat h = findHomography(cornerV, cornerI); if (h.empty()) { _detected = false; @@ -75,7 +75,7 @@ } } -// ���W�ϊ��i����摜���W���摜���W�j +// 座標変換(視野画像座標→画像座標) cv::Point2f Marker::ConvV2I(cv::Point gazeV) { cv::Mat h = _HomographyV2I.Get(); if (h.empty()) return cv::Point2f(-1.F, -1.F); @@ -95,7 +95,7 @@ } #if 0 -// �}�[�J�[��`�悷�� +// マーカーを描画する void Marker::DrawMarker(cv::Mat& img) { if (_Corners.size() < 1) { mwut::DebugPrintf(_T("Marker not generated")); diff --git a/ECTrainer2/Marker.h b/ECTrainer2/Marker.h index be91ad4..cc13262 100644 --- a/ECTrainer2/Marker.h +++ b/ECTrainer2/Marker.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "GOpenCV.h" #include "RingBuffer.h" @@ -6,31 +6,31 @@ class Marker { - const cv::Point SIZE = cv::Point(100, 100); // AR�}�[�J�[�̃T�C�Y - const cv::Point MARGIN = cv::Point(10, 10); // AR�}�[�J�[���͘g�̕� - const float OUTER_MARGIN = 0.01F; // �}�[�J�[�`��p + const cv::Point SIZE = cv::Point(100, 100); // ARマーカーのサイズ + const cv::Point MARGIN = cv::Point(10, 10); // ARマーカー周囲枠の幅 + const float OUTER_MARGIN = 0.01F; // マーカー描画用 - std::vector> _Corners; // �}�[�J�[���_���W�i�񎦉摜���W�j - cv::Ptr _Dictionary; // AR�}�[�J�[�����Z�b�g - bool _detected; // �}�[�J�[���o�”ۏ�� - RingBuffer _HomographyV2I; // �ϊ��s�� ����摜���񎦉摜 + std::vector> _Corners; // マーカー頂点座標(提示画像座標) + cv::Ptr _Dictionary; // ARマーカー辞書セット + bool _detected; // マーカー検出可否状態 + RingBuffer _HomographyV2I; // 変換行列 視野画像→提示画像 - // �}�[�J�[���_�̐��� + // マーカー頂点の生成 void CalcMarkerCorners(cv::Size imgsize); public: - const cv::Size IMGSIZE = cv::Size(1920, 1080); // �񎦉摜�T�C�Y + const cv::Size IMGSIZE = cv::Size(1920, 1080); // 提示画像サイズ - // �R���X�g���N�^ + // コンストラクタ Marker(); - // �}�[�J�[���o + // マーカー検出 void Detect(cv::Mat& img); - // �}�[�J�[���o��Ԃ��擾 + // マーカー検出状態を取得 bool IsDetected() { return _detected; } - // ���W�ϊ��i����摜���W���摜���W�j + // 座標変換(視野画像座標→画像座標) cv::Point2f ConvV2I(cv::Point gazeV); - // �ϊ��s����擾 + // 変換行列を取得 cv::Mat GetHomography() { return _HomographyV2I.Get(); } - //void DrawMarker(cv::Mat& img); // �摜�Ƀ}�[�J�[��`�� + //void DrawMarker(cv::Mat& img); // 画像にマーカーを描画 }; diff --git a/ECTrainer2/MeanBuffer.h b/ECTrainer2/MeanBuffer.h index df36e8f..c39b2af 100644 --- a/ECTrainer2/MeanBuffer.h +++ b/ECTrainer2/MeanBuffer.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include diff --git a/ECTrainer2/MovieObject.cpp b/ECTrainer2/MovieObject.cpp index e98d68a..faf4d91 100644 --- a/ECTrainer2/MovieObject.cpp +++ b/ECTrainer2/MovieObject.cpp @@ -1,20 +1,20 @@ -#include "MovieObject.h" +#include "MovieObject.h" -// �R���X�g���N�^ +// コンストラクタ MovieObject::MovieObject() :_lastAccess(0) { } -// �e�[�u������f�[�^���Z�b�g +// テーブルからデータをセット int MovieObject::SetData(mwut::STR_TABLE table) { _frame.clear(); int addLines = 0; for (int r = 0; r < table.size(); r++) { - // �s�`�F�b�N + // 行チェック int cols = (int)table[r].size(); if (cols < 4 || (cols - 1) % 3 != 0) continue; @@ -25,7 +25,7 @@ if (!check) continue; - // �f�[�^�ǂݍ��� + // データ読み込み FrameInfo fi; fi.eTime = (float)atof(table[r][0].c_str()); int nElements = (cols - 1) / 3; @@ -51,25 +51,25 @@ return addLines; } -// �t�@�C��������f�[�^���Z�b�g +// ファイル名からデータをセット int MovieObject::SetData(const std::string& filename) { mwut::STR_TABLE table; if (!mwut::ReadTable(filename, table)) return 0; return SetData(table); } -// �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�� + // 前回結果から前方に探索 int index = _lastAccess; for (; index < _frame.size(); index++) { if (_frame[index].eTime > sTime) break; diff --git a/ECTrainer2/MovieObject.h b/ECTrainer2/MovieObject.h index 3fa832b..4b088f2 100644 --- a/ECTrainer2/MovieObject.h +++ b/ECTrainer2/MovieObject.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -6,11 +6,11 @@ #include "myWinUtils.h" -// �\���v�f +// 構成要素 struct Element { - float x; // X���W - float y; // Y���W - float d; // �T�C�Y + float x; // X座標 + float y; // Y座標 + float d; // サイズ Element(float X, float Y, float D) { x = X; @@ -19,30 +19,30 @@ } }; -// �t���[����� +// フレーム情報 struct FrameInfo { - float eTime; // ���� - std::vector elements; // �v�f�Q + float eTime; // 時間 + std::vector elements; // 要素群 }; -// �f���I�u�W�F�N�g�N���X +// 映像オブジェクトクラス class MovieObject { std::vector _frame; int _lastAccess; public: - // �R���X�g���N�^ + // コンストラクタ MovieObject(); - // �e�[�u������f�[�^���Z�b�g + // テーブルからデータをセット int SetData(mwut::STR_TABLE table); - // �t�@�C��������f�[�^���Z�b�g + // ファイル名からデータをセット int SetData(const std::string& filename); - // �w�莞�Ԃ̃I�u�W�F�N�g����Ԃ� + // 指定時間のオブジェクト情報を返す std::vector GetElements(float sTime); - // �t���[������Ԃ� + // フレーム数を返す int GetNumFrames() { return (int)_frame.size(); } - // �󂩂ǂ��� + // 空かどうか bool IsEmpty() { return _frame.size() < 1; } - // ���� + // 消去 void Clear() { _frame.clear(); _lastAccess = 0; } }; diff --git a/ECTrainer2/MyWinUtils.h b/ECTrainer2/MyWinUtils.h index eec65fa..7c2a8c2 100644 --- a/ECTrainer2/MyWinUtils.h +++ b/ECTrainer2/MyWinUtils.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -9,7 +9,7 @@ typedef std::vector> STR_TABLE; - // �X���b�v�N���X + // スワップクラス template class SWAP { public: @@ -20,41 +20,41 @@ } }; - // �}���`�o�C�g����������C�h������iUNICODE�j�ɕϊ� + // マルチバイト文字列をワイド文字列(UNICODE)に変換 std::wstring Multi2Wide(std::string const& src); - // �����t���f�o�b�O�o�� + // 書式付きデバッグ出力 int DebugPrintf(LPCTSTR format, ...); - // �e�[�u����ǂݍ��� + // テーブルを読み込み bool ReadTable(const std::string& filename, STR_TABLE& table, const char delimiter = ','); - // �}���`�f�B�X�v���C�̏����擾 - // �v�f0�F���C���E�C���h�E + // マルチディスプレイの情報を取得 + // 要素0:メインウインドウ std::vector GetDisplayInfo(); - // �f�B�X�v���C���擾�R�[���o�b�N + // ディスプレイ情報取得コールバック BOOL CALLBACK MonitorEnumProc( HMONITOR hMon, HDC hdcMon, LPRECT lpMon, LPARAM dwData); - // ���S�ȃf���[�g + // 安全なデリート void SafeDelete(void** ptr); - // ���t����������擾 + // 日付時刻文字列取得 std::string DateTimeStr(); - // �����x�^�C�}�[�N���X + // 高精度タイマークラス class HPTimer { - LARGE_INTEGER _nFreq; // ���g�� - LARGE_INTEGER _nBegin; // �J�n���� - LARGE_INTEGER _nLast; // �O��₢���킹���� + LARGE_INTEGER _nFreq; // 周波数 + LARGE_INTEGER _nBegin; // 開始時間 + LARGE_INTEGER _nLast; // 前回問い合わせ時間 double Calc(LARGE_INTEGER before); public: HPTimer(); - double Elapse(); // �J�n������̌o�ߎ���(ms) - double Interval(); // �O�񂩂�̌o�ߎ���(ms) - void Reset(); // �J�n���ԃ��Z�b�g - static void HPSleep(double delayms); // �����xSleep + double Elapse(); // 開始時からの経過時間(ms) + double Interval(); // 前回からの経過時間(ms) + void Reset(); // 開始時間リセット + static void HPSleep(double delayms); // 高精度Sleep }; } diff --git a/ECTrainer2/REST_Handler.cpp b/ECTrainer2/REST_Handler.cpp index b2a69b2..f68205a 100644 --- a/ECTrainer2/REST_Handler.cpp +++ b/ECTrainer2/REST_Handler.cpp @@ -1,4 +1,4 @@ -#include "REST_Handler.h" +#include "REST_Handler.h" http_response REST_Handler::POST_Request(const TCHAR* baseURL, json::value data) { diff --git a/ECTrainer2/REST_Handler.h b/ECTrainer2/REST_Handler.h index 4186cd6..24f390b 100644 --- a/ECTrainer2/REST_Handler.h +++ b/ECTrainer2/REST_Handler.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include diff --git a/ECTrainer2/RingBuffer.h b/ECTrainer2/RingBuffer.h index 77115e8..07fe453 100644 --- a/ECTrainer2/RingBuffer.h +++ b/ECTrainer2/RingBuffer.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include @@ -14,24 +14,24 @@ int _read; bool _update; public: - // �R���X�g���N�^ - // size �o�b�t�@�̃T�C�Y - // initial �S�v�f�̏����l + // コンストラクタ + // size バッファのサイズ + // initial 全要素の初期値 RingBuffer(int size = DEEFAULT_SIZE); RingBuffer(int size, T initial); - // �f�X�g���N�^ + // デストラクタ ~RingBuffer(); - // �f�[�^���i�[���� + // データを格納する void Put(T value); - // �ŐV�̃f�[�^���o�� - // peeking true ���o���L�^���Ȃ� false (�f�t�H���g�j���o���L�^���� - // past �ߋ��ɂ����̂ڂ�i�f�t�H���g=0�j + // 最新のデータ取り出し + // peeking true 取り出し記録しない false (デフォルト)取り出し記録する + // past 過去にさかのぼる(デフォルト=0) T Get(bool peeking = false, int past = 0); - // �V�����f�[�^���lj����ꂽ�� + // 新しいデータが追加されたか bool IsNew() { return _update; }; }; diff --git a/ECTrainer2/SceneCamera.cpp b/ECTrainer2/SceneCamera.cpp index c5c6676..1f33dff 100644 --- a/ECTrainer2/SceneCamera.cpp +++ b/ECTrainer2/SceneCamera.cpp @@ -1,4 +1,4 @@ - + #include #include @@ -8,15 +8,15 @@ #include "ECTrainerGUI.h" #include "MyWinUtils.h" -// �R���X�g���N�^ +// コンストラクタ SceneCamera::SceneCamera(ECTrainer* pEct) : BaseProcess(pEct) , _buffer() { } -// ������ +// 初期化 bool SceneCamera::Init() { - // ���E�J�����ɐڑ� + // 視界カメラに接続 #if defined(EYEDEVICE_GLASS2) _SceneCam.open("rtsp://" TOBII_ADDR ":8554/live/scene"); _pEct->PWorker()->EventLog(_T("Tobii Glasses camera connected.")); @@ -29,7 +29,7 @@ _pEct->PWorker()->EventLog(_T("Cannot connect camera.")); return false; } - // �摜�T�C�Y��ۑ� + // 画像サイズを保存 cv::Mat scene; _SceneCam >> scene; _sceneSize = scene.size(); @@ -38,13 +38,13 @@ return true; } -// ���[�v +// ループ bool SceneCamera::Routine() { - // �V�[���B�e + // シーン撮影 cv::Mat scene; _SceneCam >> scene; _buffer.Put(scene); - Sleep(15); // Tobii�̃V�[���J������25FPS 15ms��Sleep�͖��Ȃ� + Sleep(15); // Tobiiのシーンカメラは25FPS 15msのSleepは問題ない return true; } diff --git a/ECTrainer2/SceneCamera.h b/ECTrainer2/SceneCamera.h index 04da545..00f7fed 100644 --- a/ECTrainer2/SceneCamera.h +++ b/ECTrainer2/SceneCamera.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "GOpenCV.h" #include "BaseProcess.h" @@ -12,7 +12,7 @@ RingBuffer _buffer; cv::Size _sceneSize; - std::string ClassName() { return "SceneCamera"; } // FPS�\�� + std::string ClassName() { return "SceneCamera"; } // FPS表示 public: SceneCamera(ECTrainer* pEct); diff --git a/ECTrainer2/Stimulus.cpp b/ECTrainer2/Stimulus.cpp index f088065..69d2555 100644 --- a/ECTrainer2/Stimulus.cpp +++ b/ECTrainer2/Stimulus.cpp @@ -1,9 +1,9 @@ -#include "BaseProcess.h" +#include "BaseProcess.h" #include "Stimulus.h" #include "ECTrainer.h" #include "Worker.h" -// �R���X�g���N�^ +// コンストラクタ Stimulus::Stimulus(ECTrainer* pEct) : BaseProcess(pEct) , _StimNo(-1) , _pMovieObject(NULL) @@ -19,18 +19,18 @@ mwut::SafeDelete((void**)&_pMovieObject); } -// ������ +// 初期化 bool Stimulus::Init() { _Display.Put(cv::imread(OPENING_FILE)); - // �ݒ�t�@�C�����e�[�u���ɓǂݍ��� + // 設定ファイルをテーブルに読み込み mwut::STR_TABLE table; if (!mwut::ReadTable(STIM_CONFIG_FILE, table)) { mwut::DebugPrintf(_T("Can't open config file : %d\n"), STIM_CONFIG_FILE.c_str()); return false; } - // �e�[�u������\���̂֊i�[ + // テーブルから構造体へ格納 _TotalExpTime = 0; for (int r = 0; r < table.size(); r++) { if (table[r].size() != 5 || atoi(table[r][0].c_str()) < 1) continue; @@ -51,17 +51,17 @@ return true; } -// ��{���� +// 基本処理 bool Stimulus::Routine() { if (_StimNo >= 0) { double eTime = _StimTimer.Elapse(); - // �h���؂�ւ��^�C���L�[�p�[ + // 刺激切り替えタイムキーパー if (eTime / 1000. > (double)_StimInfoSet[_StimNo].dulation) { this->MoveNext(); } - // �����ǂݍ��� + // 動画を読み込む if (_StimInfoSet[_StimNo].type == 2 && _cap.isOpened()) { _cap.set(cv::CAP_PROP_POS_MSEC, eTime); cv::Mat frame; @@ -74,49 +74,49 @@ return true; } -// �C�x���g���� +// イベント処理 bool Stimulus::EventProc(MSG& msg) { switch (msg.message) { - case (int)ECTMSG::CALIB_START: // �L�����u���[�V�����J�n + case (int)ECTMSG::CALIB_START: // キャリブレーション開始 this->SetImage(CALIB_FILE); break; - case (int)ECTMSG::CALIB_OK: // �L�����u���[�V�������� + case (int)ECTMSG::CALIB_OK: // キャリブレーション成功 this->SetImage(CALIB_COMPLETE_FILE); break; - case (int)ECTMSG::CALIB_FAILED: // �L�����u���[�V�������s - case (int)ECTMSG::CALIB_ERR: // �L�����u���[�V�����G���[ + case (int)ECTMSG::CALIB_FAILED: // キャリブレーション失敗 + case (int)ECTMSG::CALIB_ERR: // キャリブレーションエラー this->SetImage(CALIB_FAILED_FILE); break; - case (int)ECTMSG::EXP_START: // �����J�n + case (int)ECTMSG::EXP_START: // 実験開始 this->SetStimulus(0); break; - case (int)ECTMSG::EXP_STOP: // ������~ + case (int)ECTMSG::EXP_STOP: // 実験停止 _StimNo = -1; this->SetImage(EXP_STOP_FILE); break; - case (int)ECTMSG::EXP_END: // �����I�� + case (int)ECTMSG::EXP_END: // 実験終了 _StimNo = -1; this->SetImage(EXP_DONE_FILE); break; - case (int)ECTMSG::SYSTEM_ERROR: // �V�X�e���G���[ + case (int)ECTMSG::SYSTEM_ERROR: // システムエラー _StimNo = -1; this->SetImage(ERROR_FILE); break; - case (int)ECTMSG::MOVIE_END: // ����Đ��������ɓ��B + case (int)ECTMSG::MOVIE_END: // 動画再生が末尾に到達 this->MoveNext(); break; } return true; } -// ���̎h���ֈړ� +// 次の刺激へ移動 bool Stimulus::MoveNext() { if (_StimNo < 0) return false; @@ -133,7 +133,7 @@ return true; } -// �h���� +// 刺激提示 bool Stimulus::SetStimulus(int newStimNo) { if (newStimNo < 0 || newStimNo >= _StimInfoSet.size()) return false; @@ -162,7 +162,7 @@ return true; } -// �摜�ǂݍ��� +// 画像読み込み bool Stimulus::SetImage(cv::String imageFile) { auto img = cv::imread(imageFile); if (img.empty()) { @@ -175,7 +175,7 @@ return true; } -// ����I�u�W�F�N�g�̓ǂݍ��� +// 動画オブジェクトの読み込み void Stimulus::LoadMovieObject(int stimNo) { int nFrames = _pMovieObject->SetData(_StimInfoSet[stimNo].csvfile); @@ -183,14 +183,14 @@ mwut::Multi2Wide(_StimInfoSet[stimNo].csvfile).c_str(), nFrames); } -// �^�[�Q�b�g�����擾 +// ターゲット情報を取得 std::vector Stimulus::GetMovieObject(float eTime) { if (eTime < 0) eTime = (float)_StimTimer.Elapse() / 1000.F; return _pMovieObject->GetElements(eTime); } -// �摜�Ƀ}�[�J�[��`�� +// 画像にマーカーを描画 //void Stimulus::StimWithMarker() { // cv::Mat img = cv::imread(_StimImages[_StimNo].filename); // _pMarker->Generate(img.size()); diff --git a/ECTrainer2/Stimulus.h b/ECTrainer2/Stimulus.h index 846f07a..b3c28d5 100644 --- a/ECTrainer2/Stimulus.h +++ b/ECTrainer2/Stimulus.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -14,12 +14,12 @@ enum class STIM_PAGE; struct StimInfo { - int type; // 1:�摜 2:���� - std::string filepath; // �񎦃t�@�C�����i�p�X�t���j - std::string filename; // �񎦃t�@�C�����i�p�X�Ȃ��j - std::string smallmovie; // �k������t�@�C���� - float dulation; // ����(sec) - std::string csvfile; // �^�[�Q�b�g���W�t�@�C���i�����ꍇ��_�A���_�[�o�[�j + int type; // 1:画像 2:動画 + std::string filepath; // 提示ファイル名(パス付き) + std::string filename; // 提示ファイル名(パスなし) + std::string smallmovie; // 縮小動画ファイル名 + float dulation; // 時間(sec) + std::string csvfile; // ターゲット座標ファイル(無い場合は_アンダーバー) }; class Stimulus : public BaseProcess @@ -36,57 +36,57 @@ const cv::String EXP_STOP_FILE = "../images/ExpStop.png"; const cv::String EXP_DONE_FILE = "../images/ExpDone.png"; - std::vector _StimInfoSet; // �����ݒ� - MovieObject* _pMovieObject; // �^�[�Q�b�g��� - int _StimNo; // �h���f�[�^�ԍ��@-1:��~ - mwut::HPTimer _StimTimer; // �h���񎦃^�C�}�[ - RingBuffer _Display; // �\���摜 - RingBuffer _Movie; // ������ - cv::VideoCapture _cap; // ����I�u�W�F�N�g + std::vector _StimInfoSet; // 実験設定 + MovieObject* _pMovieObject; // ターゲット情報 + int _StimNo; // 刺激データ番号 -1:停止 + mwut::HPTimer _StimTimer; // 刺激提示タイマー + RingBuffer _Display; // 表示画像 + RingBuffer _Movie; // 動画情報 + cv::VideoCapture _cap; // 動画オブジェクト float _TotalExpTime; - // �h����ݒ� + // 刺激を設定 bool SetStimulus(int newStimNo); - // ����I�u�W�F�N�g�̓ǂݍ��� + // 動画オブジェクトの読み込み void LoadMovieObject(int stimNo); - // ��{���� + // 基本処理 bool Routine(); - // �C�x���g���� + // イベント処理 bool EventProc(MSG& msg); - // ���̎h���ֈړ� + // 次の刺激へ移動 bool MoveNext(); - // �摜�ǂݍ��� + // 画像読み込み bool SetImage(cv::String imageFile); - // �摜�Ƀ}�[�J�[��`�� + // 画像にマーカーを描画 //void StimWithMarker(); - std::string ClassName() { return "Stimulus"; } // FPS�\�� + std::string ClassName() { return "Stimulus"; } // FPS表示 public: - // �R���X�g���N�^ + // コンストラクタ Stimulus(ECTrainer* pEct); - // �f�X�g���N�^ + // デストラクタ ~Stimulus(); - // ������ + // 初期化 bool Init(); - // �h���f�[�^�ԍ����擾 + // 刺激データ番号を取得 int GetStimNo() { return _StimNo; } - // �h���t�@�C�������擾 + // 刺激ファイル名を取得 std::string GetStimFile() { return _StimInfoSet[_StimNo].filename; } - // �h���̎�ނ��擾 + // 刺激の種類を取得 bool IsStimMovie() { return (_StimInfoSet[_StimNo].type == 2); } - // �h���񎦂̌o�ߎ��Ԃ��擾 + // 刺激提示の経過時間を取得 double GetStimTime() { return _StimTimer.Elapse(); } - // �������Ԃ� + // 動画情報を返す std::wstring GetMovie() { return _Movie.Get(); } - // ������̍X�V��� + // 動画情報の更新状態 bool IsNewMovie() { return _Movie.IsNew(); } - // �\���摜��Ԃ� + // 表示画像を返す cv::Mat GetDisplay() { return _Display.Get(); } - // �\���摜�̍X�V��� + // 表示画像の更新状態 bool IsNewDisplay() { return _Display.IsNew(); } - // �^�[�Q�b�g�����擾 + // ターゲット情報を取得 std::vector GetMovieObject(float eTime = -1.f); - // ���v�������Ԃ��擾 + // 合計実験時間を取得 float GetTotalExpTime() { return _TotalExpTime; } }; diff --git a/ECTrainer2/TobiiREST.cpp b/ECTrainer2/TobiiREST.cpp index 523be25..0f08be1 100644 --- a/ECTrainer2/TobiiREST.cpp +++ b/ECTrainer2/TobiiREST.cpp @@ -1,27 +1,27 @@ -#include "ECTrainer.h" +#include "ECTrainer.h" #include "TobiiREST.h" #include "ECTrainerGUI.h" #include "Worker.h" #include "myWinUtils.h" -// �R���X�g���N�^ +// コンストラクタ TobiiREST::TobiiREST(ECTrainer* pEct) : BaseProcess(pEct) , _BatteryLevel(999) , _lastBatteryQuery(0) { } -// ������ +// 初期化 bool TobiiREST::Init() { try { #if defined(EYEDEVICE_GLASS2) - // Project ID�擾 + // Project ID取得 json::value json = REST_Handler::POST_Request(SERVER _T("/api/projects")).extract_json().get(); _ProjectID = json[_T("pr_id")].as_string(); mwut::DebugPrintf(_T("Tobii Project ID : %s\n"), _ProjectID.c_str()); - // Participant ID�擾 + // Participant ID取得 json::value postData; postData[L"pa_project"] = json::value::string(_ProjectID); json = REST_Handler::POST_Request(SERVER _T("/api/participants"), postData).extract_json().get(); @@ -33,17 +33,17 @@ } catch (const std::exception & e) { - UNREFERENCED_PARAMETER(e); // e.what() ���}���`�o�C�g������Ȃ̂Ŏg���Ȃ� + UNREFERENCED_PARAMETER(e); // e.what() がマルチバイト文字列なので使えない _pEct->PWorker()->EventLog(_T("Can't connect Tobii Device.")); _pEct->MsgBox(_T("Can't connect Tobii Device."), MB_ICONERROR); return false; } } -// ��{���� +// 基本処理 bool TobiiREST::Routine() { - // �o�b�e���[���擾 + // バッテリー情報取得 DWORD cTime = timeGetTime(); if (cTime - _lastBatteryQuery > BATTERY_QUERY_INTERVAL) { _lastBatteryQuery = cTime; @@ -55,10 +55,10 @@ return true; } -// �C�x���g���� +// イベント処理 bool TobiiREST::EventProc(MSG& msg) { switch (msg.message) { - case (int)ECTMSG::CALIB_START: // �L�����u���[�V���� + case (int)ECTMSG::CALIB_START: // キャリブレーション if (StartCalib()) { QueryCalibResult(); } else { @@ -69,12 +69,12 @@ return true; } -// �L�����u���[�V�����J�n +// キャリブレーション開始 bool TobiiREST::StartCalib() { try { #if defined(EYEDEVICE_GLASS2) - // Calibration ID�擾 + // Calibration ID取得 json::value postData; postData[L"ca_project"] = json::value::string(_ProjectID); postData[L"ca_type"] = json::value::string(L"default"); @@ -83,7 +83,7 @@ _CalibrationID = json[_T("ca_id")].as_string(); mwut::DebugPrintf(_T("Tobii Calibration ID : %s\n"), _CalibrationID.c_str()); - // Calibration�J�n + // Calibration開始 std::wstring url = SERVER _T("/api/calibrations/") + _CalibrationID + _T("/start"); json = REST_Handler::POST_Request(url.c_str()).extract_json().get(); mwut::DebugPrintf(_T("Calibration start\n")); @@ -92,14 +92,14 @@ } catch (const std::exception& e) { - UNREFERENCED_PARAMETER(e); // e.what() ���}���`�o�C�g������Ȃ̂Ŏg���Ȃ� + UNREFERENCED_PARAMETER(e); // e.what() がマルチバイト文字列なので使えない mwut::DebugPrintf(_T("Error in TobiiREST::StartCalib()\n")); return false; } } // GetCalibResult -// �߂�l -1:�G���[ 0:���s 1:���� +// 戻り値 -1:エラー 0:失敗 1:成功 bool TobiiREST::QueryCalibResult() { try { @@ -122,14 +122,14 @@ } catch (const std::exception & e) { - UNREFERENCED_PARAMETER(e); // e.what() ���}���`�o�C�g������Ȃ̂Ŏg���Ȃ� + UNREFERENCED_PARAMETER(e); // e.what() がマルチバイト文字列なので使えない ((BaseProcess*)_pEct->PWorker())->PostMsg(ECTMSG::CALIB_ERR); mwut::DebugPrintf(_T("Error in TobiiREST::QueryCalibResult()\n")); return false; } } -// �o�b�e���[�c�ʎ擾 +// バッテリー残量取得 bool TobiiREST::QueryBatteryLevel() { try { #if defined(EYEDEVICE_GLASS2) @@ -142,7 +142,7 @@ #endif return true; } catch (const std::exception & e) { - UNREFERENCED_PARAMETER(e); // e.what() ���}���`�o�C�g������Ȃ̂Ŏg���Ȃ� + UNREFERENCED_PARAMETER(e); // e.what() がマルチバイト文字列なので使えない mwut::DebugPrintf(_T("Error in TobiiREST::QueryBatteryLevel()\n")); return false; } diff --git a/ECTrainer2/TobiiREST.h b/ECTrainer2/TobiiREST.h index 863bfcf..2e5f942 100644 --- a/ECTrainer2/TobiiREST.h +++ b/ECTrainer2/TobiiREST.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "REST_Handler.h" #include "BaseProcess.h" @@ -12,25 +12,25 @@ utility::string_t _ProjectID; utility::string_t _ParticipantID; utility::string_t _CalibrationID; - int _BatteryLevel; // ���ڑ��� 999 - DWORD _lastBatteryQuery; // �O��̃o�b�e���[���擾���� + int _BatteryLevel; // 未接続時 999 + DWORD _lastBatteryQuery; // 前回のバッテリー情報取得時間 bool StartCalib(); bool QueryCalibResult(); bool QueryBatteryLevel(); - // ���b�Z�[�W���� + // メッセージ処理 virtual bool EventProc(MSG& msg); - // �ʏ폈�� + // 通常処理 bool Routine(); - //std::string ClassName() { return "TobiiREST"; } // FPS�\�� + //std::string ClassName() { return "TobiiREST"; } // FPS表示 public: - // �R���X�g���N�^ + // コンストラクタ TobiiREST(ECTrainer* pEct); - // ������ + // 初期化 bool Init(); - // �o�b�e���[�c�ʎ擾 + // バッテリー残量取得 int GetBatteryLevel() { return _BatteryLevel; }; }; diff --git a/ECTrainer2/Worker.cpp b/ECTrainer2/Worker.cpp index db75b10..fc213db 100644 --- a/ECTrainer2/Worker.cpp +++ b/ECTrainer2/Worker.cpp @@ -1,4 +1,4 @@ -#include "BaseProcess.h" +#include "BaseProcess.h" #include "Worker.h" #include "ECTrainer.h" #include "EyeTrack.h" @@ -8,7 +8,7 @@ #include "MovieObject.h" #include "myWinUtils.h" -// �R���X�g���N�^ +// コンストラクタ Worker::Worker(ECTrainer* pEct) : BaseProcess(pEct) , _AppStatus(APP_STATUS::BOOT) , _fpLogData(NULL) @@ -22,13 +22,13 @@ _pContactTimer = new mwut::HPTimer(); } -// �f�X�g���N�^ +// デストラクタ Worker::~Worker() { mwut::SafeDelete((void**)&_pExpTimer); mwut::SafeDelete((void**)&_pContactTimer); } -// ������ +// 初期化 bool Worker::Init() { _AppStatus = APP_STATUS::IDLE; @@ -36,10 +36,10 @@ return true; } -// ��{���� +// 基本処理 bool Worker::Routine() { - // �������X�V��҂� + // 視線情報更新を待つ if (!_pEct->PEyeTrack()->IsNewGazeV()) { Sleep(0); return false; @@ -48,16 +48,16 @@ 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); - // �\���摜�擾 + // 表示画像取得 if (_StimImage.empty() || _pEct->PStimulus()->IsNewDisplay()) { _StimImage = _pEct->PStimulus()->GetDisplay(); _FullScreenImage.Put(_StimImage); } - // �^�[�Q�b�g�摜���� + // ターゲット画像生成 int hit = -1; double dtMin = 0; int fb = 0; @@ -68,13 +68,13 @@ float scale = (float)stimImg.cols / _pEct->PMarker()->IMGSIZE.width; if (elems.size() > 0) { for (int e = 0; e < elems.size(); e++) { - // �^�[�Q�b�g�`�� + // ターゲット描画 auto target = cv::Point2f(elems[e].x, elems[e].y); if (elems[e].d > 0) { cv::circle(stimImg, target * scale, (int)(elems[e].d * scale), 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; @@ -84,7 +84,7 @@ } } if (gazeI.x >= 0) { - // �摜��̒����_�`�� + // 画像上の注視点描画 cv::circle(stimImg, gazeI * scale, (int)(20 * scale), CV_RGB(0, 0, 255), 3); if (hit >= 0) { @@ -93,7 +93,7 @@ if (_ContactTime >= (double)(FEEDBACK_TIME * _FBLevel)) { this->PostMsg((ECTMSG)((int)ECTMSG::FB_OK + _FBLevel - 1)); fb = _FBLevel++; - if (_FBLevel > 5) this->ResetParams(); // �ŏIFB��Ƀ��Z�b�g + if (_FBLevel > 5) this->ResetParams(); // 最終FB後にリセット } } } @@ -103,18 +103,18 @@ _TargetImage.Put(_StimImage); } - // ���O�o�� + // ログ出力 if (stimNo >= 0 && _fpLogData != NULL) { - _ftprintf(_fpLogData, _T("%.3f"), _pExpTimer->Elapse() / 1000.); // �o�ߎ��� - _ftprintf(_fpLogData, _T(",%d"), stimNo); // �h���f�[�^�ԍ� - _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"), _ContactTime / 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�� + _ftprintf(_fpLogData, _T("%.3f"), _pExpTimer->Elapse() / 1000.); // 経過時間 + _ftprintf(_fpLogData, _T(",%d"), stimNo); // 刺激データ番号 + _ftprintf(_fpLogData, _T(",%.3f"), _pEct->PStimulus()->GetStimTime() / 1000.); // 刺激提示の経過時間 + _ftprintf(_fpLogData, _T(",%.1f,%.1f"), gazeV.x, gazeV.y); // 注視点(視野カメラ座標) + _ftprintf(_fpLogData, _T(",%.1f,%.1f"), gazeI.x, gazeI.y); // 注視点(画像座標) + _ftprintf(_fpLogData, _T(",%d"), hit + 1); // ターゲット判定 + _ftprintf(_fpLogData, _T(",%.2f"), _ContactTime / 1000.); // 目標コンタクト時間 + _ftprintf(_fpLogData, _T(",%d"), fb); // フィードバック + _ftprintf(_fpLogData, _T(",%d"), _pEct->PBitalMonitor()->GetRR()); // バイタル出力(RR間隔) + // ホモグラフィ行列出力 cv::Mat h = _pEct->PMarker()->GetHomography(); if (!h.empty() && h.rows == 3 && h.cols == 3) { double* ptr = h.ptr(0); @@ -128,26 +128,26 @@ return true; } -// ����p�����[�^�����Z�b�g +// 判定パラメータをリセット void Worker::ResetParams() { _pContactTimer->Reset(); _FBLevel = 1; _ContactTime = 0; } -// �C�x���g���� +// イベント処理 bool Worker::EventProc(MSG& msg) { switch (msg.message) { - case (int)ECTMSG::SOFTWARE_START: // �\�t�g�E�F�A�N�� + case (int)ECTMSG::SOFTWARE_START: // ソフトウェア起動 break; - case (int)ECTMSG::SOFTWARE_END: // �\�t�g�E�F�A�I�� + case (int)ECTMSG::SOFTWARE_END: // ソフトウェア終了 this->EventLog(_T("Software End")); _pEct->StopApp(); break; - case (int)ECTMSG::CALIB_START: // �L�����u���[�V�����J�n + case (int)ECTMSG::CALIB_START: // キャリブレーション開始 if (_AppStatus == APP_STATUS::IDLE) { _AppStatus = APP_STATUS::CALIB; ((BaseProcess*)_pEct->PStimulus())->PostMsg(ECTMSG::CALIB_START); @@ -156,20 +156,20 @@ } break; - case (int)ECTMSG::CALIB_OK: // �L�����u���[�V�������� + case (int)ECTMSG::CALIB_OK: // キャリブレーション成功 _AppStatus = APP_STATUS::IDLE; ((BaseProcess*)_pEct->PStimulus())->PostMsg(ECTMSG::CALIB_OK); this->EventLog(_T("Calibration Success")); break; - case (int)ECTMSG::CALIB_FAILED: // �L�����u���[�V�������s - case (int)ECTMSG::CALIB_ERR: // �L�����u���[�V�����G���[ + case (int)ECTMSG::CALIB_FAILED: // キャリブレーション失敗 + case (int)ECTMSG::CALIB_ERR: // キャリブレーションエラー _AppStatus = APP_STATUS::IDLE; ((BaseProcess*)_pEct->PStimulus())->PostMsg(ECTMSG::CALIB_FAILED); this->EventLog(_T("Calibration Failed")); break; - case (int)ECTMSG::EXP_START: // �����J�n + case (int)ECTMSG::EXP_START: // 実験開始 if (_AppStatus == APP_STATUS::IDLE) { this->OpenDataLog(); this->EventLog(_T("Experiment Start")); @@ -180,7 +180,7 @@ } break; - case (int)ECTMSG::EXP_STOP: // ������~ + case (int)ECTMSG::EXP_STOP: // 実験停止 if (_AppStatus == APP_STATUS::STIM) { this->CloseDataLog(); _AppStatus = APP_STATUS::IDLE; @@ -189,7 +189,7 @@ } break; - case (int)ECTMSG::EXP_END: // �����I�� + case (int)ECTMSG::EXP_END: // 実験終了 if (_AppStatus == APP_STATUS::STIM) { this->CloseDataLog(); _AppStatus = APP_STATUS::IDLE; @@ -198,53 +198,53 @@ } break; - case (int)ECTMSG::EXP_NEXT: // ���̎h���Ɉړ� + case (int)ECTMSG::EXP_NEXT: // 次の刺激に移動 this->EventLog(_T("Next stimulation")); this->ResetParams(); break; - case (int)ECTMSG::SYSTEM_ERROR: // �V�X�e���G���[ + case (int)ECTMSG::SYSTEM_ERROR: // システムエラー this->EventLog(_T("System Error")); _AppStatus = APP_STATUS::IDLE; ((BaseProcess*)_pEct->PStimulus())->PostMsg(ECTMSG::SYSTEM_ERROR); ((BaseProcess*)_pEct->PECTrainerGUI())->PostMsg(ECTMSG::MOVIE_STOP); break; - case (int)ECTMSG::FB_OK: // �t�B�[�h�o�b�N�FOK + case (int)ECTMSG::FB_OK: // フィードバック:OK PlaySound(SOUND_OK, NULL, SND_FILENAME | SND_ASYNC); //this->EventLog(_T("Feedback OK")); break; - case (int)ECTMSG::FB_GOOD: // �t�B�[�h�o�b�N�FGood + case (int)ECTMSG::FB_GOOD: // フィードバック:Good PlaySound(SOUND_GOOD, NULL, SND_FILENAME | SND_ASYNC); //this->EventLog(_T("Feedback Good")); break; - case (int)ECTMSG::FB_NICE: // �t�B�[�h�o�b�N�FNice + case (int)ECTMSG::FB_NICE: // フィードバック:Nice PlaySound(SOUND_NICE, NULL, SND_FILENAME | SND_ASYNC); //this->EventLog(_T("Feedback Nice")); break; - case (int)ECTMSG::FB_GREAT: // �t�B�[�h�o�b�N�FGreat + case (int)ECTMSG::FB_GREAT: // フィードバック:Great PlaySound(SOUND_GREAT, NULL, SND_FILENAME | SND_ASYNC); //this->EventLog(_T("Feedback Great")); break; - case (int)ECTMSG::FB_EXCELLENT: // �t�B�[�h�o�b�N�FExcellent + case (int)ECTMSG::FB_EXCELLENT: // フィードバック:Excellent PlaySound(SOUND_EXCELLENT, NULL, SND_FILENAME | SND_ASYNC); //this->EventLog(_T("Feedback Excellent")); break; - case (int)ECTMSG::FB_GOOUT: // �t�B�[�h�o�b�N�F�����O�� + case (int)ECTMSG::FB_GOOUT: // フィードバック:視線外れ PlaySound(SOUND_GOOUT, NULL, SND_FILENAME | SND_ASYNC); break; } return true; } -// �f�[�^���O�t�@�C�����J�� +// データログファイルを開く void Worker::OpenDataLog() { - this->CloseDataLog(); // �O�̂��ߕ‚��� + this->CloseDataLog(); // 念のため閉じる auto filename = DATA_LOG_FILE + mwut::Multi2Wide(mwut::DateTimeStr()) + _T(".csv"); @@ -253,12 +253,12 @@ return; } - // �w�b�_�s + // ヘッダ行 _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")); } -// �f�[�^���O�t�@�C�����J�� +// データログファイルを開く void Worker::CloseDataLog() { if (_fpLogData) { fclose(_fpLogData); @@ -266,10 +266,10 @@ } } -// �C�x���g���O�o�� +// イベントログ出力 void Worker::EventLog(const TCHAR* msg) { - FILE* fp = NULL; // �C�x���g���O�t�@�C���|�C���^ + FILE* fp = NULL; // イベントログファイルポインタ if (_tfopen_s(&fp, EVENT_LOG_FILE, _T("a")) != 0) { _pEct->MsgBox(_T("Can't open event log file."), MB_ICONERROR); return; @@ -286,12 +286,12 @@ fclose(fp); } -// �R���^�N�g�ݐώ��Ԃ��擾 +// コンタクト累積時間を取得 double Worker::GetContactTime() { return _AppStatus == APP_STATUS::STIM ? _ContactTime : 0; } -// �����o�ߎ��Ԃ��擾�imsec�j +// 実験経過時間を取得(msec) double Worker::GetExpTime() { return _AppStatus == APP_STATUS::STIM ? _pExpTimer->Elapse() : 0; } diff --git a/ECTrainer2/Worker.h b/ECTrainer2/Worker.h index c9575f6..9ed4095 100644 --- a/ECTrainer2/Worker.h +++ b/ECTrainer2/Worker.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -15,10 +15,10 @@ class ECTrainer; enum class APP_STATUS; -// ���[�J�[�N���X -// �A�v���P�[�V�����̏�ԊǗ� -// �A�C�R���^�N�g���� -// ���O�o�� +// ワーカークラス +// アプリケーションの状態管理 +// アイコンタクト判定 +// ログ出力 class Worker : public BaseProcess { const TCHAR* SOUND_OK = _T("../voices/OK_S.wav"); @@ -29,52 +29,52 @@ const TCHAR* SOUND_GOOUT = _T("../voices/KbdKeyTap.wav"); const TCHAR* DATA_LOG_FILE = _T("LogData"); 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���^ - mwut::HPTimer* _pExpTimer; // �����o�߃^�C�}�[ - mwut::HPTimer* _pContactTimer; // �ڕW�R���^�N�g�^�C�}�[ - //mwut::HPTimer* _pNohitTimer; // �����O�ꎞ�� - double _ContactTime; // �R���^�N�g�ݐώ��� - RingBuffer _TargetImage; // �^�[�Q�b�g�摜 - cv::Mat _StimImage; // �h���摜 - RingBuffer _FullScreenImage; // �S��ʗp�摜 - int _FBLevel; // �t�B�[�h�o�b�N���x�� 1�`5 - //bool _IsInside; // �������^�[�Q�b�g�ɂ��邩 + const int FEEDBACK_TIME = 3000; // フィードバックの時間(1レベル)msec + //const int NOHIT_TIME = 100; // 視線が外れたと判定する時間 msec + APP_STATUS _AppStatus; // アプリケーション状態 + FILE* _fpLogData; // データログファイルポインタ + mwut::HPTimer* _pExpTimer; // 実験経過タイマー + mwut::HPTimer* _pContactTimer; // 目標コンタクトタイマー + //mwut::HPTimer* _pNohitTimer; // 視線外れ時間 + double _ContactTime; // コンタクト累積時間 + RingBuffer _TargetImage; // ターゲット画像 + cv::Mat _StimImage; // 刺激画像 + RingBuffer _FullScreenImage; // 全画面用画像 + int _FBLevel; // フィードバックレベル 1~5 + //bool _IsInside; // 視線がターゲットにあるか - // ��{���� + // 基本処理 bool Routine(); - // �C�x���g���� + // イベント処理 bool EventProc(MSG& msg); - // ����p�����[�^�����Z�b�g + // 判定パラメータをリセット void ResetParams(); - // �f�[�^���O�t�@�C�����J�� + // データログファイルを開く void OpenDataLog(); - // �f�[�^���O�t�@�C�����J�� + // データログファイルを開く void CloseDataLog(); - std::string ClassName() { return "Worker"; } // FPS�\�� + std::string ClassName() { return "Worker"; } // FPS表示 public: - // �R���X�g���N�^ + // コンストラクタ Worker(ECTrainer* pEct); - // �f�X�g���N�^ + // デストラクタ ~Worker(); - // ������ + // 初期化 bool Init(); - // �A�v���P�[�V������Ԃ̎擾 + // アプリケーション状態の取得 APP_STATUS GetAppStatus() { return _AppStatus; } - // �^�[�Q�b�g�摜�擾 + // ターゲット画像取得 cv::Mat GetTargetImg() { return _TargetImage.Get(); } - // �S��ʉ摜�̍X�V��� + // 全画面画像の更新状態 bool IsNewFullScreenImg() { return _FullScreenImage.IsNew(); } - // �S��ʉ摜�擾 + // 全画面画像取得 cv::Mat GetFullScreenImg() { return _FullScreenImage.Get(); } - // �C�x���g���O�o�� + // イベントログ出力 void EventLog(const TCHAR* msg); - // �R���^�N�g�ݐώ��Ԃ��擾 + // コンタクト累積時間を取得 double GetContactTime(); - // �����o�ߎ��Ԃ��擾�imsec�j + // 実験経過時間を取得(msec) double GetExpTime(); }; diff --git a/ECTrainer2/cvui.h b/ECTrainer2/cvui.h index d4e47e7..55df78b 100644 --- a/ECTrainer2/cvui.h +++ b/ECTrainer2/cvui.h @@ -1,4 +1,4 @@ -/* +/* A (very) simple UI lib built on top of OpenCV drawing primitives. Version: 2.7.0 diff --git a/ECTrainer2/main.cpp b/ECTrainer2/main.cpp index 7b5f796..5064584 100644 --- a/ECTrainer2/main.cpp +++ b/ECTrainer2/main.cpp @@ -1,4 +1,4 @@ - + #include #include #include "ECTrainer.h" diff --git a/ECTrainer2/myWinUtils.cpp b/ECTrainer2/myWinUtils.cpp index 0bd6218..b75299d 100644 --- a/ECTrainer2/myWinUtils.cpp +++ b/ECTrainer2/myWinUtils.cpp @@ -1,4 +1,4 @@ -#include "MyWinUtils.h" +#include "MyWinUtils.h" #include #include @@ -7,7 +7,7 @@ namespace mwut { - // �}���`�o�C�g����������C�h������iUNICODE�j�ɕϊ� + // マルチバイト文字列をワイド文字列(UNICODE)に変換 std::wstring Multi2Wide(std::string const& src) { auto const dest_size = ::MultiByteToWideChar(CP_ACP, 0U, src.data(), -1, nullptr, 0U); std::vector dest(dest_size, L'\0'); @@ -19,7 +19,7 @@ return std::wstring(dest.begin(), dest.end()); } - // �����t���f�o�b�O�o�� + // 書式付きデバッグ出力 int DebugPrintf(LPCTSTR format, ...) { va_list args; va_start(args, format); @@ -34,43 +34,43 @@ return len; } - // �e�[�u����ǂݍ��� + // テーブルを読み込み bool ReadTable(const std::string& filename, STR_TABLE& table, const char delimiter) { - // �t�@�C�����J�� + // ファイルを開く std::fstream filestream(filename); - if (!filestream.is_open()) return false; // �t�@�C�����J���Ȃ������ꍇ�͏I�� + if (!filestream.is_open()) return false; // ファイルが開けなかった場合は終了 - // �t�@�C����ǂݍ��� + // ファイルを読み込む while (!filestream.eof()) { - // �P�s�ǂݍ��� + // 1行読み込む std::string buffer; filestream >> buffer; - // �t�@�C������ǂݍ��񂾂P�s�̕��������؂蕶���ŕ����ă��X�g�ɒlj����� - std::vector record; // �P�s���̕�����̃��X�g - std::istringstream streambuffer(buffer); // ������X�g���[�� - std::string token; // �P�Z�����̕����� + // ファイルから読み込んだ1行の文字列を区切り文字で分けてリストに追加する + std::vector record; // 1行分の文字列のリスト + std::istringstream streambuffer(buffer); // 文字列ストリーム + std::string token; // 1セル分の文字列 while (std::getline(streambuffer, token, delimiter)) { - // �P�Z�����̕���������X�g�ɒlj����� + // 1セル分の文字列をリストに追加する record.push_back(token); } - // �P�s���̕�������o�͈����̃��X�g�ɒlj����� + // 1行分の文字列を出力引数のリストに追加する table.push_back(record); } return true; } - // �}���`�f�B�X�v���C�̏����擾 - // �v�f0�F���C���E�C���h�E + // マルチディスプレイの情報を取得 + // 要素0:メインウインドウ std::vector GetDisplayInfo() { - // �f�B�X�v���C���擾 + // ディスプレイ情報取得 std::vector displays; EnumDisplayMonitors(NULL, NULL, (MONITORENUMPROC)MonitorEnumProc, (LPARAM)&displays); - // ���C�����j�^��擪�v�f�Ɉړ� + // メインモニタを先頭要素に移動 int mainMonitor = 0; for (int i = 0; i < displays.size(); i++) { if (displays[i].left == 0 && displays[i].top == 0) mainMonitor = i; @@ -93,7 +93,7 @@ return displays; } - // �f�B�X�v���C���擾�R�[���o�b�N + // ディスプレイ情報取得コールバック BOOL CALLBACK MonitorEnumProc( HMONITOR hMon, HDC hdcMon, LPRECT lpMon, LPARAM dwData) { @@ -102,7 +102,7 @@ return TRUE; } - // ���S�ȃf���[�g + // 安全なデリート void SafeDelete(void** ptr) { if (*ptr) { delete* ptr; @@ -110,7 +110,7 @@ } } - // ���t����������擾 (C++20�ɂȂ����� std::format �g�������j + // 日付時刻文字列取得 (C++20になったら std::format 使いたい) std::string DateTimeStr() { SYSTEMTIME st; ::GetLocalTime(&st); @@ -122,16 +122,16 @@ return str; } - // �����x�^�C�}�[�N���X + // 高精度タイマークラス - // �R���X�g���N�^ + // コンストラクタ HPTimer::HPTimer() { QueryPerformanceFrequency(&_nFreq); QueryPerformanceCounter(&_nBegin); _nLast = _nBegin; } - // �o�ߎ��ԎZ�o + // 経過時間算出 double HPTimer::Calc(LARGE_INTEGER before) { LARGE_INTEGER cur; QueryPerformanceCounter(&cur); @@ -140,22 +140,22 @@ return elapse; } - // �J�n������̌o�ߎ���(ms) + // 開始時からの経過時間(ms) double HPTimer::Elapse() { return this->Calc(_nBegin); } - // �O�񂩂�̌o�ߎ���(ms) + // 前回からの経過時間(ms) double HPTimer::Interval() { return this->Calc(_nLast); } - // �J�n���ԃ��Z�b�g + // 開始時間リセット void HPTimer::Reset() { QueryPerformanceCounter(&_nBegin); } - // �����xSleep + // 高精度Sleep void HPTimer::HPSleep(double delayms) { HPTimer timer; while (1) {