1.為什么使用DirectShow
筆者使用的是兩個(gè)USB攝像頭,單攝像頭視頻采集使用OpenCV的VideoCapture類沒(méi)有問(wèn)題,但是雙攝像頭就有問(wèn)題,一個(gè)正常,另外一個(gè)采集不到信息,顯示一片灰色。網(wǎng)上有種解決方法是逆序打開攝像頭,結(jié)果兩個(gè)窗口是可以采集到視頻信息,但是竟然是同一個(gè)攝像頭的視頻信息,無(wú)奈的只能使用DirectShow采集多攝像頭視頻信息。
先看看什么是DirectShow:
DirectShow 是 DirectX 的組件之一, DirectX 軟件開發(fā)包是 Microsoft 提供的一套在 Windows平臺(tái)上開發(fā)高性能圖形、聲音、輸入、輸出和網(wǎng)絡(luò)游戲的編程接口。這其中,DirectShow提供了應(yīng)用程序從適當(dāng)?shù)挠布胁蹲胶皖A(yù)覽音、視頻的能力。數(shù)據(jù)源包括: VCR、 Camera、 TV Tuner、 Microphone 或其他的數(shù)據(jù)源。應(yīng)用程序可以立刻顯示捕捉的數(shù)據(jù)(預(yù)覽),或是保存到一個(gè)文件中。
攝像頭采集信息常用的軟件AMCap就是基于DirectShow SDK編寫的。查閱一下官方文檔,感覺(jué)好難的樣子,難道要新學(xué)一門“快過(guò)時(shí)”的技術(shù)嗎?幸好于仕琪老師寫了一個(gè)CCameraDS類,可直接返回IplImage,使用方便。
2.在VS2010中配置DirectShow并采集雙目攝像頭視頻
下載DirectShow相關(guān)文件,我已經(jīng)共享在百度云盤,點(diǎn)擊下載。解壓以后copy到D:\opencv里(放在這里為了管理方便)
在解決資源管理器中的項(xiàng)目名稱處右鍵\屬性\配置屬性\VC++目錄,引用目錄中添加DirectShow的include文件夾,我添加的是D:\opencv\DirectShow\Include
在引用目錄下面有一個(gè)庫(kù)目錄,添加DirectShow的Lib文件夾,我添加的是D:\opencv\DirectShow\Lib;
下載CCameraDS類相關(guān)文件,點(diǎn)擊下載。解壓以后把CameraDS.h,CameraDS.cpp復(fù)制到已經(jīng)配置好OpenCV庫(kù)的工程中,并添加到工程中。在解決資源管理器中,頭文件和源文件分別右鍵\添加\現(xiàn)有項(xiàng),把CCameraDS的頭文件和源文件添加進(jìn)去
main函數(shù)寫入如下內(nèi)容
#include "stdafx.h"
#include
#include
#include
#include
#include
#include
#include "CameraDS.h"
using namespace cv;
int main()
{
int cam_count;
//僅僅獲取攝像頭數(shù)目
cam_count = CCameraDS::CameraCount();
printf("There are %d cameras.\n", cam_count);
}
編譯,error,一個(gè)一個(gè)解決
fatal error C1083: 無(wú)法打開包括文件:”dxtrans.h”: No such file or directory
下載的DirectShow包里面沒(méi)有該頭文件,全盤搜索Windows也沒(méi)有,后來(lái)發(fā)現(xiàn)使用該頭文件的是qedit.h,估計(jì)這個(gè)文件有問(wèn)題。直接在網(wǎng)上重新down了一個(gè)qedit.h(點(diǎn)擊下載),替代了DirectShow自帶的qedit.h,路徑如下D:\opencv\DirectShow\Include\qedit.h。其它解決方法參考這里,也有效果
fatal error C1010:在查找預(yù)編譯頭時(shí)遇到意外的文件結(jié)尾。是否忘記了向源中添加“#include “StdAfx.h””?
在CameraDS.cpp最上面一行添加#include "StdAfx.h"即可
運(yùn)行,結(jié)果如下:
改寫main函數(shù),顯示兩個(gè)攝像頭內(nèi)容
int main()
{
int cam_count;
//僅僅獲取攝像頭數(shù)目
cam_count = CCameraDS::CameraCount();
printf("There are %d cameras.\n", cam_count);
//獲取所有攝像頭的名稱
for(int i=0; i < cam_count; i++)
{
char camera_name[1024];
int retval = CCameraDS::CameraName(i, camera_name, sizeof(camera_name) );
if(retval >0)
printf("Camera #%d's Name is '%s'.\n", i, camera_name);
else
printf("Can not get Camera #%d's name.\n", i);
}
if(cam_count==0)
return -1;
CCameraDS camera1, camera2;
//手動(dòng)打開攝像頭
// if(! camera1.OpenCamera(0, true)) //彈出屬性選擇窗口
//
{
//
fprintf(stderr, "Can not open camera1.\n");
//
return -1;
//
}
// if(! camera2.OpenCamera(1, true)) //彈出屬性選擇窗口
// {
//
fprintf(stderr, "Can not open camera2.\n");
//
return -1;
// }
//自動(dòng)打開攝像頭
if(! camera1.OpenCamera(0, false, 320, 240)) //不彈出屬性選擇窗口,用代碼制定圖像寬和高
{
fprintf(stderr, "Can not open camera1.\n");
return -1;
}
if(! camera2.OpenCamera(1, false, 320, 240))//不彈出屬性選擇窗口,用代碼制定圖像寬和高
{
fprintf(stderr, "Can not open camera2.\n");
return -1;
}
while(1)
{
//獲取一幀
IplImage *pFrame1 = camera1.QueryFrame();
IplImage *pFrame2 = camera2.QueryFrame();
//顯示
cvShowImage("camera1", pFrame1);
cvShowImage("camera2", pFrame2);
if (cvWaitKey(20) == 'q')
break;
}
camera1.CloseCamera(); //可不調(diào)用此函數(shù),CCameraDS析構(gòu)時(shí)會(huì)自動(dòng)關(guān)閉攝像頭
cvDestroyWindow("camera1");
camera2.CloseCamera();
cvDestroyWindow("camera2");
return 0;
}
運(yùn)行結(jié)果如下:
3.總結(jié)
評(píng)論