Opencv区分カメラwindows iserialNumber
問題の背景:
カメラシリアル番号に従ってOpen(index)を取得します.
Opencvを使用して複数のカメラを開く場合、一般的にはVideoCapture.open(index)方式を使用します.この方法は便利ですが、どのカメラを開くかを指定するために他の情報を入力することはできません.
Windowsプラットフォームの下で、OpencvはUSBカメラのロジックコードを開けて主にcap_にありますdshow.cppでは、ソースコードを読んでデバイスを開く順序は列挙順序のみに関係し、DirectShowのIPropertyBagクラスを使用してDevicePath、FriendNameなどの属性を取得できますが、シーケンス番号(iserialNumber)に関する方法はありません.実際の使用過程では、一般的に私たちが使っているカメラはメーカーであり、設備の実例経路、設備名はすべて同じで、ツールが修正できるか、メーカーが設備名を修正して区別することができるが、設備名は信頼できず、挿抜の順序とHubによって変化し、設備と唯一バインドされていない.メーカーがシリアル番号を変更するツールを提供した後、シリアル番号はデバイスと唯一バインドされており、信頼性が高く、USBカメラを区別することができます.したがって,シーケンス番号を取得できる方法を見つけ,OpencvのdirectShowコードと組み合わせて考えると,固定シーケンス番号の固定indexを取得し,videoCaptureでそのindexデバイスを開くことができる.注意すべき点は、cameraが存在するhubシーケンス番号のみが変更でき、それ自体は変更できないため、シーケンス番号を取得する過程で親デバイスを取得する必要があることです.
コードは次のとおりです.
ここでは、[L,R][バージョン番号][行][列]、例えばL 000,R 010の4ビットのシーケンス番号が用いられる.プログラム中のCheckSerialNumberはシーケンス番号のチェックです.コードは2つのステップに分けられ、第1のステップはdirectShow列挙デバイスを利用してデバイスインスタンスパスを取得し、第2のステップはインスタンスパスを取得した後、windows Api二次列挙を採用し、親デバイスのシーケンス番号を取得し、対応関係を得る.例えばL 001は、第2のオープンであるべきであり、彼のOpencv列挙Indexは3である可能性がある.では、私はこのカメラを開くと、Open(3).
もし問題があれば、私のqqに連絡してください.
カメラシリアル番号に従ってOpen(index)を取得します.
Opencvを使用して複数のカメラを開く場合、一般的にはVideoCapture.open(index)方式を使用します.この方法は便利ですが、どのカメラを開くかを指定するために他の情報を入力することはできません.
Windowsプラットフォームの下で、OpencvはUSBカメラのロジックコードを開けて主にcap_にありますdshow.cppでは、ソースコードを読んでデバイスを開く順序は列挙順序のみに関係し、DirectShowのIPropertyBagクラスを使用してDevicePath、FriendNameなどの属性を取得できますが、シーケンス番号(iserialNumber)に関する方法はありません.実際の使用過程では、一般的に私たちが使っているカメラはメーカーであり、設備の実例経路、設備名はすべて同じで、ツールが修正できるか、メーカーが設備名を修正して区別することができるが、設備名は信頼できず、挿抜の順序とHubによって変化し、設備と唯一バインドされていない.メーカーがシリアル番号を変更するツールを提供した後、シリアル番号はデバイスと唯一バインドされており、信頼性が高く、USBカメラを区別することができます.したがって,シーケンス番号を取得できる方法を見つけ,OpencvのdirectShowコードと組み合わせて考えると,固定シーケンス番号の固定indexを取得し,videoCaptureでそのindexデバイスを開くことができる.注意すべき点は、cameraが存在するhubシーケンス番号のみが変更でき、それ自体は変更できないため、シーケンス番号を取得する過程で親デバイスを取得する必要があることです.
コードは次のとおりです.
ここでは、[L,R][バージョン番号][行][列]、例えばL 000,R 010の4ビットのシーケンス番号が用いられる.プログラム中のCheckSerialNumberはシーケンス番号のチェックです.コードは2つのステップに分けられ、第1のステップはdirectShow列挙デバイスを利用してデバイスインスタンスパスを取得し、第2のステップはインスタンスパスを取得した後、windows Api二次列挙を採用し、親デバイスのシーケンス番号を取得し、対応関係を得る.例えばL 001は、第2のオープンであるべきであり、彼のOpencv列挙Indexは3である可能性がある.では、私はこのカメラを開くと、Open(3).
// ConsoleApplication1.cpp : 。
//
#pragma comment (lib, "setupapi.lib")
#pragma comment (lib, "cfgmgr32.lib")
#pragma comment (lib, "strmiids.lib")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "DistinguishCamera.h"
#include
#define GUID_CAMERA_STRING L"{65e8773d-8f56-11d0-a3b9-00a0c9223196}"
static char* GuidToString(const GUID &guid)
{
int buf_len = 64;
char *buf = (char *)malloc(buf_len);
_snprintf(
buf,
buf_len,
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1],
guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5],
guid.Data4[6], guid.Data4[7]);
//printf("%s
",buf);
return buf;
}
static BOOL GetParentDeviceInstanceId(_Out_ PWCHAR pszParentDeviceInstanceId, _Out_ PDEVINST phParentDeviceInstanceId, _In_ DEVINST hCurrentDeviceInstanceId) {
// Handle to parent Device Instance ID
BOOL result = CM_Get_Parent(phParentDeviceInstanceId, hCurrentDeviceInstanceId, 0);
if (result == CR_SUCCESS) {
// Device ID as String
memset(pszParentDeviceInstanceId, 0, MAX_DEVICE_ID_LEN);
result = CM_Get_Device_IDW(*phParentDeviceInstanceId, pszParentDeviceInstanceId, MAX_DEVICE_ID_LEN, 0);
if (result == CR_SUCCESS) {
return TRUE;
}
}
return FALSE;
}
// , "C[Version][L|R][int][int]",
static int CheckSerialNumber(string serialNumber)
{
int k = serialNumber.length() - 1;
while (serialNumber[k] != '\\') k--;
if (serialNumber[k + 1] == 'C' && (serialNumber[k + 2] >= '0' && serialNumber[k + 2] <= '9') &&(serialNumber[k + 3] == 'L' || serialNumber[k + 3] == 'R'))
{
int id = (serialNumber[k + 4] - '0') * 10 + (serialNumber[k + 5] - '0') * 2;
if (serialNumber[k + 3] == 'R') id++;
return id;
}
else
return -1;//illegal
}
static int getSerialNumber(string childDistanceId)
{
USES_CONVERSION;
// GUID to match devices by class
GUID guid;
CLSIDFromString(GUID_CAMERA_STRING, &guid);
// Get matching devices info
HDEVINFO devInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);// DIGCF_ALLCLASSES);
// Device Instance ID as string
WCHAR szDeviceInstanceId[MAX_DEVICE_ID_LEN];
if (devInfo != INVALID_HANDLE_VALUE) {
DWORD devIndex = 0;
SP_DEVINFO_DATA devInfoData;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
// Loop over devices found in SetupDiGetClassDevs
while (SetupDiEnumDeviceInfo(devInfo, devIndex, &devInfoData))
{
// Read Device Instance ID of current device
memset(szDeviceInstanceId, 0, MAX_DEVICE_ID_LEN);
SetupDiGetDeviceInstanceIdW(devInfo, &devInfoData, szDeviceInstanceId, MAX_PATH, 0);
//compare the device's instanceId
char *szDeviceInstId = W2A(szDeviceInstanceId);
transform(childDistanceId.begin(), childDistanceId.end(), childDistanceId.begin(), ::toupper);
if (childDistanceId.compare(szDeviceInstId) == 0)
{
// Handle of current defice instance id
DEVINST hCurrentDeviceInstanceId = devInfoData.DevInst;
// Handle of parent Device Instance ID
DEVINST hParentDeviceInstanceId;
// Parent Device Instance ID as string
WCHAR pszParentDeviceInstanceId[MAX_DEVICE_ID_LEN];
// Initialize / clean variables
memset(szDeviceInstanceId, 0, MAX_DEVICE_ID_LEN);
hParentDeviceInstanceId = NULL;
if (GetParentDeviceInstanceId(pszParentDeviceInstanceId, &hParentDeviceInstanceId, hCurrentDeviceInstanceId))
{
string parentDeviceInstanceId = W2A(pszParentDeviceInstanceId);
return (CheckSerialNumber(parentDeviceInstanceId));
//if (DeviceIdMatchesPattern(pszParentDeviceInstanceId, pszParentDeviceInstanceIdPattern)) {
// // Parent Device Instance ID matches given regexp - print it out and exit
// wprintf(L"%s
", pszParentDeviceInstanceId);
// getchar();
// return 0;
//}
// Parent Device Instance ID does not match the pattern - check parent's parent
//hCurrentDeviceInstanceId = hParentDeviceInstanceId;
break;
}
else {
// There is no parent. Stop the loop.
break;
}
}
devIndex++;
}
}
return 0;
}
bool getCameraOrderBySerialNumber(vector *order, int numOfCamera)
{
int numOfFoundedCamera = 0;
USES_CONVERSION;
// Init COM
HRESULT hr = NULL;
hr = CoInitialize(NULL);
if (FAILED(hr)){
printf("Error, Can not init COM.");
return false;
}
// printf("===============Directshow Filters ===============
");
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr)){
return hr;
}
IEnumMoniker *pEnumCat = NULL;
//Category
/************************************************************************
Friendly Name CLSID
-------------------------------------------------------------------------
Audio Capture Sources CLSID_AudioInputDeviceCategory
Audio Compressors CLSID_AudioCompressorCategory
Audio Renderers CLSID_AudioRendererCategory
Device Control Filters CLSID_DeviceControlCategory
DirectShow Filters CLSID_LegacyAmFilterCategory
External Renderers CLSID_TransmitCategory
Midi Renderers CLSID_MidiRendererCategory
Video Capture Sources CLSID_VideoInputDeviceCategory
Video Compressors CLSID_VideoCompressorCategory
WDM Stream Decompression Devices CLSID_DVDHWDecodersCategory
WDM Streaming Capture Devices AM_KSCATEGORY_CAPTURE
WDM Streaming Crossbar Devices AM_KSCATEGORY_CROSSBAR
WDM Streaming Rendering Devices AM_KSCATEGORY_RENDER
WDM Streaming Tee/Splitter Devices AM_KSCATEGORY_SPLITTER
WDM Streaming TV Audio Devices AM_KSCATEGORY_TVAUDIO
WDM Streaming TV Tuner Devices AM_KSCATEGORY_TVTUNER
WDM Streaming VBI Codecs AM_KSCATEGORY_VBICODEC
************************************************************************/
//hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnumCat, 0);
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
//hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioCompressorCategory, &pEnumCat, 0);
//hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEnumCat, 0);
//hr = pSysDevEnum->CreateClassEnumerator(CLSID_MediaMultiplexerCategory, &pEnumCat, 0);
//hr = pSysDevEnum->CreateClassEnumerator(CLSID_LegacyAmFilterCategory, &pEnumCat, 0);
if (hr != S_OK) {
pSysDevEnum->Release();
return false;
}
// Obtain a class enumerator for the video input category.
IMoniker *pMoniker = NULL;
ULONG monikerFetched;
int deviceCounter = 0;
//Filter
while (pEnumCat->Next(1, &pMoniker, &monikerFetched) == S_OK)
{
IPropertyBag *pPropBag;
VARIANT varName;
IBaseFilter *pFilter = NULL;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
if (FAILED(hr))
{
pMoniker->Release();
continue;
}
VariantInit(&varName);
// hr = pPropBag->Read(L"FriendlyName", &varName, 0);
hr = pPropBag->Read(L"DevicePath", &varName, 0);
//"FriendlyName": The name of the device.
//"Description": A description of the device.
//Filter Info================
// com
string varNameBak = W2A(varName.bstrVal);
while (varNameBak[0] != 'u')
varNameBak.erase(0, 1);//remove one char
int k = 0;
while (varNameBak[k] != '{')
{
if (varNameBak[k] == '#')
{
varNameBak.erase(k, 1);
varNameBak.insert(k, "\\");
}
k++;
}
varNameBak.erase(k - 1); //remove all char in id > k
//printf("[%s]
", W2A(varName.bstrVal));
//cout << varNameBak << endl;
int index = getSerialNumber(varNameBak);
if (index != -1)
{
order->at(index) = deviceCounter;
numOfFoundedCamera++;
}
VariantClear(&varName);
pPropBag->Release();
pMoniker->Release();
deviceCounter++;
}
pEnumCat->Release();
pSysDevEnum->Release();
//printf("=================================================
");
CoUninitialize();
//
//ID
if (numOfFoundedCamera == numOfCamera)
{
for (int i = 0; i < numOfCamera; i++)
if (order->at(i) == -1) return false;
return true;
}
else
{
return false;
}
}
//int main()
//{
// vector *order = new vector(10, -1);
// getCameraOrderBySerialNumber(order);
// return 0;
//}
もし問題があれば、私のqqに連絡してください.