00 GUI介面的製作-"cvcam.h"視訊函式庫(1)

Post date: 2012/4/10 上午 09:16:40

這邊介紹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網站上下載