• 卡尔曼滤波+opencv 实现跟踪人脸 小demo


    #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
    " << 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);
        }
        
        
    }
  • 相关阅读:
    C++ 复制控制之复制构造函数
    static关键字总结
    C++ 隐式类类型转换
    Unity 移动端触摸屏操作
    【原创】为什么要用规则引擎?
    【原创】你的Redis怎么持久化的
    【原创】JAVA中令人眼花撩乱的数字魔法
    【原创】谈谈redis的热key问题如何解决
    【原创】Mysql中事务ACID实现原理
    【原创】杂谈自增主键用完了怎么办
  • 原文地址:https://www.cnblogs.com/lcj1105/p/4975943.html
Copyright © 2020-2023  润新知