diff --git a/.gitignore b/.gitignore index 142cbb7f..4a16329c 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,4 @@ matlab_runners/Action Unit Experiments/out_SEMAINE/ matlab_runners/Gaze Experiments/mpii_out/ *.vspx matlab_version/AU_training/experiments/full_model_training/mat_models_o/ +lib/local/Utilities/x64/Release/ diff --git a/lib/3rdParty/CameraEnumerator/CameraEnumerator.vcxproj b/lib/3rdParty/CameraEnumerator/CameraEnumerator.vcxproj new file mode 100644 index 00000000..7ec6dacb --- /dev/null +++ b/lib/3rdParty/CameraEnumerator/CameraEnumerator.vcxproj @@ -0,0 +1,139 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {50B7D4BF-E33B-41D0-AA89-76BBA57BF5CC} + Win32Proj + CameraEnumerator + 8.1 + + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/3rdParty/CameraEnumerator/CameraEnumerator.vcxproj.filters b/lib/3rdParty/CameraEnumerator/CameraEnumerator.vcxproj.filters new file mode 100644 index 00000000..eccf7117 --- /dev/null +++ b/lib/3rdParty/CameraEnumerator/CameraEnumerator.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {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;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 + + + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/lib/3rdParty/CameraEnumerator/DeviceEnumerator.cpp b/lib/3rdParty/CameraEnumerator/DeviceEnumerator.cpp new file mode 100644 index 00000000..efb8a3aa --- /dev/null +++ b/lib/3rdParty/CameraEnumerator/DeviceEnumerator.cpp @@ -0,0 +1,123 @@ +#include "DeviceEnumerator.h" +#include + +std::map DeviceEnumerator::getVideoDevicesMap() { + return getDevicesMap(CLSID_VideoInputDeviceCategory); +} + +std::map DeviceEnumerator::getAudioDevicesMap() { + return getDevicesMap(CLSID_AudioInputDeviceCategory); +} + +// Returns a map of id and devices that can be used +std::map DeviceEnumerator::getDevicesMap(const GUID deviceClass) +{ + std::map deviceMap; + + // TODO add back? Calling from C# seems to not need this + //HRESULT hr = CoInitialize(nullptr); + //if (FAILED(hr)) { + // return deviceMap; // Empty deviceMap as an error + //} + + // Create the System Device Enumerator + ICreateDevEnum *pDevEnum; + HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum)); + + // If succeeded, create an enumerator for the category + IEnumMoniker *pEnum = NULL; + if (SUCCEEDED(hr)) { + hr = pDevEnum->CreateClassEnumerator(deviceClass, &pEnum, 0); + if (hr == S_FALSE) { + hr = VFW_E_NOT_FOUND; + } + pDevEnum->Release(); + } + + // Now we check if the enumerator creation succeeded + int deviceId = -1; + if (SUCCEEDED(hr)) { + // Fill the map with id and friendly device name + IMoniker *pMoniker = NULL; + while (pEnum->Next(1, &pMoniker, NULL) == S_OK) { + + IPropertyBag *pPropBag; + HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag)); + if (FAILED(hr)) { + pMoniker->Release(); + continue; + } + + // Create variant to hold data + VARIANT var; + VariantInit(&var); + + std::string deviceName; + std::string devicePath; + + // Read FriendlyName or Description + hr = pPropBag->Read(L"Description", &var, 0); // Read description + if (FAILED(hr)) { + // If description fails, try with the friendly name + hr = pPropBag->Read(L"FriendlyName", &var, 0); + } + // If still fails, continue with next device + if (FAILED(hr)) { + VariantClear(&var); + continue; + } + // Convert to string + else { + deviceName = ConvertBSTRToMBS(var.bstrVal); + } + + VariantClear(&var); // We clean the variable in order to read the next value + + // We try to read the DevicePath + hr = pPropBag->Read(L"DevicePath", &var, 0); + if (FAILED(hr)) { + VariantClear(&var); + continue; // If it fails we continue with next device + } + else { + devicePath = ConvertBSTRToMBS(var.bstrVal); + } + + // We populate the map + deviceId++; + Device currentDevice; + currentDevice.id = deviceId; + currentDevice.deviceName = deviceName; + currentDevice.devicePath = devicePath; + deviceMap[deviceId] = currentDevice; + + } + pEnum->Release(); + } + CoUninitialize(); + return deviceMap; +} + +/* +This two methods were taken from +https://stackoverflow.com/questions/6284524/bstr-to-stdstring-stdwstring-and-vice-versa +*/ + +std::string DeviceEnumerator::ConvertBSTRToMBS(BSTR bstr) +{ + int wslen = ::SysStringLen(bstr); + return ConvertWCSToMBS((wchar_t*)bstr, wslen); +} + +std::string DeviceEnumerator::ConvertWCSToMBS(const wchar_t* pstr, long wslen) +{ + int len = ::WideCharToMultiByte(CP_ACP, 0, pstr, wslen, NULL, 0, NULL, NULL); + + std::string dblstr(len, '\0'); + len = ::WideCharToMultiByte(CP_ACP, 0 /* no flags */, + pstr, wslen /* not necessary NULL-terminated */, + &dblstr[0], len, + NULL, NULL /* no default char */); + + return dblstr; +} diff --git a/lib/3rdParty/CameraEnumerator/DeviceEnumerator.h b/lib/3rdParty/CameraEnumerator/DeviceEnumerator.h new file mode 100644 index 00000000..6e4716c6 --- /dev/null +++ b/lib/3rdParty/CameraEnumerator/DeviceEnumerator.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#pragma comment(lib, "strmiids") + +#include +#include + +struct Device { + int id; // This can be used to open the device in OpenCV + std::string devicePath; + std::string deviceName; // This can be used to show the devices to the user +}; + +class DeviceEnumerator { + +public: + + DeviceEnumerator() = default; + std::map getDevicesMap(const GUID deviceClass); + std::map getVideoDevicesMap(); + std::map getAudioDevicesMap(); + +private: + + std::string ConvertBSTRToMBS(BSTR bstr); + std::string ConvertWCSToMBS(const wchar_t* pstr, long wslen); + +}; diff --git a/lib/3rdParty/CameraEnumerator/OpenCVDeviceEnumerator.cpp b/lib/3rdParty/CameraEnumerator/OpenCVDeviceEnumerator.cpp new file mode 100644 index 00000000..8c721815 --- /dev/null +++ b/lib/3rdParty/CameraEnumerator/OpenCVDeviceEnumerator.cpp @@ -0,0 +1,36 @@ +#include +#include + +#include "DeviceEnumerator.h" + +int main() +{ + + /* + The id field of the Device struct can be used with an OpenCV VideoCapture object + */ + + DeviceEnumerator de; + + // Audio Devices + std::map devices = de.getAudioDevicesMap(); + + // Print information about the devices + for (auto const &device : devices) { + std::cout << "== AUDIO DEVICE (id:" << device.first << ") ==" << std::endl; + std::cout << "Name: " << device.second.deviceName << std::endl; + std::cout << "Path: " << device.second.devicePath << std::endl; + } + + // Video Devices + devices = de.getVideoDevicesMap(); + + // Print information about the devices + for (auto const &device : devices) { + std::cout << "== VIDEO DEVICE (id:" << device.first << ") ==" << std::endl; + std::cout << "Name: " << device.second.deviceName << std::endl; + std::cout << "Path: " << device.second.devicePath << std::endl; + } + +} + diff --git a/lib/3rdParty/CameraEnumerator/readme.md b/lib/3rdParty/CameraEnumerator/readme.md new file mode 100644 index 00000000..bfbfa949 --- /dev/null +++ b/lib/3rdParty/CameraEnumerator/readme.md @@ -0,0 +1,32 @@ +# Device Enumerator for OpenCV + +This project contains a *C++* class that allows the enumeration of devices using DirectShow in Windows, in order to select and obtain the ID that needs to be used with OpenCV when creating, for example, a VideoCapture object to grab frames from a camera. I decided to put this up as "How to get the ID of a device to use inside OpenCV?" is a question that pops up continuously. + +## Contents + +The project contains the class itself (DeviceEnumerator.h and DeviceEnumerator.cpp) and also an example of how to use the class (OpenCVDeviceEnumerator.cpp) + +## License + +MIT License + +Copyright (c) 2018 David Gil de Gómez Pérez (Studiosi) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +