卡尔曼滤波+opencv 实现跟踪人脸 小demo
2015-11-18 21:24 Yan消云散_ 阅读(3683) 评论(0) 编辑 收藏 举报#include "opencv2/objdetect/objdetect.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/video/tracking.hpp" #include <iostream> #include <stdio.h> using namespace std; using namespace cv; /** 函数声明 */ void detectAndDisplay(Mat& frame); /** 全局变量 */ string face_cascade_name = "haarcascade_frontalface_alt.xml"; //string eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml"; CascadeClassifier face_cascade; //CascadeClassifier eyes_cascade; string window_name = "Face detection with Kalman"; RNG rng(12345); struct face{ Point leftTop=0; int width=0; int height=0; }; face preFace; /** @主函数 */ int main() { //kalman参数设置 int stateNum = 4; int measureNum = 2; KalmanFilter KF(stateNum, measureNum, 0); //Mat processNoise(stateNum, 1, CV_32F); Mat measurement = Mat::zeros(measureNum, 1, CV_32F); KF.transitionMatrix = *(Mat_<float>(stateNum, stateNum) << 1, 0, 1, 0,//A 状态转移矩阵 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1); //这里没有设置控制矩阵B,默认为零 setIdentity(KF.measurementMatrix);//H=[1,0,0,0;0,1,0,0] 测量矩阵 setIdentity(KF.processNoiseCov, Scalar::all(1e-5));//Q高斯白噪声,单位阵 setIdentity(KF.measurementNoiseCov, Scalar::all(1e-1));//R高斯白噪声,单位阵 setIdentity(KF.errorCovPost, Scalar::all(1));//P后验误差估计协方差矩阵,初始化为单位阵 randn(KF.statePost, Scalar::all(0), Scalar::all(0.1));//初始化状态为随机值 //读入视频 if (!face_cascade.load(face_cascade_name)){ cout << "--(!)Error loading\n" << endl; }; Mat frame, frame2; VideoCapture cap; cap.open("me1.mp4"); //cap.open("me2.mp4"); //cap.open("me3.mp4"); while (true){ for (int i = 0; i < 1; i++){ cap >> frame; } if (!frame.empty()) { resize(frame, frame2, Size(), 0.5, 0.5, INTER_LINEAR); Mat prediction = KF.predict(); Point predict_pt = Point((int)prediction.at<float>(0), (int)prediction.at<float>(1)); detectAndDisplay(frame2); measurement.at<float>(0) = (float)preFace.leftTop.x; measurement.at<float>(1) = (float)preFace.leftTop.y; KF.correct(measurement); //画卡尔曼的效果 Point center(predict_pt.x + preFace.width*0.5, predict_pt.y + preFace.height*0.5); ellipse(frame2, center, Size(preFace.width*0.3, preFace.height*0.3), 0, 0, 360, Scalar(0, 0, 255), 4, 8, 0); circle(frame2, center, 3, Scalar(0, 0, 255), -1); imshow(window_name, frame2); waitKey(1); } else { printf(" --(!) No frame -- Break!"); break; } } return 0; } /** @函数 detectAndDisplay */ void detectAndDisplay(Mat& frame) { std::vector<Rect> faces; Mat frame_gray; int Max_area=0; int faceID=0; cvtColor(frame, frame_gray, CV_BGR2GRAY); equalizeHist(frame_gray, frame_gray); //-- 多尺寸检测人脸 face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30)); //找出最大的脸,可以去除不是脸的误检,这些误检一般比较小 for (int i = 0; i < faces.size(); i++) { if ((int)(faces[i].width*faces[i].height) > Max_area){ Max_area =(int) faces[i].width*faces[i].height; faceID=i; } } if (faces.size() > 0)//必须是检测到脸才绘制当前人脸圆圈,并且只能绘制最大的脸 { preFace.leftTop.x = faces[faceID].x; preFace.leftTop.y = faces[faceID].y; preFace.height = faces[faceID].height; preFace.width = faces[faceID].width; Point center(faces[faceID].x + faces[faceID].width*0.5, faces[faceID].y + faces[faceID].height*0.5); ellipse(frame, center, Size(faces[faceID].width*0.5, faces[faceID].height*0.5), 0, 0, 360, Scalar(0, 255, 0), 1, 8, 0); circle(frame, center, 3, Scalar(0, 255,0), -1); } else{//没检测到人脸绘制之前的人脸 Point center(preFace.leftTop.x + preFace.width*0.5, preFace.leftTop.y + preFace.height*0.5); ellipse(frame, center, Size(preFace.width*0.5, preFace.height*0.5), 0, 0, 360, Scalar(0, 255, 0), 1, 8, 0); circle(frame, center, 3, Scalar(0, 255, 0), -1); } }