opencv--读取摄像头识别人脸并跟踪

VS上的程序

 
   

#include "stdafx.h" #include "cv.h" #include "highgui.h" #include "windows.h" #include #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 = "haarcascade_frontalface_alt.xml"; /* "haarcascade_profileface.xml";*/ HANDLE hCom; //全局变量,串口句柄 //中心 int CenterPoint=0; int DivDat; bool ComOpen=false; int Angle=0; int DevCnt=0; int GetKey; bool OpenCom() { COMMTIMEOUTS TimeOuts; hCom = CreateFile(TEXT("COM3"),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); if(hCom == INVALID_HANDLE_VALUE) { //AfxMessageBox("打开COM失败!"); return FALSE; } SetupComm(hCom,1024,1024); //输入缓冲区和输出缓冲区的大小都是1024 ////设定读超时 //TimeOuts.ReadIntervalTimeout = 1000; //TimeOuts.ReadTotalTimeoutMultiplier = 500; //TimeOuts.ReadTotalTimeoutConstant = 5000; ////设定写超时 //TimeOuts.WriteTotalTimeoutMultiplier = 500; //TimeOuts.WriteTotalTimeoutConstant = 2000; //SetCommTimeouts(hCom, &TimeOuts); //设置超时 DCB dcb; GetCommState(hCom, &dcb); dcb.BaudRate = 9600; //波特率为9600 dcb.ByteSize = 8; //每个字节有8位 dcb.Parity = NOPARITY; //无奇偶校验位 dcb.StopBits = TWOSTOPBITS; //两个停止位 SetCommState(hCom, &dcb); PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR); printf("Com Open OK..."); return TRUE; } void CloseCom() { CloseHandle(hCom); } void ComSend(unsigned char dir,unsigned char dat) { unsigned char lpOutBuffer[4]; memset(lpOutBuffer,'\0', 4); //前7个字节先清零 if(dat>255) dat=255; lpOutBuffer[0] = dir; //发送缓冲区的第1个字节为DC1 lpOutBuffer[1] = dat; //第2个字节为字符0(30H) lpOutBuffer[2] = '\r'; //第3个字节为字符0(30H) lpOutBuffer[3] = '\n'; // 第4个字节为字符1(31H) DWORD dwBytesWrite = 4; COMSTAT ComStat; DWORD dwErrorFlags; BOOL bWriteStat; ClearCommError(hCom,&dwErrorFlags,&ComStat); bWriteStat = WriteFile(hCom, lpOutBuffer, dwBytesWrite, &dwBytesWrite, NULL); PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); if (!bWriteStat) { printf("Send Fail...\r\n"); return ; } } void StepMotor(int step) { if(step>128) step=128; else if(step<-128) step=-128; step=step/10; if(ComOpen) { Angle = Angle + step; if(Angle>128) { ComSend(0,128); Angle=0; printf( "Send Angle>128\r\n"); return; } else if(Angle<-128) { ComSend(1,128); Angle=0; printf( "Send Angle<-128\r\n"); return; } if(step>0) { ComSend(1,step); } else { ComSend(0,0-step); } printf( "Send DivDat= %d\n",step); } } int main( int argc, char** argv ) { // HWND MyWin; ComOpen=OpenCom(); cascade_name = "haarcascade_frontalface_alt2.xml"; cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 ); CvCapture* pCap = cvCreateCameraCapture( 1 );//这里-1也可以,不过我的电脑装的有CyberLink YouCam软件, //OpenCV会默认调用该摄像头,而不调用系统的驱动 //IplImage *camframe = NULL; if (cvCreateCameraCapture == NULL) { return(0); } //cvNamedWindow("Camera",CV_WINDOW_FULLSCREEN); /*while ((camframe = cvQueryFrame(pCap)) != 0 && cvWaitKey(20) != 27) { camframe = cvQueryFrame(pCap); cvShowImage("Camera", camframe); } */ //cvReleaseCapture(&pCap); //cvDestroyWindow("Camera"); if( !cascade ) { fprintf( stderr, "ERROR: Could not load classifier cascade\n" ); return -1; } storage = cvCreateMemStorage(0); // cvNamedWindow( "result", 1 ); // // const char* filename = "lena.jpg"; // IplImage* image = cvLoadImage( filename, 1 ); // if( image ) // { // detect_and_draw( image ); // cvWaitKey(0); // cvReleaseImage( &image ); // } // cvDestroyWindow("result"); //return 0; //======================================================== // CvCapture 是一个结构体,用来保存图像捕获所需要的信息。 // opencv提供两种方式从外部捕获图像,一种是从摄像头中,一种 // 是通过解码视频得到图像。两种方式都必须从第一帧开始一帧一帧 // 的按顺序获取,因此每获取一帧后都要保存相应的状态和参数。 // 比如从视频文件中获取,需要保存视频文件的文件名,相应的****** // 类型,下一次如果要获取将需要解码哪一帧等。 这些信息都保存在 // CvCapture结构中,每获取一帧后,这些信息都将被更新,获取下一帧 // 需要将新信息传给获取的api接口 //======================================================= //CvCapture* capture = 0; //=========================================================== // IplImage 是结构体类型,用来保存一帧图像的信息,也就是一帧 // 图像的所有像素值构成的一个矩阵 //=========================================================== IplImage *frame, *frame_copy = 0; // 创建一个窗口,用“result”作为窗口的标识符 cvNamedWindow("Camera", 1 ); // ========================================== // 初始化一个视频捕获操作。 // 告诉底层的捕获api我想从 Capture1.avi中捕获图片, // 底层api将检测并选择相应的******并做好准备工作 //============================================== //capture = cvCaptureFromFile("hello.avi"); frame = cvQueryFrame(pCap); if(frame != 0) { CenterPoint=frame->width/2; } else return 0; while ((frame = cvQueryFrame(pCap)) != 0 ) { frame = cvQueryFrame(pCap); detect_and_draw( frame ); //cvShowImage("Camera", frame); // 如果你敲了键盘,就退出程序,否则继续捕获下一帧 GetKey = cvWaitKey( 10 ); if( GetKey == 13 )//回车键退出 break; } cvReleaseCapture(&pCap); cvDestroyWindow("Camera"); return 0; // // 如果 初始化失败,那么capture为空指针,程序停止, // // 否则进入捕获循环 // if( capture ) // { // if( cvGrabFrame( capture )) // frame = cvRetrieveFrame( capture ); //// 如果获取缓存或转换失败,则退出循环 //if( frame ) //{ // CenterPoint=frame->width/2; //} // //// 捕获循环 // for(;;) // { // // 调用cvGrabFrame,让底层api解码一帧图像 // // 如果解码失败,就退出循环 // // 如果成功,解码的图像保存在底层api的缓存中 // if( !cvGrabFrame( capture )) // break; // // // 将解码得到图像信息从缓存中转换成IplImage格式放在frame中 // frame = cvRetrieveFrame( capture ); // // // 如果获取缓存或转换失败,则退出循环 // if( !frame ) // break; // detect_and_draw( frame ); // // // 将frame中的图像信息在窗口result中显示 // // detect_and_draw( frame ); // cvShowImage( "source", frame ); // // // 暂停一会儿,让你看一下图像 // //Sleep(10); // // // 如果你敲了键盘,就退出程序,否则继续捕获下一帧 // if( cvWaitKey( 10 ) >= 0 ) // break; // } // // // 退出程序之前要清理一下堆栈中的内存,免得内存泄露 // //cvReleaseImage( &frame );注意不需要这句,因为frame是从视频中捕获的,没有单独分配内存,无需释放,当capture 释放的时候frame自然就释放了。 // // // 退出之前结束底层api的捕获操作,免得它们占着茅坑不拉屎 // // 比如会使得别的程序无法访问已经被它们打开的文件 // cvReleaseCapture( &capture ); // //} // cvDestroyWindow("source"); // //cvDestroyWindow("result"); // return 0; } void detect_and_draw(IplImage* img ) { double scale=1.2; 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}} };//Just some pretty colors to draw with DevCnt++; if(DevCnt>5) DevCnt=0; //Image Preparation // 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); cvCvtColor(img,gray, CV_BGR2GRAY); cvResize(gray, small_img, CV_INTER_LINEAR); cvEqualizeHist(small_img,small_img); //直方图均衡 //Detect objects if any // cvClearMemStorage(storage); double t = (double)cvGetTickCount(); CvSeq* objects = cvHaarDetectObjects(small_img,cascade,storage,1.1,2,0,cvSize(30,30)); t = (double)cvGetTickCount() - t; printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) ); //Loop through found objects and draw boxes around them for(int i=0;i<(objects? objects->total:0);++i) { CvRect* r=(CvRect*)cvGetSeqElem(objects,i); cvRectangle(img, cvPoint(r->x*scale,r->y*scale), cvPoint((r->x+r->width)*scale,(r->y+r->height)*scale), colors[i%8]); //获取中心点 DivDat=(r->x*scale+r->width*scale/2-CenterPoint)*128/320; if((i==0)) StepMotor(DivDat); } for( int i = 0; i < (objects? objects->total : 0); i++ ) { CvRect* r = (CvRect*)cvGetSeqElem( objects, 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 ); } cvShowImage( "Camera", img ); cvReleaseImage(&gray); cvReleaseImage(&small_img); }

