GUI接口的制作-"cvcam.h"视频函数库(1)

这边介绍OpenCV另一个跟视频有关的函数库"cvcam.h",它也包括AVI文件的存取跟视频播放,不同的是,它具有控制视频相关功能的子程序

cvcamInit()
cvcamStart()
cvcamPause()
cvcamResume()
cvcamStop()
cvcamExit()

及两个配置视频相关的GUI接口.而且它是支持HWND,也就是它可以支持其他窗口接口程序设计,直接整合在它们的Form里,如Visual C++或C++ Builder窗口接口程序设计,只要给它窗口接口的ID,就可以整合操作,且一次可以打开多个视频.

cvcam.h的视频使用
#include <cvcam.h>
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <windows.h>


void CaptureCallback(IplImage *frame1);

int main()
{
    HWND CaptureWindow=0;
    int width=640;
    int height=480;
    int CamerasCount= cvcamGetCamerasCount();
    printf("视频装置总数量: %d\n",CamerasCount);

    CameraDescription CameraDescription1;
    cvcamSetProperty(0,CVCAM_PROP_ENABLE,CVCAMTRUE);
    cvcamSetProperty(0,CVCAM_PROP_RENDER,CVCAMTRUE);
    cvcamSetProperty(0,CVCAM_PROP_WINDOW,&CaptureWindow);
    cvcamSetProperty(0,CVCAM_PROP_CALLBACK,(void *)&CaptureCallback);
    cvcamSetProperty(0,CVCAM_RNDWIDTH,&width);
    cvcamSetProperty(0,CVCAM_RNDHEIGHT,&height);

    cvcamGetProperty(0,CVCAM_VIDEOFORMAT,NULL);
    cvcamGetProperty(0,CVCAM_CAMERAPROPS,NULL);
    cvcamGetProperty(0,CVCAM_DESCRIPTION,&CameraDescription1);

    cvcamInit();
    cvcamStart();

    printf("===============================\n");
    printf("选择编号0的装置\n");
    printf("装置名称:\n%d\n",CameraDescription1.device);
    printf("装置描述:\n%s\n",CameraDescription1.DeviceDescription);
    printf("装置信道数:\n%d\n",CameraDescription1.channel);
    printf("装置信道描述:\n%s\n",CameraDescription1.ChannelDescription);
    printf("最大宽上限:\n%d\n",CameraDescription1.maxwidth);
    printf("最大高上限:\n%d\n",CameraDescription1.maxheight);
    printf("最小宽上限:\n%d\n",CameraDescription1.minwidth);
    printf("最小高上限:\n%d\n",CameraDescription1.minheight);

    cvWaitKey(0);
    cvcamStop();
    cvcamExit();

}
void CaptureCallback(IplImage *frame1)
{
    int i,j;
    for(i=0;i<frame1->height;i+=20)
    {
        for(j=0;j<frame1->widthStep;j+=frame1->nChannels)
        {
            frame1->imageData[i*j] =0;
            frame1->imageData[i*j+1]=0;
            frame1->imageData[i*j+2]=255;
        }
    }
}

执行结果:
(1)Frame格式修改

(2)视频装置配置

(3)播放


上 面的程序代码,属于cvcam重新打开的win32窗口,而非OpenCV自己的窗口程序,所以不支持cvSetMouseCallback()及 cvCreateTrackbar()的呼叫,因此,不能制作鼠标及Trackbar事件,不过它可以用键盘阻断,以及他程序内部自身的呼 叫,CaptureCallback()就是他的呼叫方法,,它可以藉由HWND去嵌入窗口程序(Visual C++,C++ Builder)做更强大的应用.上面的程序代码给了一个HWND为NULL的窗口代号,让她重新打开了一个非Opencv的窗口,接着侦测视频装置数量 cvcamGetCamerasCount(),注意,这是程序代码必要的,如果不做侦测就找不到视频装置,接着是视频描述数据结 构,cvcamSetProperty()是视频属性设立,第一个功能CVCAM_PROP_ENABLE是将视频设成 Enable,CVCAM_PROP_RENDER则是交付视频,CVCAM_PROP_WINDOW则是选定视频打开窗 口,CVCAM_PROP_CALLBACK就是视频的呼叫,可以自行定义子程序来修改视频显示画面的内容,CVCAM_RNDWIDTH跟 CVCAM_RNDHEIGHT可以自由修改画面的宽跟高.接着是用cvcamGetProperty()取得信息,CVCAM_VIDEOFORMAT 及CVCAM_CAMERAPROPS为打开GUI接口视频功能配置,CVCAM_DESCRIPTION是取得视频详细描述.这边显示的执行结果是变成 红色直线条,而CameraDescription数据结构获取的讯息有些也不一定正确.

