1. 程式人生 > >OpenCV+VideoInput 捕捉攝像頭+人臉檢測

OpenCV+VideoInput 捕捉攝像頭+人臉檢測

【概述】

筆者用的環境是筆記本Win7+VS2010+OpenCV2.2    

當利用OpenCV的cvCreateCameraCapture(0)、cvQueryFrame( pCapture )函式捕捉攝像頭資料時,老是捕捉不到,顯示黑視窗。

在網上搜了搜,發現筆記本內建攝像頭無法簡單得使用cvQueryFrame()來採集影象,它採集的是VFM格式的視訊,一般USB外接攝像頭都支援這種格式,而筆記本的攝像頭驅動都只相容Directshow,那麼如何用Directshow採集視訊呢?具體參見:使用DirectShow採集影象

上述方法配置起來比較複雜!!!

筆者後來找著了一簡單的方法。

原來新版的OpenCV(OpenCV 2.0及以上版本)提供了第三方的VideoInput

庫,功能強大、效率高效。該庫就在OpenCV開發包裡頭。

【使用方法】

新增函式庫   C:\OpenCV2.2\3rdparty\include

新增靜態連結庫    C:\OpenCV2.2\3rdparty\lib 包含標頭檔案 #include <videoInput.h>

如果編譯時遇到如下錯誤:

"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 <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>

#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=\"<cascade_path>\" [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 );
}

【執行截圖】