diff --git a/ECTrainer1/ECTrainer1.cpp b/ECTrainer1/ECTrainer1.cpp new file mode 100644 index 0000000..c7c824e --- /dev/null +++ b/ECTrainer1/ECTrainer1.cpp @@ -0,0 +1,104 @@ + +// ECTrainer1.cpp : アプリケーションのクラス動作を定義します。 +// + +#include "pch.h" +#include "framework.h" +#include "ECTrainer1.h" +#include "ECTrainer1Dlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CECTrainer1App + +BEGIN_MESSAGE_MAP(CECTrainer1App, CWinApp) + ON_COMMAND(ID_HELP, &CWinApp::OnHelp) +END_MESSAGE_MAP() + + +// CECTrainer1App の構築 + +CECTrainer1App::CECTrainer1App() +{ + // TODO: この位置に構築用コードを追加してください。 + // ここに InitInstance 中の重要な初期化処理をすべて記述してください。 +} + + +// 唯一の CECTrainer1App オブジェクト + +CECTrainer1App theApp; + + +// CECTrainer1App の初期化 + +BOOL CECTrainer1App::InitInstance() +{ + // アプリケーション マニフェストが visual スタイルを有効にするために、 + // ComCtl32.dll Version 6 以降の使用を指定する場合は、 + // Windows XP に InitCommonControlsEx() が必要です。さもなければ、ウィンドウ作成はすべて失敗します。 + INITCOMMONCONTROLSEX InitCtrls; + InitCtrls.dwSize = sizeof(InitCtrls); + // アプリケーションで使用するすべてのコモン コントロール クラスを含めるには、 + // これを設定します。 + InitCtrls.dwICC = ICC_WIN95_CLASSES; + InitCommonControlsEx(&InitCtrls); + + CWinApp::InitInstance(); + + + AfxEnableControlContainer(); + + // ダイアログにシェル ツリー ビューまたはシェル リスト ビュー コントロールが + // 含まれている場合にシェル マネージャーを作成します。 + CShellManager *pShellManager = new CShellManager; + + // MFC コントロールでテーマを有効にするために、"Windows ネイティブ" のビジュアル マネージャーをアクティブ化 + CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows)); + + // 標準初期化 + // これらの機能を使わずに最終的な実行可能ファイルの + // サイズを縮小したい場合は、以下から不要な初期化 + // ルーチンを削除してください。 + // 設定が格納されているレジストリ キーを変更します。 + // TODO: 会社名または組織名などの適切な文字列に + // この文字列を変更してください。 + SetRegistryKey(_T("アプリケーション ウィザードで生成されたローカル アプリケーション")); + + CECTrainer1Dlg dlg; + m_pMainWnd = &dlg; + INT_PTR nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: ダイアログが で消された時のコードを + // 記述してください。 + } + else if (nResponse == IDCANCEL) + { + // TODO: ダイアログが <キャンセル> で消された時のコードを + // 記述してください。 + } + else if (nResponse == -1) + { + TRACE(traceAppMsg, 0, "警告: ダイアログの作成に失敗しました。アプリケーションは予期せずに終了します。\n"); + TRACE(traceAppMsg, 0, "警告: ダイアログで MFC コントロールを使用している場合、#define _AFX_NO_MFC_CONTROLS_IN_DIALOGS を指定できません。\n"); + } + + // 上で作成されたシェル マネージャーを削除します。 + if (pShellManager != nullptr) + { + delete pShellManager; + } + +#if !defined(_AFXDLL) && !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS) + ControlBarCleanUp(); +#endif + + // ダイアログは閉じられました。アプリケーションのメッセージ ポンプを開始しないで + // アプリケーションを終了するために FALSE を返してください。 + return FALSE; +} + diff --git a/ECTrainer1/ECTrainer1.h b/ECTrainer1/ECTrainer1.h new file mode 100644 index 0000000..b65652a --- /dev/null +++ b/ECTrainer1/ECTrainer1.h @@ -0,0 +1,32 @@ + +// ECTrainer1.h : PROJECT_NAME アプリケーションのメイン ヘッダー ファイルです +// + +#pragma once + +#ifndef __AFXWIN_H__ + #error "PCH に対してこのファイルをインクルードする前に 'pch.h' をインクルードしてください" +#endif + +#include "resource.h" // メイン シンボル + + +// CECTrainer1App: +// このクラスの実装については、ECTrainer1.cpp を参照してください +// + +class CECTrainer1App : public CWinApp +{ +public: + CECTrainer1App(); + +// オーバーライド +public: + virtual BOOL InitInstance(); + +// 実装 + + DECLARE_MESSAGE_MAP() +}; + +extern CECTrainer1App theApp; diff --git a/ECTrainer1/ECTrainer1.rc b/ECTrainer1/ECTrainer1.rc new file mode 100644 index 0000000..182b8d8 --- /dev/null +++ b/ECTrainer1/ECTrainer1.rc Binary files differ diff --git a/ECTrainer1/ECTrainer1.vcxproj b/ECTrainer1/ECTrainer1.vcxproj new file mode 100644 index 0000000..1e66a28 --- /dev/null +++ b/ECTrainer1/ECTrainer1.vcxproj @@ -0,0 +1,224 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {E2EC3843-4077-4DC8-96F7-37C1BA5094FD} + MFCProj + ECTrainer1 + 10.0 + + + + Application + true + v142 + Unicode + Static + + + Application + false + v142 + true + Unicode + Static + + + Application + true + v142 + Unicode + Static + + + Application + false + v142 + true + Unicode + Static + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + true + _WINDOWS;_DEBUG;%(PreprocessorDefinitions) + pch.h + + + Windows + + + false + true + _DEBUG;%(PreprocessorDefinitions) + + + 0x0411 + _DEBUG;%(PreprocessorDefinitions) + $(IntDir);%(AdditionalIncludeDirectories) + + + + + Use + Level3 + Disabled + true + WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) + pch.h + + + Windows + + + false + true + _DEBUG;%(PreprocessorDefinitions) + + + 0x0411 + _DEBUG;%(PreprocessorDefinitions) + $(IntDir);%(AdditionalIncludeDirectories) + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) + pch.h + + + Windows + true + true + + + false + true + NDEBUG;%(PreprocessorDefinitions) + + + 0x0411 + NDEBUG;%(PreprocessorDefinitions) + $(IntDir);%(AdditionalIncludeDirectories) + + + + + Use + Level3 + MaxSpeed + true + true + true + _WINDOWS;NDEBUG;%(PreprocessorDefinitions) + pch.h + + + Windows + true + true + + + false + true + NDEBUG;%(PreprocessorDefinitions) + + + 0x0411 + NDEBUG;%(PreprocessorDefinitions) + $(IntDir);%(AdditionalIncludeDirectories) + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ECTrainer1/ECTrainer1.vcxproj.filters b/ECTrainer1/ECTrainer1.vcxproj.filters new file mode 100644 index 0000000..eff4ee2 --- /dev/null +++ b/ECTrainer1/ECTrainer1.vcxproj.filters @@ -0,0 +1,66 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + ヘッダー ファイル + + + ヘッダー ファイル + + + ヘッダー ファイル + + + ヘッダー ファイル + + + ヘッダー ファイル + + + ヘッダー ファイル + + + ヘッダー ファイル + + + + + ソース ファイル + + + ソース ファイル + + + ソース ファイル + + + + + リソース ファイル + + + + + リソース ファイル + + + + + リソース ファイル + + + \ No newline at end of file diff --git a/ECTrainer1/ECTrainer1Dlg.cpp b/ECTrainer1/ECTrainer1Dlg.cpp new file mode 100644 index 0000000..ffd5450 --- /dev/null +++ b/ECTrainer1/ECTrainer1Dlg.cpp @@ -0,0 +1,481 @@ + +// ECTrainer1Dlg.cpp : 実装ファイル +// + +#include "pch.h" +#include "framework.h" +#include "ECTrainer1.h" +#include "ECTrainer1Dlg.h" +#include "afxdialogex.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// アプリケーションのバージョン情報に使われる CAboutDlg ダイアログ + +class CAboutDlg : public CDialogEx +{ +public: + CAboutDlg(); + +// ダイアログ データ +#ifdef AFX_DESIGN_TIME + enum { IDD = IDD_ABOUTBOX }; +#endif + + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV サポート + +// 実装 +protected: + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnBnClickedButton1(); +}; + +CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX) +{ +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) +END_MESSAGE_MAP() + + +// CECTrainer1Dlg ダイアログ + +// コンストラクタ +CECTrainer1Dlg::CECTrainer1Dlg(CWnd* pParent /*=nullptr*/) + : CDialogEx(IDD_ECTRAINER1_DIALOG, pParent) + , _bRunning(false) + , _pCameraThread(NULL) +{ + _hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +// DDX処理 +void CECTrainer1Dlg::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); +} + +// メッセージマップ +BEGIN_MESSAGE_MAP(CECTrainer1Dlg, CDialogEx) + ON_WM_SYSCOMMAND() + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + ON_WM_CLOSE() +END_MESSAGE_MAP() + + +// CECTrainer1Dlg メッセージ ハンドラー + +// ダイアログ初期化 +BOOL CECTrainer1Dlg::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + + // "バージョン情報..." メニューをシステム メニューに追加します。 + + // IDM_ABOUTBOX は、システム コマンドの範囲内になければなりません。 + ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); + ASSERT(IDM_ABOUTBOX < 0xF000); + + CMenu* pSysMenu = GetSystemMenu(FALSE); + if (pSysMenu != nullptr) + { + BOOL bNameValid; + CString strAboutMenu; + bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); + ASSERT(bNameValid); + if (!strAboutMenu.IsEmpty()) + { + pSysMenu->AppendMenu(MF_SEPARATOR); + pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); + } + } + + // このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、 + // Framework は、この設定を自動的に行います。 + SetIcon(_hIcon, TRUE); // 大きいアイコンの設定 + SetIcon(_hIcon, FALSE); // 小さいアイコンの設定 + + // ワーカースレッド起動 + _bRunning = true; + StartImageThreads(); + StartDataThreads(); + + return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を返します。 +} + +// システムコマンド +void CECTrainer1Dlg::OnSysCommand(UINT nID, LPARAM lParam) +{ + if ((nID & 0xFFF0) == IDM_ABOUTBOX) + { + CAboutDlg dlgAbout; + dlgAbout.DoModal(); + } + else + { + CDialogEx::OnSysCommand(nID, lParam); + } +} + +// 描画イベント +void CECTrainer1Dlg::OnPaint() +{ + if (IsIconic()) + { + // ダイアログに最小化時のアイコンを描画 + CPaintDC dc(this); // 描画のデバイス コンテキスト + SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); + // クライアントの四角形領域内の中央 + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + // アイコンの描画 + dc.DrawIcon(x, y, _hIcon); + } + else + { + CDialogEx::OnPaint(); + } +} + +// 最小化ウィンドウドラッグ時のカーソル取得関数 +HCURSOR CECTrainer1Dlg::OnQueryDragIcon() +{ + return static_cast(_hIcon); +} + +// Mat画像をピクチャボックスに表示 +void CECTrainer1Dlg::ShowImage(int id, Mat& img) +{ + CDC* dc = GetDlgItem(id)->GetDC(); + HDC dstDC = dc->GetSafeHdc(); + + CRect rc; + GetDlgItem(id)->GetClientRect(&rc); + cv::Size size(rc.Width() & ~0x03, rc.Height() & ~0x03); + resize(img, img, size); + + BITMAPINFO info = {}; + info.bmiHeader.biBitCount = 24; + info.bmiHeader.biWidth = size.width; + info.bmiHeader.biHeight = -size.height; + info.bmiHeader.biPlanes = 1; + info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + info.bmiHeader.biCompression = BI_RGB; + + StretchDIBits(dstDC, 0, 0, size.width, size.height, + 0, 0, size.width, size.height, + img.data, &info, DIB_RGB_COLORS, SRCCOPY); + + ReleaseDC(dc); +} + +// 閉じる時のイベント +void CECTrainer1Dlg::OnClose() +{ + //if (IDOK == MessageBox(_T("本当に終了しますか?"), _T("確認"), MB_OKCANCEL)) { + // + //} + _bRunning = false; + HANDLE handles[] = { _pCameraThread->m_hThread, _pImageThread->m_hThread, _pTargetThread->m_hThread, + _pKeepAliveThread->m_hThread, _pDataThread->m_hThread }; + WaitForMultipleObjects(sizeof(handles)/sizeof(HANDLE), handles, TRUE, 2000); + + CDialogEx::OnClose(); +} + +// カメラスレッド開始 +bool CECTrainer1Dlg::StartImageThreads() +{ + // カメラスレッド生成 + _pCameraThread = AfxBeginThread(CallCameraThreadProc, + (LPVOID)this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL); + if (!_pCameraThread) return false; + _pCameraThread->m_pMainWnd = this; // メインウィンドウに自分自身を設定 + _pCameraThread->m_bAutoDelete = TRUE; // スレッド終了時にオブジェクトを自動的に破棄 + _pCameraThread->ResumeThread(); // スレッドを開始 + + // 画像処理スレッド生成 + _pImageThread = AfxBeginThread(CallImageThreadProc, + (LPVOID)this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL); + if (!_pImageThread) return false; + _pImageThread->m_pMainWnd = this; // メインウィンドウに自分自身を設定 + _pImageThread->m_bAutoDelete = TRUE; // スレッド終了時にオブジェクトを自動的に破棄 + _pImageThread->ResumeThread(); // スレッドを開始 + + // 画像処理スレッド生成 + _pTargetThread = AfxBeginThread(CallTargetThreadProc, + (LPVOID)this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL); + if (!_pTargetThread) return false; + _pTargetThread->m_pMainWnd = this; // メインウィンドウに自分自身を設定 + _pTargetThread->m_bAutoDelete = TRUE; // スレッド終了時にオブジェクトを自動的に破棄 + _pTargetThread->ResumeThread(); // スレッドを開始 + + return true; +} + +// カメラスレッドを呼び出す static関数 +UINT CECTrainer1Dlg::CallCameraThreadProc(LPVOID pParam) +{ + CECTrainer1Dlg* pDlg = dynamic_cast(reinterpret_cast(pParam)); + if (pDlg) pDlg->CameraThreadProc(); + return 0; +} + +// 画像処理スレッドを呼び出す static関数 +UINT CECTrainer1Dlg::CallImageThreadProc(LPVOID pParam) { + CECTrainer1Dlg* pDlg = dynamic_cast(reinterpret_cast(pParam)); + if (pDlg) pDlg->ImageThreadProc(); + return 0; +} + +// 刺激スレッドを呼び出す static関数 +UINT CECTrainer1Dlg::CallTargetThreadProc(LPVOID pParam) { + CECTrainer1Dlg* pDlg = dynamic_cast(reinterpret_cast(pParam)); + if (pDlg) pDlg->TargetThreadProc(); + return 0; +} + +// カメラスレッド本体 +void CECTrainer1Dlg::CameraThreadProc() +{ + TRACE(_T("CameraThreadProc start\n")); + + VideoCapture cam("rtsp://" ADDR ":8554/live/scene"); + if (!cam.isOpened()) { + MessageBox(_T("cannot open camera " ADDR)); + return; + } + + _write = 0, _read = 0; + do { + cam >> _frames[_write]; + _read = _write; + _write = (++_write) % FRAMES; + } while (_bRunning); + + TRACE(_T("CameraThreadProc end\n")); +} + +// 画像処理スレッド本体 +void CECTrainer1Dlg::ImageThreadProc() { + TRACE(_T("ImageThreadProc start\n")); + + //const cv::aruco::PREDEFINED_DICTIONARY_NAME dictionary_name = cv::aruco::DICT_4X4_50; + cv::Ptr dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_4X4_50); + Point2f cornerPosW[] = { {5, 155}, {215, 155}, {5, 5}, {215, 5}, {5, 60}, + {5, 105}, {215, 60}, {215, 105}, {54, 5}, {54, 60} }; + + int lastRead = 0; + do { + while (_read == lastRead && _bRunning); + Mat img = _frames[_read].clone(); + + Point2f gpC = Point2f(_gpC.x * img.cols, _gpC.y * img.rows); + + // マーカーの検出 + std::vector mids; + std::vector> corners; + cv::Ptr parameters = cv::aruco::DetectorParameters::create(); + cv::aruco::detectMarkers(img, dictionary, corners, mids, parameters); + cv::aruco::drawDetectedMarkers(img, corners, mids); + + std::vector cornerW, cornerC; + for (int i = 0; i < corners.size(); i++) { + cornerC.push_back(corners[i][0]); + cornerW.push_back(cornerPosW[mids[i] - 1]); + + //circle(img, corners[i][0], 10, CV_RGB(255, 0, 0), 2); + //char msg[256]; + //sprintf_s(msg, 256, "%d", mids[i]); + ////putText(img, cv::format("%d", mids[i]), corners[i][0], FONT_HERSHEY_COMPLEX, 1.0, CV_RGB(255, 0, 0)); + //putText(img, msg, corners[i][0], FONT_HERSHEY_COMPLEX, 1.0, CV_RGB(255, 0, 0)); + } + if (cornerC.size() >= 4) { + Mat h = findHomography(cornerC, cornerW); + if (!h.empty()) { + putText(img, "H", Point(5, 20), FONT_HERSHEY_COMPLEX, 1.0, CV_RGB(255, 0, 0), 1); + + if (_gpC.x > 0 && _gpC.y > 0) { + Mat gpCe = (cv::Mat_(3, 1) << gpC.x, gpC.y, 1); + Mat gpWe = h * gpCe; + double* pgpWe = gpWe.ptr(0); + _gpW = Point2f((float)(*pgpWe / *(pgpWe + 2)), (float)(*(pgpWe + 1) / *(pgpWe + 2))); + + //TRACE("gpC %d,%d gpWe %.1f,%.1f,%.1f gpW %.1f,%.1f \n", + // (int)gpC.x, (int)gpC.y, *pgpWe, *(pgpWe + 1), *(pgpWe + 2), + // *pgpWe / *(pgpWe + 2), *(pgpWe + 1) / *(pgpWe + 2)); + } + } + } + + if (_gpC.x > 0 && _gpC.y > 0) { + circle(img, gpC, 10, CV_RGB(255, 0, 0), 2); + } + + ShowImage(IDC_IMAGE, img); + } while (_bRunning); + + TRACE(_T("ImageThreadProc end\n")); +} + +// 刺激スレッド本体 +void CECTrainer1Dlg::TargetThreadProc() { + TRACE(_T("TargetThreadProc start\n")); + + Size targetW = Size(240, 180); + Mat target = imread("manL1.png"); + namedWindow("target", WINDOW_NORMAL); + + do { + Mat tdisp = target.clone(); + + if (_gpW.x > 0 && _gpW.x < targetW.width && _gpW.y > 0 && _gpW.y < targetW.height) { + Point2f gpW = Point2f(_gpW.x * target.size().width / targetW.width, _gpW.y * target.size().height / targetW.height); + circle(tdisp, gpW, 10, CV_RGB(0, 0, 255), 2); + } + + imshow("target", tdisp); + waitKey(1); + } while (_bRunning); + + TRACE(_T("TargetThreadProc end\n")); +} + +// データスレッド開始 +bool CECTrainer1Dlg::StartDataThreads() +{ + //Initialize winsock + WSADATA wsa; + if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) + { + TRACE("Initialising Winsock Failed with error Code : %d\n", WSAGetLastError()); + return false; + } + if ((_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR) + { + TRACE("Creating socket failed with error code : %d", WSAGetLastError()); + return false; + } + + //setup address structure + memset((char*)&_socketAddr, 0, sizeof(_socketAddr)); + _socketAddr.sin_family = AF_INET; + _socketAddr.sin_port = htons(PORT); + InetPton(_socketAddr.sin_family, _T(ADDR), &_socketAddr.sin_addr.S_un.S_addr); + + // Keep Alive スレッド生成 + _pKeepAliveThread = AfxBeginThread(CallKeepAliveThreadProc, + (LPVOID)this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL); + if (!_pKeepAliveThread) return false; + _pKeepAliveThread->m_pMainWnd = this; // メインウィンドウに自分自身を設定 + _pKeepAliveThread->m_bAutoDelete = TRUE; // スレッド終了時にオブジェクトを自動的に破棄 + _pKeepAliveThread->ResumeThread(); // スレッドを開始 + + // データスレッド生成 + _pDataThread = AfxBeginThread(CallDataThreadProc, + (LPVOID)this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL); + if (!_pDataThread) return false; + _pDataThread->m_pMainWnd = this; // メインウィンドウに自分自身を設定 + _pDataThread->m_bAutoDelete = TRUE; // スレッド終了時にオブジェクトを自動的に破棄 + _pDataThread->ResumeThread(); // スレッドを開始 + + return true; +} + +// Keep Aliveスレッドを呼び出す static関数 +UINT CECTrainer1Dlg::CallKeepAliveThreadProc(LPVOID pParam) +{ + CECTrainer1Dlg* pDlg = dynamic_cast(reinterpret_cast(pParam)); + if (pDlg) pDlg->KeepAliveThreadProc(); + return 0; +} + +// データスレッドを呼び出す static関数 +UINT CECTrainer1Dlg::CallDataThreadProc(LPVOID pParam) +{ + CECTrainer1Dlg* pDlg = dynamic_cast(reinterpret_cast(pParam)); + if (pDlg) pDlg->DataThreadProc(); + return 0; +} + +// Keep Aliveスレッド本体 +void CECTrainer1Dlg::KeepAliveThreadProc() +{ + TRACE(_T("KeepAliveThreadProc start\n")); + + const int KEEP_ALIVE_WAIT_COUNT = 20; // x 100ms + int slen = sizeof(_socketAddr); + char message[BUFLEN]; + strcpy_s(message, BUFLEN, KA_DATA_MSG.c_str()); + + do { + //TRACE(_T("Keep Alive Data Sent \n")); + if (sendto(_socket, message, (int)strlen(message), 0, (struct sockaddr*) & _socketAddr, slen) == SOCKET_ERROR) + { + TRACE(_T("Keep Alive Data Sent Error\n")); + } + for (int i = 0; i < KEEP_ALIVE_WAIT_COUNT && _bRunning; i ++) Sleep(100); + } while (_bRunning); + + closesocket(_socket); + WSACleanup(); + + TRACE(_T("KeepAliveThreadProc end\n")); +} + +// データスレッド本体 +void CECTrainer1Dlg::DataThreadProc() +{ + TRACE(_T("DataThreadProc start\n")); + + int slen = sizeof(_socketAddr); + char buf[BUFLEN]; + int lastGidx = 0; + Point2f gp; + + Sleep(500); // 最初のKeepAlive送信待ち + + do { + memset(buf, '\0', BUFLEN); + if (recvfrom(_socket, buf, BUFLEN, 0, + (struct sockaddr*) & _socketAddr, &slen) == SOCKET_ERROR) + { + TRACE(_T("Data Receive Error\n")); + Sleep(10); + continue; + } + //TRACE("%s\n", buf); + + GazeData gd(buf); + if (gd.gidx > lastGidx) { + _gpC = gp; + gp = Point(0, 0); + lastGidx = gd.gidx; + } + if (gd.isGP && gd.s == 0) { + gp = gd.gp; + //_gp = gp; + //TRACE("%d, %f, %f\n", gd.gidx, gd.gpx, gd.gpy); + } + } while (_bRunning); + + closesocket(_socket); + WSACleanup(); + + TRACE(_T("DataThreadProc end\n")); +} diff --git a/ECTrainer1/ECTrainer1Dlg.h b/ECTrainer1/ECTrainer1Dlg.h new file mode 100644 index 0000000..d8bfc39 --- /dev/null +++ b/ECTrainer1/ECTrainer1Dlg.h @@ -0,0 +1,131 @@ + +// ECTrainer1Dlg.h : ヘッダー ファイル +// + +#pragma once + +#include +#include +#include "myOpenCV.h" + +//#define ADDR "192.168.71.50" +#define ADDR "192.168.23.158" + +const std::string KA_DATA_MSG = "{\"type\": \"live.data.unicast\", \"key\": \"some_GUID\", \"op\": \"start\"}"; + +// CECTrainer1Dlg ダイアログ +class CECTrainer1Dlg : public CDialogEx +{ +// コンストラクション +public: + CECTrainer1Dlg(CWnd* pParent = nullptr); // 標準コンストラクター + +// ダイアログ データ +#ifdef AFX_DESIGN_TIME + enum { IDD = IDD_ECTRAINER1_DIALOG }; +#endif + +// 実装 +protected: + static const int PORT = 49152; //The port on which to listen for incoming data + static const int BUFLEN = 512; //Max length of buffer + static const int FRAMES = 2; + + HICON _hIcon; + bool _bRunning; + CWinThread* _pCameraThread; + CWinThread* _pImageThread; + CWinThread* _pTargetThread; + CWinThread* _pKeepAliveThread; + CWinThread* _pDataThread; + SOCKET _socket; + struct sockaddr_in _socketAddr; + Point2f _gpC; + Point2f _gpW; + Mat _frames[FRAMES]; + int _write, _read; + + // 生成された、メッセージ割り当て関数 + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV サポート + virtual BOOL OnInitDialog(); + afx_msg void OnSysCommand(UINT nID, LPARAM lParam); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + DECLARE_MESSAGE_MAP() + void ShowImage(int id, Mat &img); + bool StartImageThreads(); + bool StartDataThreads(); +public: + static UINT CallCameraThreadProc(LPVOID pParam); + static UINT CallImageThreadProc(LPVOID pParam); + static UINT CallTargetThreadProc(LPVOID pParam); + static UINT CallKeepAliveThreadProc(LPVOID pParam); + static UINT CallDataThreadProc(LPVOID pParam); + void CameraThreadProc(); + void ImageThreadProc(); + void TargetThreadProc(); + void KeepAliveThreadProc(); + void DataThreadProc(); + afx_msg void OnClose(); +}; + +// +struct GazeData { + long ts = 0; + int s = 0; + int gidx = 0; + int l = 0; + Point2f gp; + Point3f gdr; + Point3f gdl; + bool isGP = false; + bool isGDR = false; + bool isGDL = false; + + GazeData(char* str) { + char* pts = strstr(str, "\"ts\""); + if (pts) ts = atol(pts + 5); + else pts = str; + + char* ps = strstr(pts + 5, "\"s\""); + if (ps) s = atoi(ps + 4); + else ps = str; + + char* pgidx = strstr(ps + 4, "\"gidx\""); + if (pgidx) gidx = atoi(pgidx + 7); + else pgidx = str; + + char* pl = strstr(pgidx + 7, "\"l\""); + if (pl) { + l = atoi(pl + 4); + + char* pgp = strstr(pl + 4, "\"gp\""); + if (pgp) { + isGP = true; + gp.x = (float)atof(pgp + 6); + pgp = strchr(pgp + 6, ','); + if (pgp) gp.y = (float)atof(pgp + 1); + } + } + + char* pgd = strstr(pgidx, "\"gd\""); + if (pgd) { + if (strstr(pgd, "right") != NULL) { + isGDR = true; + gdr.x = (float)atof(pgd + 6); + pgd = strchr(pgd + 6, ','); + if (pgd) gdr.y = (float)atof(pgd + 1); + else pgd = pgidx; + pgd = strchr(pgd + 1, ','); + if (pgd) gdr.z = (float)atof(pgd + 1); + } else { + isGDL = true; + gdl .x = (float)atof(pgd + 6); + pgd = strchr(pgd + 6, ','); + if (pgd) gdl.y = (float)atof(pgd + 1); + pgd = strchr(pgd + 1, ','); + if (pgd) gdl.z = (float)atof(pgd + 1); + } + } + } +}; diff --git a/ECTrainer1/framework.h b/ECTrainer1/framework.h new file mode 100644 index 0000000..4f5d370 --- /dev/null +++ b/ECTrainer1/framework.h @@ -0,0 +1,49 @@ +#pragma once + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Windows ヘッダーから使用されていない部分を除外します。 +#endif + +#include "targetver.h" + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 一部の CString コンストラクターは明示的です。 + +// 一般的で無視しても安全な MFC の警告メッセージの一部の非表示を解除します。 +#define _AFX_ALL_WARNINGS + +#include // MFC のコアおよび標準コンポーネント +#include // MFC の拡張部分 + + +#include // MFC オートメーション クラス + + + +#ifndef _AFX_NO_OLE_SUPPORT +#include // MFC の Internet Explorer 4 コモン コントロール サポート +#endif +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC の Windows コモン コントロール サポート +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include // MFC におけるリボンとコントロール バーのサポート + + + + + + + + + +#ifdef _UNICODE +#if defined _M_IX86 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_X64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#else +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#endif +#endif + + diff --git a/ECTrainer1/manL1.png b/ECTrainer1/manL1.png new file mode 100644 index 0000000..8167af3 --- /dev/null +++ b/ECTrainer1/manL1.png Binary files differ diff --git a/ECTrainer1/myOpenCV.h b/ECTrainer1/myOpenCV.h new file mode 100644 index 0000000..efc5474 --- /dev/null +++ b/ECTrainer1/myOpenCV.h @@ -0,0 +1,103 @@ + +// OpenCV 3�n, 4�n ���ʃw�b�_�[�t�@�C�� +// 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 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 + +#else +// �•ʂ̃��C�u�����w�� �iCmake��Static�Ŏg�p���Ȃǁj +// ��{���W���[�� +#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 +#pragma comment(lib, PREHEAD "videoio" CV_VERSION_STR CV_EXT_STR) // Video I/O +#pragma comment(lib, PREHEAD "highgui" CV_VERSION_STR CV_EXT_STR) // High-level GUI +//#pragma comment(lib, PREHEAD "video" CV_VERSION_STR CV_EXT_STR) // Video Analysis +#pragma comment(lib, PREHEAD "calib3d" CV_VERSION_STR CV_EXT_STR) // Camera Calibration and 3D Reconstruction +//#pragma comment(lib, PREHEAD "features2d" CV_VERSION_STR CV_EXT_STR) // 2D Features Framework +//#pragma comment(lib, PREHEAD "objdetect" CV_VERSION_STR CV_EXT_STR) // Object Detection +//#pragma comment(lib, PREHEAD "dnn" CV_VERSION_STR CV_EXT_STR) // Deep Neural Network module +//#pragma comment(lib, PREHEAD "ml" CV_VERSION_STR CV_EXT_STR) // Machine Learning +//#pragma comment(lib, PREHEAD "flann" CV_VERSION_STR CV_EXT_STR) // Clustering and Search in Multi-Dimensional Spaces +//#pragma comment(lib, PREHEAD "photo" CV_VERSION_STR CV_EXT_STR) // Computational Photography +//#pragma comment(lib, PREHEAD "stitching" CV_VERSION_STR CV_EXT_STR) // Images stitching +//#pragma comment(lib, PREHEAD "cudaarithm" CV_VERSION_STR CV_EXT_STR) // CUDA Operations on Matrices +//#pragma comment(lib, PREHEAD "cudabgsegm" CV_VERSION_STR CV_EXT_STR) // CUDA Background Segmentation +//#pragma comment(lib, PREHEAD "cudacodec" CV_VERSION_STR CV_EXT_STR) // CUDA Video Encoding/Decoding +//#pragma comment(lib, PREHEAD "cudafeatures2d" CV_VERSION_STR CV_EXT_STR) // CUDA Feature Detection and Description +//#pragma comment(lib, PREHEAD "cudafilters" CV_VERSION_STR CV_EXT_STR) // CUDA Image Filtering +//#pragma comment(lib, PREHEAD "cudaimgproc" CV_VERSION_STR CV_EXT_STR) // CUDA Image Processing +//#pragma comment(lib, PREHEAD "cudalegacy" CV_VERSION_STR CV_EXT_STR) // CUDA Legacy support +//#pragma comment(lib, PREHEAD "cudaobjdetect" CV_VERSION_STR CV_EXT_STR) // CUDA Object Detection +//#pragma comment(lib, PREHEAD "cudaoptflow" CV_VERSION_STR CV_EXT_STR) // CUDA Optical Flow +//#pragma comment(lib, PREHEAD "cudastereo" CV_VERSION_STR CV_EXT_STR) // CUDA Stereo Correspondence +//#pragma comment(lib, PREHEAD "cudawarping" CV_VERSION_STR CV_EXT_STR) // CUDA Image Warping +//#pragma comment(lib, PREHEAD "cudev" CV_VERSION_STR CV_EXT_STR) // CUDA Device layer +//#pragma comment(lib, PREHEAD "shape" CV_VERSION_STR CV_EXT_STR) // Shape Distance and Matching +//#pragma comment(lib, PREHEAD "superres" CV_VERSION_STR CV_EXT_STR) // Super Resolution +//#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 +//#pragma comment(lib, PREHEAD "ccalib" CV_VERSION_STR CV_EXT_STR) // Custom Calibration Pattern for 3D reconstruction +//#pragma comment(lib, PREHEAD "cnn_3dobj" CV_VERSION_STR CV_EXT_STR) // 3D object recognition and pose estimation API +//#pragma comment(lib, PREHEAD "cvv" CV_VERSION_STR CV_EXT_STR) // GUI for Interactive Visual Debugging of Computer Vision Programs +//#pragma comment(lib, PREHEAD "datasets" CV_VERSION_STR CV_EXT_STR) // Framework for working with different datasets +//#pragma comment(lib, PREHEAD "dnn_objdetect" CV_VERSION_STR CV_EXT_STR) // DNN used for object detection +//#pragma comment(lib, PREHEAD "dpm" CV_VERSION_STR CV_EXT_STR) // Deformable Part-based Models +//#pragma comment(lib, PREHEAD "face" CV_VERSION_STR CV_EXT_STR) // Face Analysis +//#pragma comment(lib, PREHEAD "freetype" CV_VERSION_STR CV_EXT_STR) // Drawing UTF-8 strings with freetype/harfbuzz +//#pragma comment(lib, PREHEAD "fuzzy" CV_VERSION_STR CV_EXT_STR) // Image processing based on fuzzy mathematics +//#pragma comment(lib, PREHEAD "hdf" CV_VERSION_STR CV_EXT_STR) // Hierarchical Data Format I/O routines +//#pragma comment(lib, PREHEAD "hfs" CV_VERSION_STR CV_EXT_STR) // Hierarchical Feature Selection for Efficient Image Segmentation +//#pragma comment(lib, PREHEAD "img_hash" CV_VERSION_STR CV_EXT_STR) // The module brings implementations of different image hashing algorithms. +//#pragma comment(lib, PREHEAD "line_descriptor" CV_VERSION_STR CV_EXT_STR) // Binary descriptors for lines extracted from an image +//#pragma comment(lib, PREHEAD "matlab" CV_VERSION_STR CV_EXT_STR) // MATLAB Bridge +//#pragma comment(lib, PREHEAD "optflow" CV_VERSION_STR CV_EXT_STR) // Optical Flow Algorithms +//#pragma comment(lib, PREHEAD "ovis" CV_VERSION_STR CV_EXT_STR) // OGRE 3D Visualiser +//#pragma comment(lib, PREHEAD "phase_unwrapping" CV_VERSION_STR CV_EXT_STR) // Phase Unwrapping API +//#pragma comment(lib, PREHEAD "plot" CV_VERSION_STR CV_EXT_STR) // Plot function for Mat data +//#pragma comment(lib, PREHEAD "reg" CV_VERSION_STR CV_EXT_STR) // Image Registration +//#pragma comment(lib, PREHEAD "rgbd" CV_VERSION_STR CV_EXT_STR) // RGB-Depth Processing +//#pragma comment(lib, PREHEAD "saliency" CV_VERSION_STR CV_EXT_STR) // Saliency API +//#pragma comment(lib, PREHEAD "sfm" CV_VERSION_STR CV_EXT_STR) // Structure From Motion +//#pragma comment(lib, PREHEAD "stereo" CV_VERSION_STR CV_EXT_STR) // Stereo Correspondance Algorithms +//#pragma comment(lib, PREHEAD "structured_light" CV_VERSION_STR CV_EXT_STR) // Structured Light API +//#pragma comment(lib, PREHEAD "surface_matching" CV_VERSION_STR CV_EXT_STR) // Surface Matching +//#pragma comment(lib, PREHEAD "text" CV_VERSION_STR CV_EXT_STR) // Scene Text Detection and Recognition +//#pragma comment(lib, PREHEAD "tracking" CV_VERSION_STR CV_EXT_STR) // Tracking API +//#pragma comment(lib, PREHEAD "xfeatures2d" CV_VERSION_STR CV_EXT_STR) // Extra 2D Features Framework +//#pragma comment(lib, PREHEAD "ximgproc" CV_VERSION_STR CV_EXT_STR) // Extended Image Processing +//#pragma comment(lib, PREHEAD "xobjdetect" CV_VERSION_STR CV_EXT_STR) // Extended object detection +//#pragma comment(lib, PREHEAD "xphoto" CV_VERSION_STR CV_EXT_STR) // Additional photo processing algorithms +#endif + +using namespace cv; diff --git a/ECTrainer1/opencv411.props b/ECTrainer1/opencv411.props new file mode 100644 index 0000000..45beb6f --- /dev/null +++ b/ECTrainer1/opencv411.props @@ -0,0 +1,15 @@ + + + + + + D:\SDK\OpenCV4.1.1\include;$(IncludePath) + D:\SDK\OpenCV4.1.1\x64\vc16\lib;$(LibraryPath) + + + D:\SDK\OpenCV4.1.1\include;$(IncludePath) + D:\SDK\OpenCV4.1.1\x86\vc16\lib\lib;$(LibraryPath) + + + + diff --git a/ECTrainer1/pch.cpp b/ECTrainer1/pch.cpp new file mode 100644 index 0000000..0d6adf8 --- /dev/null +++ b/ECTrainer1/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: プリコンパイル済みヘッダーに対応するソース ファイル + +#include "pch.h" + +// プリコンパイル済みヘッダーを使用している場合、コンパイルを成功させるにはこのソース ファイルが必要です。 diff --git a/ECTrainer1/pch.h b/ECTrainer1/pch.h new file mode 100644 index 0000000..10f9979 --- /dev/null +++ b/ECTrainer1/pch.h @@ -0,0 +1,13 @@ +// pch.h: プリコンパイル済みヘッダー ファイルです。 +// 次のファイルは、その後のビルドのビルド パフォーマンスを向上させるため 1 回だけコンパイルされます。 +// コード補完や多くのコード参照機能などの IntelliSense パフォーマンスにも影響します。 +// ただし、ここに一覧表示されているファイルは、ビルド間でいずれかが更新されると、すべてが再コンパイルされます。 +// 頻繁に更新するファイルをここに追加しないでください。追加すると、パフォーマンス上の利点がなくなります。 + +#ifndef PCH_H +#define PCH_H + +// プリコンパイルするヘッダーをここに追加します +#include "framework.h" + +#endif //PCH_H diff --git a/ECTrainer1/res/ECTrainer1.ico b/ECTrainer1/res/ECTrainer1.ico new file mode 100644 index 0000000..d56fbcd --- /dev/null +++ b/ECTrainer1/res/ECTrainer1.ico Binary files differ diff --git a/ECTrainer1/res/ECTrainer1.rc2 b/ECTrainer1/res/ECTrainer1.rc2 new file mode 100644 index 0000000..ae7da82 --- /dev/null +++ b/ECTrainer1/res/ECTrainer1.rc2 Binary files differ diff --git a/ECTrainer1/resource.h b/ECTrainer1/resource.h new file mode 100644 index 0000000..ae06403 --- /dev/null +++ b/ECTrainer1/resource.h @@ -0,0 +1,22 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ で生成されたインクルード ファイル。 +// ECTrainer1.rc で使用 +// +#define IDM_ABOUTBOX 0x0010 +#define IDD_ABOUTBOX 100 +#define IDS_ABOUTBOX 101 +#define IDD_ECTRAINER1_DIALOG 102 +#define IDR_MAINFRAME 128 +#define IDC_IMAGE 1002 +#define IDC_IMAGE2 1003 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 131 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/ECTrainer1/targetver.h b/ECTrainer1/targetver.h new file mode 100644 index 0000000..b99810c --- /dev/null +++ b/ECTrainer1/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// SDKDDKVer.h をインクルードすると、利用できる最も上位の Windows プラットフォームが定義されます。 + +// 以前の Windows プラットフォーム用にアプリケーションをビルドする場合は、WinSDKVer.h をインクルードし、 +// SDKDDKVer.h をインクルードする前に、サポート対象とするプラットフォームを示すように _WIN32_WINNT マクロを設定します。 + +#include diff --git a/PrismSoftware.sln b/PrismSoftware.sln index 5afd5c6..e9e8b0f 100644 --- a/PrismSoftware.sln +++ b/PrismSoftware.sln @@ -5,6 +5,8 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GSTtest", "GSTtest\GSTtest.vcxproj", "{BB038458-DFC5-4ACD-96CB-35512801136D}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ECTrainer1", "ECTrainer1\ECTrainer1.vcxproj", "{E2EC3843-4077-4DC8-96F7-37C1BA5094FD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -18,9 +20,16 @@ {BB038458-DFC5-4ACD-96CB-35512801136D}.Debug|x86.ActiveCfg = Debug|Win32 {BB038458-DFC5-4ACD-96CB-35512801136D}.Debug|x86.Build.0 = Debug|Win32 {BB038458-DFC5-4ACD-96CB-35512801136D}.Release|x64.ActiveCfg = Release|x64 - {BB038458-DFC5-4ACD-96CB-35512801136D}.Release|x64.Build.0 = Release|x64 {BB038458-DFC5-4ACD-96CB-35512801136D}.Release|x86.ActiveCfg = Release|Win32 {BB038458-DFC5-4ACD-96CB-35512801136D}.Release|x86.Build.0 = Release|Win32 + {E2EC3843-4077-4DC8-96F7-37C1BA5094FD}.Debug|x64.ActiveCfg = Debug|x64 + {E2EC3843-4077-4DC8-96F7-37C1BA5094FD}.Debug|x64.Build.0 = Debug|x64 + {E2EC3843-4077-4DC8-96F7-37C1BA5094FD}.Debug|x86.ActiveCfg = Debug|Win32 + {E2EC3843-4077-4DC8-96F7-37C1BA5094FD}.Debug|x86.Build.0 = Debug|Win32 + {E2EC3843-4077-4DC8-96F7-37C1BA5094FD}.Release|x64.ActiveCfg = Release|x64 + {E2EC3843-4077-4DC8-96F7-37C1BA5094FD}.Release|x64.Build.0 = Release|x64 + {E2EC3843-4077-4DC8-96F7-37C1BA5094FD}.Release|x86.ActiveCfg = Release|Win32 + {E2EC3843-4077-4DC8-96F7-37C1BA5094FD}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE