Opencv区分カメラwindows iserialNumber

10341 ワード

問題の背景:
      カメラシリアル番号に従って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に連絡してください.