下面这一段程序代码就是要做到视频的选择,以及 两台视频的功能配置,使用的是cvcamSelectCamera()的函数,"cvcam.h"具有一个窗口接口一次可以自己选择两台想要用的视频功 能,以及二择一的视频装置,但是对于不同厂商的视频装置会造成无法同步播放的问题,可以用视频仿真器的软件解决,以下为多台视频操控程序代码

cvcam.h的视频二择一,或是两台操作
#include <cvcam.h>
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <windows.h>


void CaptureCallback(IplImage *frame1);
void StereoCallback(IplImage frame1,IplImage *frame2);

int main()
{
    HWND CaptureWindow1=0;
    HWND CaptureWindow2=0;

    int *CameraNumber;
    int nSelected = cvcamSelectCamera(&CameraNumber);
    if(nSelected==1)
    {
        cvcamSetProperty(CameraNumber[0], CVCAM_PROP_ENABLE, CVCAMTRUE);
        cvcamSetProperty(CameraNumber[0], CVCAM_PROP_RENDER, CVCAMTRUE);
        cvcamSetProperty(CameraNumber[0], CVCAM_STEREO_CALLBACK,(void *)&CaptureCallback);
        cvcamSetProperty(CameraNumber[0], CVCAM_PROP_WINDOW, &CaptureWindow1);

    }
    else if(nSelected==2)
    {
        cvNamedWindow("cvcam1 Window",1);
        CaptureWindow1=(HWND)cvGetWindowHandle("cvcam1 Window");
        cvcamSetProperty(CameraNumber[0], CVCAM_PROP_ENABLE, CVCAMTRUE);
        cvcamSetProperty(CameraNumber[0], CVCAM_PROP_RENDER, CVCAMTRUE);
        cvcamSetProperty(CameraNumber[0], CVCAM_STEREO_CALLBACK,(void *)&StereoCallback);
        cvcamSetProperty(CameraNumber[0], CVCAM_PROP_WINDOW, &CaptureWindow1);

        cvNamedWindow("cvcam2 Window",1);
        CaptureWindow2=(HWND)cvGetWindowHandle("cvcam2 Window");
        cvcamSetProperty(CameraNumber[1], CVCAM_PROP_ENABLE, CVCAMTRUE);
        cvcamSetProperty(CameraNumber[1], CVCAM_PROP_RENDER, CVCAMTRUE);
        cvcamSetProperty(CameraNumber[1], CVCAM_STEREO_CALLBACK,(void *)&StereoCallback);
        cvcamSetProperty(CameraNumber[1], CVCAM_PROP_WINDOW, &CaptureWindow2);

    }

    cvcamInit();
    cvcamStart();

    cvWaitKey(0);

    cvcamStop();
    cvcamExit();
    free(CameraNumber);
    cvDestroyWindow("cvcam1 Window");
    cvDestroyWindow("cvcam2 Window");
}
void CaptureCallback(IplImage *frame1)
{}
void StereoCallback(IplImage frame1,IplImage *frame2)
{}

执行结果:
(1)选择想要用的装置


(2)选择e2eSoft VCam出现的挂载画面


(2)装置播放


