2014-07-08 49 views
3

嘿那裏:)我目前開始在OpenCv中使用卡爾曼濾波器。 我遇到了2個問題。卡爾曼OpenCV估計沒有測量

第一個是,我用http://www.morethantechnical.com/2011/06/17/simple-kalman-filter-for-tracking-using-opencv-2-2-w-code/的例子。 在視頻中,似乎Kalman濾波器會降低噪聲,但如果我運行我的代碼,噪聲不會降低,所以如果我移動鼠標,則預測的行爲幾乎完全像鼠標移動,而不會降低噪聲。是由於我的高採樣率還是measurementMatrix,processNoiseCov,measurementNoiseCov和errorCovPost設置錯誤的值?我希望你能理解我的意思。

我的其他問題是,如果我按「n」我想禁用新的測量,我想Kalmanfilter仍然猜測鼠標的新位置。在http://code.opencv.org/issues/1380 Mircea Popa說:

「但在kalman.correct()調用之前將測量矩陣設置爲0(這是程序員的職責),因此修正係數(增益)爲0,並且過濾器的狀態會根據預測的結果進行更新。「所以我試圖這樣做:測量= Mat ::零(2,1,CV_32F),但只是預測的位置已經在位置(0,0),所以不是我所期望的。有什麼我明白錯誤?不是測量Mircea Popa談到的「測量矩陣」嗎?還是有另一種方法讓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; 
} 

回答

2

從更廣義的POV說起......如果你想有一個卡爾曼濾波器軟化測量噪聲,你必須更多地依賴於過程模型和少在測量更新。所以在你的情況下,調整「measurementMatrix,processNoiseCov,measurementNoiseCov」可能會導致你輸出更柔和。

+0

謝謝你的快速答覆梅茨堡。我的理解是否正確:這些矩陣在初始化時設置了一次?或者我需要每次更換它們? – CelesterSpencer

+0

在初始化中設置一次...是的。 – metsburg