Оценка Kalman OpenCV без измерения

Привет :) В настоящее время я начал работать с Kalmanfilter в OpenCv. Я столкнулся с 2 проблемами.

Во-первых, я использовал пример из http://www.morethantechnical.com/2011/06/17/simple-kalman-filter-for-tracking-using-opencv-2-2-w-code/ . В видео кажется, что шум уменьшается с помощью фильтра Калмана, но если я запускаю свой код, шум не уменьшается, поэтому, если я перемещаю мышь, предсказание ведет себя почти так же, как движение мыши, без уменьшения шума. Это связано с моей высокой частотой дискретизации или неправильно заданы значения MeasurementMatrix, processNoiseCov, MeasurementNoiseCov и errorCovPost? Надеюсь, вы понимаете, что я имею в виду.

Моя другая проблема заключается в том, что если я нажму «n», я хочу отключить новые измерения, и я хочу, чтобы Kalmanfilter все еще угадывал новое положение мыши. В http://code.opencv.org/issues/1380 Мирча Попа сказал:

"но установите матрицу измерений в 0 перед вызовом kalman.correct() (это обязанность программиста). При этом поправочный коэффициент (коэффициент усиления) становится равным 0, а состояние фильтра обновляется на основе того, что это было предсказано».

Итак, я попытался сделать что-то вроде этого: измерение = Mat::zeros(2,1, CV_32F), но тогда только позиция прогноза была в позиции (0,0), так что это не то, что я ожидал. Я что-то не так понял? Разве измерение не является «матрицей измерения», о которой говорил Мирча Попа? Или есть другой способ позволить KalmanFilter предсказать новую позицию без измерения?

Чтобы прояснить, что я ожидаю от Kalmanfilter: если нет измерения, движение предполагаемой позиции должно быть равномерным, а направление движения должно быть на прямой линии, которая определяется двумя последними позициями.

Вот мой код:

#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/video/tracking.hpp" 

using namespace cv;
using namespace std;



int m_X = 0;
int m_Y = 0;
bool cursorSet = false;
bool noDetection = false;
Mat_<float> lastPosition(2,1);


void drawCross(Mat &img, Point &center, Scalar color, int d) {
    line( img, Point( center.x - d, center.y - d ), Point( center.x + d, center.y + d ), color, 2, CV_AA, 0); 
    line( img, Point( center.x + d, center.y - d ), Point( center.x - d, center.y + d ), color, 2, CV_AA, 0);
};  

void CallBackFunc(int event, int x, int y, int flags, void* userdata) {
    m_X = x;
    m_Y = y;
    cursorSet = true;
    cout << "Mouse move over the window - position (" << x << ", " << y << ")" << endl;
};

void GetCursorPos(Point &mousepos){
    mousepos = Point(m_X, m_Y);
};

int main( ) {

    //create window and set callback for mouse movement
    namedWindow("window", 1);
    setMouseCallback("window", CallBackFunc, NULL);

    // Image to show mouse tracking
    Mat img(600, 800, CV_8UC3);
    vector<Point> mousev,kalmanv;
    mousev.clear();
    kalmanv.clear();

    //wait until mouse has an initial position inside the window
    while(!cursorSet) {
        imshow("window", img); 
        waitKey(10);
    };



    //create kalman Filter
    KalmanFilter KF(6, 2, 0);

    //position of the mouse will be observed
    Point mousePos;
    GetCursorPos(mousePos);

    // intialization of KF...
    KF.transitionMatrix = *(Mat_<float>(6, 6) << 1,0,1,0,.5,0,      // x  + v_x + 1/2  a_x 
                                                 0,1,0,1,0,0.5,     // y  + v_Y + 1/2  a_y
                                                 0,0,1,0,1,0,       //      v_x +      a_x 
                                                 0,0,0,1,0,1,       //      v_y +      a_y    
                                                 0,0,0,0,1,0,       //                 a_x
                                                 0,0,0,0,0,1);      //                 a_y
    Mat_<float> measurement(2,1); measurement.setTo(Scalar(0));

    //initialize the pre state 
    KF.statePost.at<float>(0) = mousePos.x;
    KF.statePost.at<float>(1) = mousePos.y;
    KF.statePost.at<float>(2) = 0;
    KF.statePost.at<float>(3) = 0;
    KF.statePost.at<float>(4) = 0;
    KF.statePost.at<float>(5) = 0;


    setIdentity(KF.measurementMatrix);
    setIdentity(KF.processNoiseCov, Scalar::all(1e-1));
    setIdentity(KF.measurementNoiseCov, Scalar::all(1e-5));
    setIdentity(KF.errorCovPost, Scalar::all(1e-3));


    while(1) {
        img = Scalar::all(0);
        // First predict, to update the internal statePre variable
        Mat prediction = KF.predict();
        Point predictPt(prediction.at<float>(0),prediction.at<float>(1));

        // Get mouse point
        if (!noDetection) {
            GetCursorPos(mousePos);
            measurement(0) = mousePos.x;
            measurement(1) = mousePos.y;
        }else { 
            measurement(0) = prediction.at<float>(0);
            measurement(1) = prediction.at<float>(1);
        }

        // The update phase3
        Mat estimated = KF.correct(measurement);

        Point statePt(estimated.at<float>(0),estimated.at<float>(1));
        Point measPt(measurement(0),measurement(1));


        // draw cross for actual mouse position and kalman guess
        mousev.push_back(measPt);
        kalmanv.push_back(statePt);
        drawCross(img, statePt, Scalar(255,255,255), 5);
        drawCross(img, measPt, Scalar(0,0,255), 5 );

        // draw lines of movement
        for (int i = 0; i < mousev.size()-1; i++)
            line(img, mousev[i], mousev[i+1], Scalar(0,0,255), 1);

        for (int i = 0; i < kalmanv.size()-1; i++)
            line(img, kalmanv[i], kalmanv[i+1], Scalar(255,255,255), 1);

        imshow("window", img);     
        char key = waitKey(10);
        if (key == 'c') {
            mousev.clear();
            kalmanv.clear();    // press c to clear screen
        }if (key == 'n') {
            noDetection = true; //press n to simulate that no measurement is made
        }if (key == 'd') {
            noDetection = false;//press d to allow measurements again   
        }else if(key == 'x') {  
            break;              // press x to exit program
        }; 
     }

     return 0;
 }

person CelesterSpencer    schedule 08.07.2014    source источник


Ответы (1)


Говоря с более обобщенной точки зрения... если вы хотите иметь фильтр Калмана, который смягчает шум измерения, вы должны больше полагаться на модель процесса и меньше на обновление измерения. Таким образом, в вашем случае настройка «measurementMatrix, processNoiseCov, MeasurementNoiseCov» может привести к более мягкому выводу.

person metsburg    schedule 08.07.2014
comment
Спасибо за быстрый ответ Метсбург. Я правильно понял: эти матрицы устанавливаются один раз при инициализации? Или их нужно каждый раз менять? - person CelesterSpencer; 09.07.2014
comment
Установить один раз при инициализации... да. - person metsburg; 10.07.2014