cvcamSelectCamera() 这个函数会自动侦测视频装置的数量,并且打开一个GUI接口,让使用者可以选定想使用的装置,因而替换了cvcamGetCamerasCount()的 功能,而他最多可以选定两台装置同步播放,当cvcamSelectCamera()的回传值nSelected==1时,表示只选定一台装置,被选定的 装置代号被放在CameraNumber[0]里面,而当nSelected==2时,表示选定了两台装置,装置代号分别被放在 CameraNumber[0]及CameraNumber[1]里,而要做到同步播放,那就一定要用cvcamSetProperty()里面 CVCAM_STEREO_CALLBACK的参数啦,这个参数只能处理两台视频同步播放,并且可以在StereoCallback()这个函数处理两台 视频播放的画面内容,也就是写算法进去一次处理两台画面,也是因为这个函数的问题,造成了不同厂商的视频装置会互冲,会出现的问题是"找不到中介筛选器的 组合,所以无法连接。",这个问题就只能用视频仿真器来解决啦,把其中一台会冲到的装置挂载到视频仿真器上面,视频仿真器的下载网址

http://www.e2esoft.cn/vcam/index.asp

VCam


要注意的是,被挂载的装置会造成OpenCV的任何一个视频函数都无法播放,如果是做单一的视频播放,而该装置又被挂载,则无法使用该装置,而只能使用视频仿真器所提供的虚拟装置名称.

cvcamGetCamerasCount()
侦测所有视频装置数量,是一定要做的第一步.
int cvcamGetCamerasCount()

cvcamSelectCamera()
打 开选择视频装置的GUI界面,内部具有侦测视频装置数量cvcamGetCamerasCount()的功能,cvcamSelectCamera()的 回传值为被选定的视频数,这边只能选定两个装置,因此回传值不是0就是1,2,而它的第一个参数为被选定的视频代号数组,数组的最大长度为2,分别放入的 是第一视频装置代号跟第二视频装置代号.
cvcamSelectCamera(被选定的int *类型视频数组)

cvcamSetProperty()
设立视频装置属性,这边他的参数方式是用字串的形式去设计,如下定义

static const char CVCAM_PROP_ENABLE[] = "enable";    Enable视频
static const char CVCAM_PROP_RENDER[] = "render";    启用视频
static const char CVCAM_PROP_WINDOW[] = "window";    选定画面在哪个窗口打开
static const char CVCAM_PROP_CALLBACK[] = "callback";  配置Capture方法呼叫
static const char CVCAM_STEREO_CALLBACK[] = "stereo_callback";  配置两个装置同步播放及StereoCallback函数
static const char CVCAM_STEREO3_CALLBACK[] = "stereo3_callback";  配置三个装置同步播放及Stereo3Callback
static const char CVCAM_STEREO4_CALLBACK[] = "stereo4_callback";  配置四个装置同步播放及Stereo4Callback
static const char CVCAM_RNDWIDTH[] = "rendering_width";  修改画面宽度
static const char CVCAM_RNDHEIGHT[] = "rendering_height";  修改画面高度

因此,它的参数是字串,而非之前的用代号表示,CVCAM_PROP_WINDOW需要给它HWND类型,CVCAM_PROP_CALLBACK则需要给它自行定义的子程序名称,CVCAMTRUE则是用代号表示如下

#define CVCAMTRUE (void*)1
#define CVCAMFALSE (void*)0

cvcamSetProperty(装置代号,参数或字串,属性配置参数);

cvcamGetProperty()
取得视频装置属性,用法跟上面类似,可取得的参数为

static const char CVCAM_VIDEOFORMAT[] = "video_pp";    GUI接口的视频格式配置
static const char CVCAM_CAMERAPROPS[] = "camera_pp";    GUI接口的视频装置配置
static const char CVCAM_DESCRIPTION[] = "description";    详细信息描述

CVCAM_DESCRIPTION要用CameraDescription数据结构接.
cvcamSetProperty(装置代号,参数或字串,属性配置参数);

cvcamInit();
初始化视频

cvcamStart();
启动视频

cvcamStop();
停止视频

cvcamExit();
关闭视频

CaptureCallback()
修改播放Frame的呼叫,接收的格式是IplImage数据结构.
CaptureCallback(IplImage *frame1);

StereoCallback()
修改两个视频装置Frame播放的呼叫,接收的格式是IplImage数据结构.
CaptureCallback(IplImage *frame1,IplImage *frame2);

--
附注:Opencv1.0 only,如果opencv 1.1想要使用的话,可以到sourceforge的opencv网站上下载