opencv--读取摄像头识别人脸并跟踪
VS上的程序
#include "stdafx.h" #include "cv.h" #include "highgui.h"#include "windows.h"#include <stdio.h> #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 #endifstatic 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 <reg52.h> #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--读取摄像头识别人脸并跟踪的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows系统中nginx命令
- 下一篇: 高等数学——简单直观地了解定积分