標籤:des io ar color os 使用 sp for on
鄙人今日嘗試使用openCV調用網路攝影機做圖片中圓的圓心位置檢測時,意外發現程式能成功調用筆記的整合網路攝影機,但卻無法調用外接的USB網路攝影機。(使用的為OpenCV1.0 + VC6.0)
使用程式如下:
#include"cv.h"
#include"highgui.h"
#include"cvcam.h"
#include"iostream"
using namespace std;
int main(int argc,char* argv[])
{
CvCapture* cap;
cap=cvCaptureFromCAM(0);
//cap=cvCreateCameraCapture(1); //使用該函數與上面函數效果一樣
if(!cap)
{
cout<<"create camera capture error"<<endl;
system("pause");
exit(-1);
}
cvNamedWindow("example",1);
IplImage* img;
//sleep(2000);
while(1)
{
img=cvQueryFrame(cap);//捕獲相機的視訊框架,並進行解碼操作
//img=cvLoadImage("F:\\360雲端硬碟\\圖片\\20083281447418_2.jpg"); //直接讀取圖片
if(!img)
break;
if(img->origin==IPL_ORIGIN_TL)//如果圖片原點在左上方,將其沿X軸翻轉,使左下角
{
cvFlip(img,img);
}
cvShowImage("example",img);
cvWaitKey(30);
IplImage*gray =cvCreateImage( cvGetSize(img),8,1);
CvMemStorage*storage = cvCreateMemStorage(0);
cvCvtColor(img,gray,CV_BGR2GRAY);
cvSmooth(gray,gray,CV_GAUSSIAN,5,15);
CvSeq*circles = cvHoughCircles(gray,storage,CV_HOUGH_GRADIENT,2,gray->height/4,200,100);
int i;
for (i=0; i< circles->total; i++)
{
float*p = (float*)cvGetSeqElem(circles,i);
cvCircle(img, cvPoint(cvRound(p[0]),cvRound(p[1])),3, CV_RGB(0,255,0), -1, 8, 0);
cvCircle(img, cvPoint(cvRound(p[0]),cvRound(p[1])),cvRound(p[2]), CV_RGB(255,0,0), 3, 8, 0);
cout<<"圓心座標x="<<cvRound(p[0])<<endl<<"圓心座標y= "<<cvRound(p[1])<<endl;
cout<<"半徑="<<cvRound(p[2])<<endl;
}
cout<<"圓數量= "<<circles->total<<endl;
cvWaitKey(10);
}
cvReleaseCapture(&cap);
cvDestroyAllWindows();
cvReleaseImage(&img);
return 0;
}
關於程式中函數cap=cvCaptureFromCAM(0) 的參數,有人認為設定為0時調用的是整合網路攝影機,設定為1的時候調用的是USB網路攝影機,只有一個網路攝影機時則設定為-1;
但在本機上實驗時發現,設定為0和-1時均調用的是整合網路攝影機,而設定為1時則顯示調用錯誤“create camera capture error”;
目前解決辦法主要有兩條
1、採用VS2010 + OpenCV2.3.1的配置顯示可以調用USB網路攝影機,成功時出現Support SSE4.3的字串。
另外網上有人提出可能是使用的是win7的原因不支援OpenCV1.0,改為採用XP系統能解決該問題。但本人在xp系統上嘗試卻是不成功的,說明系統相容性並不是問題的根本。 分析更有可能是之前openCV低版本無法支撐高版本的USB網路攝影機。
2、採用DirectShow可以直接在win7 + VC6.0 + OpenCV1.0上顯示USB網路攝影機,
使用程式如下:
#include "cxcore.h"
#include "cvcam.h"
#include "windows.h"
#include "cv.h"
#include "highgui.h"
#include "iostream"
using namespace std;
IplImage* image;
void callback(IplImage* image);
int main()
{
int ncams = cvcamGetCamerasCount( );//返回可以訪問的網路攝影機數目
int width=640;
int height=480;
HWND MyWin;
// 設定系統屬性
cvcamSetProperty(0, CVCAM_PROP_ENABLE, CVCAMTRUE); //Enable視訊
//0:欲設定屬性的網路攝影機序號; 第二個參數是屬性名稱字;
//第三個參數是指向設定值的指標
cvcamSetProperty(0, CVCAM_PROP_RENDER, CVCAMTRUE); //啟用視訊
// MyWin 是視窗 HWND 的類型
MyWin = (HWND) cvGetWindowHandle("cvcam window");
cvcamSetProperty(0, CVCAM_PROP_WINDOW, &MyWin); // Selects a window
cvcamSetProperty(0,CVCAM_RNDWIDTH,&width);
cvcamSetProperty(0,CVCAM_RNDHEIGHT,&height);
//video rendering
//回呼函數將處理每一幀
cvcamSetProperty(0, CVCAM_PROP_CALLBACK, callback);
cvcamInit( );
cvcamStart( );
IplImage*gray =cvCreateImage( cvGetSize(image),8,1);
CvMemStorage*storage = cvCreateMemStorage(0);
cvCvtColor(image,gray,CV_BGR2GRAY);
cvSmooth(gray,gray,CV_GAUSSIAN,5,15);
CvSeq*circles = cvHoughCircles(gray,storage,CV_HOUGH_GRADIENT,2,gray->height/4,200,100);
int i;
for (i=0; i< circles->total; i++)
{
float*p = (float*)cvGetSeqElem(circles,i);
cvCircle(image, cvPoint(cvRound(p[0]),cvRound(p[1])),3, CV_RGB(0,255,0), -1, 8, 0);
cvCircle(image, cvPoint(cvRound(p[0]),cvRound(p[1])),cvRound(p[2]), CV_RGB(255,0,0), 3, 8, 0);
cout<<"圓心座標x="<<cvRound(p[0])<<endl<<"圓心座標y= "<<cvRound(p[1])<<endl;
cout<<"半徑="<<cvRound(p[2])<<endl;
}
cout<<"圓數量= "<<circles->total<<endl;
cvWaitKey(100);
// 現在程式開始工作
cvWaitKey(0);
cvcamStop( );
cvcamExit( );
return 0;
}
// 回呼函數
void callback(IplImage* image)
{
cvcamPause();
cvcamGetProperty(0,"raw_image",&image);
cvcamResume();
}
但是上段程式中網路攝影機每幀映像的地址還不清楚是不是*image,故目前仍然沒有將圓心位置檢測的程式段加入進去。
DirectShow是微軟公司在ActiveMovie和Video for Windows的基礎上推出的新一代基於COM(Component Object Model)的流ApsaraVideo for Media Processing的開發包,與DirectX開發包一起發布。而OpenCV是一個電腦視覺的處理庫,被廣泛應用到各種電腦視覺的研究和應用當中。OpenCV可以利用DirectShow來採集網路攝影機視頻,這比採用OpenCV裡的採集視頻資料函數要好用。這是我個人的看法。
win7系統下使用openCV調用網路攝影機問題