根据检测出来的脸部而划定眼睛范围的检测
铜过打开摄像头,然后加载脸部检测器,来抓取头像,然后根据头像的比例进行确定眼睛的位置
#include "cv.h" #include "highgui.h" #include"iostream" #include"cstring" using namespace std; using namespace cv; static string xml = "G:\\Opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml"; CvMemStorage* storage = 0; CascadeClassifier facedectector; CvCapture *capture = 0; CvRect righteye; CvRect lefteye; Mat GetMatFrom(int choice, char* filename1); Rect GetLargerFace(Mat face); void GetFaceDetectionArea(Mat face); Mat DrawEyeContours(Mat faceimg, Rect left, Rect right); int main() { facedectector.load(xml);//人脸检测 Mat img = GetMatFrom(0,NULL); cvNamedWindow("test"); while (true) { img = GetMatFrom(0, NULL); Mat grayimg; cvtColor(img,grayimg,CV_BGR2GRAY); imshow("linshi",img); imshow("linshi2", grayimg); Rect rect = GetLargerFace(grayimg); Mat img2 = grayimg(rect); GetFaceDetectionArea(img2); imshow("cishi",img2); Mat img3 = img(rect); DrawEyeContours(img3,lefteye,righteye); imshow("test",img3); if (cvWaitKey(15) == 27) break; } return 0; } //封装好的获取图片的函数 //choice=0是从摄像机中获取。 //choice!=0从文件获取,必须指定filename Mat GetMatFrom(int choice, char* filename1 = NULL) { Mat back_img = cvCreateImage(cvSize(640,480),8,3); if (choice == 0)//代表摄像机 { if (capture == NULL) capture = cvCaptureFromCAM(0); back_img = cvQueryFrame(capture); } else if (filename1!=NULL) { if (capture==NULL) try{ capture = cvCaptureFromAVI(filename1); } catch (cv::Exception){ printf("视屏文件%s加载出错!\n",filename1); } back_img = cvQueryFrame(capture); } else { printf("没有输入文件名!\n"); } return back_img; } //得到最大脸区域的矩形 Rect GetLargerFace(Mat face)//利用灰度图像 { Rect rect; std::vector<Rect> rects; double scale = 0.5; int scalewidth = cvRound(face.cols*scale); int scaleheight = cvRound(face.rows*scale); Mat smallimg; resize(face,smallimg,cvSize(scalewidth,scaleheight)); facedectector.detectMultiScale(smallimg, rects, 1.1, 3, CASCADE_FIND_BIGGEST_OBJECT | CASCADE_DO_ROUGH_SEARCH, cvSize(10, 10)); if (rects.size() < 1) { rect.x = 0; rect.y = 0; rect.width = 10; rect.height = 10; } else rect = rects[0]; //恢复图像原来大小 rect.x = cvRound(rect.x/scale); rect.y =cvRound(rect.y/scale); rect.width = cvRound(rect.width/scale); rect.height = cvRound(rect.height/scale); //判断矩形是否越界 rect.x = rect.x < 0 ? 0 : rect.x; rect.y = rect.y < 0 ? 0 : rect.y; if (rect.width + rect.x>face.cols)rect.x = face.cols - rect.width; if (rect.y + rect.height>face.rows)rect.y = face.rows - rect.height; return rect; } //得到要可检测眼睛的矩形 void GetFaceDetectionArea(Mat face)//使用的是脸部灰度图像 { //计算眼睛的区域 int leftx = cvRound(face.cols*0.16); int topy = cvRound(face.rows*0.26); int eye_width = cvRound(face.cols*0.3); int eye_height = cvRound(face.rows*0.28); int rightx = cvRound(face.cols*(1 - 0.16 - 0.3)); //得到左右眼睛的矩形 lefteye.x = leftx; lefteye.y = topy; lefteye.width = eye_width; lefteye.height = eye_height; righteye.x = rightx; righteye.y = topy; righteye.width = eye_width; righteye.height = eye_height; cout << righteye.x<<endl; cout << righteye.y<<endl; cout << righteye.width<<endl; } //画出眼睛轮廓 Mat DrawEyeContours(Mat faceimg, Rect left, Rect right) { rectangle(faceimg, cvPoint(left.x, left.y), cvPoint(left.x + left.width, left.y + left.height), cvScalar(50, 50, 50)); rectangle(faceimg, cvPoint(right.x, right.y), cvPoint(right.x + right.width, right.y + right.height), cvScalar(50, 50, 50)); return faceimg; }
窗口的大小跟着人离屏幕的距离而改变。也许这个特点能有点其他用处。
What I don't dare to say is I can't!