directshow+opencv打开easycap摄像头

今天开始写博客,记录今后的问题和解决思路。

问题:在win7上调用opencv打开easycap机子直接蓝屏,奔溃。。。

思路:本来去年做过一个类似的项目,不过是在ubuntu下面用v4l2写的,对windows编程不熟,查资料后决定选择directshow做为解决办法。

1.配置directshow环境

这个在网上搜了很多,本人用的是IDE是vs2012,而vs2012自带了directshow,那就直接开搞。首先编译一些directshow的sample来看看效果,这些sample在微软提供的sdk开发包里有,我上传到这里,有需要的可以通过这个百度云链接下载:http://pan.baidu.com/s/1kTLuS4J,里面有一个amcap例子,通过它我顺利的打开了easycap摄像头,但是看着里面的代码实在头疼 ,又开始搜资料。

2.使用CCameraDS类

找了一些通过directshow打开easycap的资料,下面是这个资料的链接:http://wiki.opencv.org.cn/index.php/%E4%BD%BF%E7%94%A8DirectShow%E9%87%87%E9%9B%86%E5%9B%BE%E5%83%8F,然后新建一个c++控制带工程,把相关的代码加入其中,提示缺少qedit.h头文件,我在网上下了一个,加入工程,又说dxtrans.h找不到,百度一下,发现了解决办法:

在#include "dxtrans.h"加入一下几行代码,并且注释掉该头文件

#define __IDxtCompositor_INTERFACE_DEFINED__
#define __IDxtAlphaSetter_INTERFACE_DEFINED__
#define __IDxtJpeg_INTERFACE_DEFINED__
#define __IDxtKey_INTERFACE_DEFINED__

#include "amstream.h"

然后顺利编译通过,F5运行,控制台顺利输出了找到的摄像头:OEM device,但是打开的是笔记本子带的摄像头,回来看代码,把OEM device这个id送进去打开,发现无法运行,设置断电,进行调试,最后停止在这个地方:

else 
{
//////////////////////////////////////////////////////////////////////////////
// 加入由 lWidth和lHeight设置的摄像头的宽和高 的功能,默认320*240
// by flymanbox @2009-01-24
//////////////////////////////////////////////////////////////////////////////
IAMStreamConfig *iconfig = NULL;
hr = m_pCameraOutput->QueryInterface(IID_IAMStreamConfig, (void**)&iconfig);   


AM_MEDIA_TYPE *pmt;
if(iconfig->GetFormat(&pmt) !=S_OK)
{
printf("GetFormat Failed ! \n");
return false;
}


// 3、考虑如果此时的的图像大小正好是 nWidth * nHeight,则就不用修改了。
if ((pmt->lSampleSize != (nWidth * nHeight * 3)) && (pmt->formattype == FORMAT_VideoInfo))
{
VIDEOINFOHEADER *phead = (VIDEOINFOHEADER*)(pmt->pbFormat);
phead->bmiHeader.biWidth = nWidth;
phead->bmiHeader.biHeight = nHeight;
if((hr = iconfig->SetFormat(pmt)) != S_OK)
{
return false;
}
}


iconfig->Release();
iconfig=NULL;
MYFREEMEDIATYPE(*pmt);
}

看了一下代码,这是设置大小的,可能是不支持大小设置,果断注释掉,继续发现程序直接退出来了,这下头大了,那就老老实实学习一些directshow的工作流程,在网上搜了一些资料,链接:http://pan.baidu.com/s/10E6f0,把这份pdf看了个大概,基本了解,继续回来看代码。下面是我对这个打开流程的一个理解:

one:

先设置一个Filter Graph Manager:hr = m_pSampleGrabber->SetMediaType(&mt);

two:

设置filter之间的数据格式,就是这句话hr = m_pSampleGrabber->SetMediaType(&mt);

three:

打开指定的id设备:BindFilter(nCamID, &m_pDeviceFilter);

for:

链接各个引脚,这个是能否打开easycap的关键,我们普通的usb摄像头只有一个输入引脚,而easycap不一样,它是集视频、音频一体的设备,那么输入设备的引脚选择就很重要了,你打开一个音频设备,却选择视频的方式,怎么可以打开?

关键代码:

CComPtr pEnum;
m_pDeviceFilter->EnumPins(&pEnum);
 hr = pEnum->Reset();
pEnum->Skip(2);//跳过非视频引脚
hr = pEnum->Next(1, &m_pCameraOutput, NULL);

我在这里跳过了两个引脚(具体几个自己多尝试一下),然后设置SetCrossBar(),顺利打开easycap摄像头。

你可能感兴趣的:(视频采集)