单片机上的程序
 
   

#include #define unit unsigned int sbit set1=P0^0; //定义四线步进电机4个IO口 sbit set2=P0^1; sbit set3=P0^2; sbit set4=P0^3; unsigned char RcvBuf[10]; unsigned char RcvCnt=0; unsigned char RcvFlag=0; void Delay(unit t) //延时函数 { while(--t); } void ComInit() { TMOD=0x20; //设置T1为工作方式2 TH1=0xfd; //装入初值,比特率为9600bps TL1=0xfd; TR1=1; //开启T1 REN=1; //接收允许 SM0=0; //方式1 SM1=1; RI=0; EA=1; //开全局中断 ES=1; //开串口中断 } //正向转动 void Forward(unsigned char step) { int i; for(i=0;i<step;i++) { set1=set2=0; //相1 : 1100 set3=set4=1; Delay(800); set3=set2=0; //相2 : 1001 set1=set4=1; Delay(800); set1=set2=1; //相3 : 0011 set3=set4=0; Delay(800); set3=set2=1; //相4 : 0110 set1=set4=0; Delay(800); //如此循环即可实现转动,如果需要反方向转动,则必须是相4-相1时序 } } //反向转动 void Backward(unsigned char step) { int i; for(i=0;i<step;i++) { set3=set2=1; //相4 : 0110 set1=set4=0; Delay(800); //如此循环即可实现转动,如果需要反方向转动,则必须是相4-相1时序 set1=set2=1; //相3 : 0011 set3=set4=0; Delay(800); set3=set2=0; //相2 : 1001 set1=set4=1; Delay(800); set1=set2=0; //相1 : 1100 set3=set4=1; Delay(800); } } void main(void) { ComInit(); for(;;) { if(RcvFlag==0xff) { RcvFlag=0x00; if(RcvBuf[0]==0x00) Forward(RcvBuf[1]); else if(RcvBuf[0]==0x01) Backward(RcvBuf[1]); } } } //串口中断 void ser() interrupt 4 { RI=0; //清除标志 RcvBuf[RcvCnt]=SBUF; if(RcvBuf[RcvCnt]=='\n') { if(RcvBuf[RcvCnt-1]=='\r') { RcvFlag=0xff; RcvCnt=0; } else RcvCnt++; } else RcvCnt++; if(RcvCnt>=10) RcvCnt=0; }

使用为  单片机上接步进电机,在步进电机上固定摄像头,当在摄像头范围内识别到人脸,会自动调节将人脸所在的位置调整到在摄像头捕捉到的中间位置
 



FROM: http://blog.163.com/tianjunqiang666@126/blog/static/87259119201331313257655/

你可能感兴趣的:(视频/opencv)