MFC Camera 攝像頭預覽 拍照


windows 上開發攝像頭程序,比較容易的方式是 OpenCV ,幾行代碼就能顯示出來,但是簡單的容易搞,有點難度定制化需求的就不這么容易了。
所以說還是要從,最基礎的 DirectShow 開始搞起,網上找了許久,這方面的資料不多。
准備工作:
SDK的下載地址:https://www.microsoft.com/en-us/download/details.aspx?id=8442 下載完成,安裝上就行了。
開發環境:win7 x86, vs2010, DirectShow SDK
參考程序:
C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow
先編譯一下 baseclasses
C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\capture\amcap
amcap 源碼,功能還挺齊全,源碼也有,但是有幾千行,這里面有的功能是不需要的,的確,直接把這個代碼復制到,你的工程里面修改一下,的確是可以使用。
但是這樣,還是不知道,其中的原理。

下面新建一個普通的 MFC 程序,配置一些編譯屬性,對比着 amcap 參考就行。

 

1,實現獲取本機 Camera 列表,音頻設備

 1 void CSampleCapDlg::AddDevices()
 2 {
 3     HRESULT hr;
 4 
 5     // enumerate all video capture devices
 6     ICreateDevEnum *pCreateDevEnum=0;
 7     hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
 8                           IID_ICreateDevEnum, (void**)&pCreateDevEnum);
 9     if(hr != NOERROR)
10     {
11         return;
12     }
13 
14     IEnumMoniker *pEm=0;
15     hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);
16     if(hr != NOERROR)
17     {
18         return;
19     }
20 
21     pEm->Reset();
22     ULONG cFetched;
23     IMoniker *pM;
24 
25     while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
26     {
27         IPropertyBag *pBag=0;
28 
29         hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
30         if(SUCCEEDED(hr))
31         {
32             VARIANT var;
33             var.vt = VT_BSTR;
34             hr = pBag->Read(L"FriendlyName", &var, NULL);
35             if(hr == NOERROR)
36             {
37                 m_ComboBoxVideoDevice.AddString(var.bstrVal);
38                 SysFreeString(var.bstrVal);
39                 pM->AddRef();
40             }
41             pBag->Release();
42         }
43 
44         pM->Release();
45     }
46     pEm->Release();
47 
48     // enumerate all audio capture devices
49     ASSERT(pCreateDevEnum != NULL);
50 
51     hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEm, 0);
52     pCreateDevEnum->Release();
53     if(hr != NOERROR)
54         return;
55     pEm->Reset();
56 
57     while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
58     {
59         IPropertyBag *pBag;
60         hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
61         if(SUCCEEDED(hr))
62         {
63             VARIANT var;
64             var.vt = VT_BSTR;
65             hr = pBag->Read(L"FriendlyName", &var, NULL);
66             if(hr == NOERROR)
67             {
68                 m_ComboBoxAudioDevice.AddString(var.bstrVal);
69                 SysFreeString(var.bstrVal);
70                 pM->AddRef();
71             }
72             pBag->Release();
73         }
74         pM->Release();
75     }
76 
77     pEm->Release();
78 }

2,實時預覽

 

 代碼比較多,不貼了。

3,拍照

寫 BMP 這里不講,很簡單一個文件頭加內容。 JPG PNG 之類的,要用到第三方庫。這里也不講。

怎么獲取圖像幀:

1 hr = CoCreateInstance(CLSID_SampleGrabber,NULL,CLSCTX_INPROC_SERVER,
2                           IID_IBaseFilter, (LPVOID*)&pSampleGrabberFilter);
3 hr = pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber,(LPVOID*)&m_pSampGrabber);
4 hr = m_pSampGrabber->SetCallback(&g_sampleGrabberCB,1);
5 HRESULT STDMETHODCALLTYPE SampleGrabberCallback::BufferCB(double Time, BYTE *pBuffer, long BufferLen)

創建一個 m_pSampGrabber 在重寫的 BufferCB 中,自己保存數據。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM