USB免驱摄像头采集图像【VS2012+opencv+directShow(CcameraDS)实现】

来源:互联网 发布:aso优化 app排名 编辑:程序博客网 时间:2024/05/27 20:52

在Opencv中文网站上有关于directShow和opencv结合采集图像的教程,地址: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
但是该配置比较老,本文讲述如何基于该教程在 VS2012和opencv2.4.9上进行配置和修改,完成USB摄像头的驱动。

博主的USB免驱摄像头如下:
这里写图片描述

文末有完整代码的下载地址

1.环境配置

在Opencv中文网站上有关于directShow和opencv结合采集图像的教程,地址: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

但说明中的“本文档介绍的CCameraDS类调用采集函数可直接返回IplImage,使用更方便,且集成了DirectShow,勿需安装庞大的DirectX/Platform SDK”并不靠谱,DirectShow 似乎已经开始被微软给淘汰了,最后存在是在多年前的 DirectX 9.0b 包里。

注意这里并不需要下载DirectX 9.0包,下面介绍在VS2012和opencv2.4.9下的配置过程。

1.1 配置VS2012和opencv环境

按照网上流行的配置即可,如http://www.sigvc.org/bbs/thread-529-1-1.html 。配置好之后尝试运行一个打开图片的小程序检测opencv环境是否配置成功。

1.2 配置DirectX环境

新建工程,配置好Opencv环境,随后将从Opencv中文网上下载的 CameraDS.h 和 CameraDS.cpp 文件分别添加到项目的头文件和源文件中。

VS2012旗舰版是自带了 SDK 的,在 C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include。
打开建立的VS2012项目的属性页,找到“VC++目录”,在“包含目录”里添加 (FrameworkSDKDir)Include(FrameworkSDKDir)Lib。

发现#include “qedit.h”报错,原因是现在的版本已经没有qedit.h这个头文件了,从网址:http://download.csdn.net/download/bcj296050240/9651955 中下载该文件,添加到项目的头文件中。

2. 运行

环境配置好之后,可以用 Opencv中文网 上下载的main.cpp运行,运行过程可能遇到const char* 无法转换的问题,将此处的代码去掉即可。

下面是本人编写的main函数,提供了USB相机的打开、监视、图像捕获功能。

2.1 查看系统的所有摄像头状态(initAllCameras函数)

参数是 CCameraDS 类的对象。该函数获取相机的数目并且显示相机名称。从输出中我们可以找到USB相机的编号,一般情况下编号为1。

//获取当前可用的摄像头并打开USB摄像头int initAllCameras(CCameraDS &m_CamDS){    //仅仅获取摄像头数目    int m_iCamCount = CCameraDS::CameraCount();    printf("There are %d cameras.\n", m_iCamCount);    if(m_iCamCount == 0)    {        return -1;    }    //获取所有摄像头的名称    for(int i = 0; i < m_iCamCount; i++)    {        char szCamName[1024];        int retval = m_CamDS.CameraName(i, szCamName, sizeof(szCamName));        if(retval >0)        {            printf("Camera #%d's Name is '%s'.\n", i, szCamName);        }        else        {            printf("Can not get Camera #%d's name.\n", i);        }    }    return m_iCamCount;}

运行结果如下所示:

There are 3 cameras.Camera #0's Name is 'Lenovo EasyCamera'.Camera #1's Name is '3D Camera'.Camera #2's Name is 'Basler GenICam Source'.

从运行结果中可以看出,使用的3D相机的编号为1。

2.2 打开USB相机(openUsbCam函数)

函数有四个参数,第一个参数为CcameraDS类的对象,camNum设置为1,表明现在要打开的USB相机,而不是电脑自带相机。camWidth和camHeight根据自己所使用相机的情况进行设置,设置为图像的宽度和高度。

代码如下:

// 打开 USB 相机  !! 在调用 camDisplay 和 camCapPic 之前必须调用该函数// camNum = 1;       // 摄像头编号为1,表示当前要使用的是 USB 摄像头// camWidth = 2560;  // 图片宽度// camHeight = 720;  // 图片高度int openUsbCam(CCameraDS &m_CamDS, const int camNum=1, const int camWidth=2560, const int camHeight = 720){    // 获取当前可用的相机个数    // 在所有的相机中,一般编号为 0 的为电脑自带摄像头,编号为 1 的为要使用的 USB 摄像头    int m_iCamCount = initAllCameras(m_CamDS);    if(m_iCamCount == -1){        cout<<"没有可用的摄像头! 退出.."<<endl;        return -1;    }    Mat pFrame;    // 打开相机并拍摄一幅图片    if((!m_CamDS.OpenCamera(camNum, false, camWidth, camHeight)) || (m_CamDS.QueryFrame() == NULL)){        cout<<"# "<<camNum<<" 号相机无法打开,程序退出..";        return -2;    }    return 1;}

2.3 实时显示(camDisplay函数)

函数有两个参数,第一个参数是CcameraDS类的对象,第二个参数是时间,默认为每隔20ms拍摄一幅图片。
在显示的过程中,按任意键可以退出。可以根据自己的要求进行修改,比如修改成按任意键保存当前图片。

// 显示相机视场的内容  每隔20毫秒显示一帧int camDisplay(CCameraDS &m_CamDS, const int t=20){    Mat pFrame;    while(1)    {        //获取一帧        pFrame = Mat(m_CamDS.QueryFrame());        //显示        imshow("Camera", pFrame);        //延迟,如果有键按下,退出        if(cv::waitKey(t) != -1)            break;    }    //m_CamDS.CloseCamera(); //可不调用此函数,CCameraDS析构时会自动关闭摄像头    cv::destroyAllWindows();    return 0;}

2.4 保存图片(camCapPic函数)

实现获取一帧图片显示并保存,保存路径有filename设置。

// 抓取图片 并保存到 filename 路径中int camCapPic(CCameraDS &m_CamDS, string filename="USBcam.jpg"){    Mat pFrame;    //获取一帧    pFrame = Mat(m_CamDS.QueryFrame());    //显示    imshow("抓取图片", pFrame);    waitKey(1000);    destroyAllWindows();    //抓取图片保存    imwrite(filename, pFrame);    //m_CamDS.CloseCamera(); //可不调用此函数,CCameraDS析构时会自动关闭摄像头    return 0;}

2.5 主函数

调用顺序为,首先实例化对象,然后打开摄像头(调用openUsbCam函数)。

打开摄像头后,可以根据自己的需要调用不同的函数,如果要实时显示,则调用camDisplay函数,如果要抓取图像保存,则调用camCapPic函数。

注意在调用这些函数时,使用的是同一个CCameraDS的对象。

注意在函数中不要轻易调用CloseCamera()函数,该函数会释放打开的USB摄像头。如果释放后要重新捕获图片,需要再次调用openUsbCam函数。

int main(){    CCameraDS m_CamDS;     // 打开USB摄像头    openUsbCam(m_CamDS);    // 1.0 显示相机内容    cout<<endl<<"显示相机内容..."<<endl;    camDisplay(m_CamDS);    cout<<"显示相机内容 退出..."<<endl<<endl;    // 2.0 抓取图片保存    string filename = "USBcam.jpg";    cout<<"抓取图片保存..."<<endl;    camCapPic(m_CamDS, filename);    cout<<"抓取图片保存 退出... 文件路径 "<<filename<<endl;    cout<<endl<<"结束..."<<endl;    getchar();    return 0;}

完整代码下载地址:

http://download.csdn.net/detail/bcj296050240/9652088

0 0
原创粉丝点击