【概述】
笔者用的环境是笔记本Win7+VS2010+OpenCV2.2
当利用OpenCV的cvCreateCameraCapture(0)、cvQueryFrame( pCapture )函数捕捉摄像头数据时,老是捕捉不到,显示黑窗口。
在网上搜了搜,发现笔记本内置摄像头无法简单得使用cvQueryFrame()来采集图像,它采集的是VFM格式的视频,一般USB外置摄像头都支持这种格式,而笔记本的摄像头驱动都只兼容Directshow,那么如何用Directshow采集视频呢?具体参见:使用DirectShow采集图像
上述方法配置起来比较复杂!!!
笔者后来找着了一简单的方法。
原来新版的OpenCV(OpenCV 2.0及以上版本)提供了第三方的VideoInput库,功能强大、效率高效。该库就在OpenCV开发包里头。
GitHub地址:https://github.com/ofTheo/videoInput
貌似官网:http://www.muonics.net/school/spring05/videoInput/
【使用方法】
添加函数库 C:\OpenCV2.2\3rdparty\include
如果编译时遇到如下错误:
"fatal error LNK1104: cannot open file 'atlthunk.lib'"
请在文件的开头加入如下语句:
#pragma comment(linker, "/NODEFAULTLIB:atlthunk.lib")
示例代码:
int main(int argc, char ** argv)
{
IplImage *frame=cvCreateImage(cvSize(320, 240), IPL_DEPTH_8U, 3);
videoInput vi;//创建视频捕获对象
vi.setupDevice(0, 320, 240);//配置设备
vi.showSettingsWindow(0);//该语句可以显示视频设置窗口,可以去掉
while(1)
{
if(vi.isFrameNew(0))
{
vi.getPixels(0, (unsigned char *)frame->imageData, false, true); //获取一帧
//cvFlip(pRgb,NULL,1); //水平翻转画面
char c=cvWaitKey(1);
if(c == 27)
break; //按ESC退出
cvNamedWindow("Video", CV_WINDOW_AUTOSIZE);
cvShowImage("Video", frame);
}
}
cvReleaseImage( &frame );
return 0;
}
#include "videoInput.h"
#include "stdio.h"
#include "cv.h"
#include "highgui.h"
#pragma comment(linker, "/NODEFAULTLIB:atlthunk.lib")
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef _EiC
#define WIN32
#endif
static CvMemStorage* storage = 0;
static CvHaarClassifierCascade* cascade = 0;
void detect_and_draw( IplImage* image );
const char* cascade_name = "C:/OpenCV2.2/data/haarcascades/haarcascade_frontalface_alt.xml";
#define WIDTH 320
#define HEIGHT 240
int main(int argc, char ** argv)
{
IplImage *frame=cvCreateImage(cvSize(WIDTH, HEIGHT), IPL_DEPTH_8U, 3);
videoInput vi;//创建视频捕获对象
vi.setupDevice(0, WIDTH, HEIGHT);//配置设备
vi.showSettingsWindow(0);//该语句可以显示视频设置窗口,可以去掉
cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
if( !cascade )
{
fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
fprintf( stderr,
"Usage: facedetect --cascade=\"\" [filename|camera_index]\n" );
return -1;
}
storage = cvCreateMemStorage(0);
while(1)
{
if(vi.isFrameNew(0))
{
vi.getPixels(0, (unsigned char *)frame->imageData, false, true); //获取一帧
if( frame )
{
detect_and_draw( frame );
}
char c=cvWaitKey(1);
if(c == 27)
break; //按ESC退出
cvNamedWindow("Video", CV_WINDOW_AUTOSIZE);
cvShowImage("Video", frame);
}
}
cvReleaseImage( &frame );
return 0;
}
void detect_and_draw( IplImage* img )
{
static CvScalar colors[] =
{
{{0,0,255}},
{{0,128,255}},
{{0,255,255}},
{{0,255,0}},
{{255,128,0}},
{{255,255,0}},
{{255,0,0}},
{{255,0,255}}
};
double scale = 1.3;
IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
cvRound (img->height/scale)),
8, 1 );
int i;
cvCvtColor( img, gray, CV_BGR2GRAY );
cvResize( gray, small_img, CV_INTER_LINEAR );
cvEqualizeHist( small_img, small_img );
cvClearMemStorage( storage );
if( cascade )
{
double t = (double)cvGetTickCount();
CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/,
cvSize(30, 30) );
t = (double)cvGetTickCount() - t;
printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
for( i = 0; i < (faces ? faces->total : 0); i++ )
{
CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
CvPoint center;
int radius;
center.x = cvRound((r->x + r->width*0.5)*scale);
center.y = cvRound((r->y + r->height*0.5)*scale);
radius = cvRound((r->width + r->height)*0.25*scale);
cvCircle( img, center, radius, colors[i%8], 3, 8, 0 );
}
}
cvNamedWindow("Video", 0);
cvResizeWindow("Video", WIDTH, HEIGHT);
cvShowImage( "Video", img );
cvReleaseImage( &gray );
cvReleaseImage( &small_img );
}