Фильтр Калмана - нулевая прогнозируемая точка (точки)

Я пытаюсь применить фильтр Калмана на С++ с OpenCV, чтобы отфильтровать некоторые треки. Первым шагом, чтобы заставить его работать для меня, было предсказать точки с фильтром из вектора Points2f.

Мой код следующий:

cv::KalmanFilter kalmanFilter(4,2,0, CV_32F); 
kalmanFilter.transitionMatrix = transitionMat;
for(int i = 0 ; i < oldTrackeables.size() ; i++)
    for(int j = 0 ; j < oldTrackeables[i].getTrack().size() ; j++)
              {
                  cv::Size msmtSize(2,1);
                  cv::Mat measurementMat(msmtSize, CV_32F);
                  measurementMat.setTo(cv::Scalar(0));
                  measurementMat.at<float>(0) = oldTrackeables[i].getTrack()[j].x;
                  measurementMat.at<float>(1) = oldTrackeables[i].getTrack()[j].y;

                  //Initialisation of the Kalman filter
                  kalmanFilter.statePre.at<float>(0) = (float) oldTrackeables[i].getTrack()[j].x;
                  kalmanFilter.statePre.at<float>(1) = (float) oldTrackeables[i].getTrack()[j].y;
                  kalmanFilter.statePre.at<float>(2) = (float) 2;
                  kalmanFilter.statePre.at<float>(3) = (float) 3;


                 cv::setIdentity(kalmanFilter.measurementMatrix);
                 cv::setIdentity(kalmanFilter.processNoiseCov, cv::Scalar::all(1e-4));
                 cv::setIdentity(kalmanFilter.measurementNoiseCov, cv::Scalar::all(.1));
                 cv::setIdentity(kalmanFilter.errorCovPost, cv::Scalar::all(.1));

                 //Prediction
                 cv::Mat prediction = kalmanFilter.predict();

                 kalmanFilter.statePre.copyTo(kalmanFilter.statePost);
                 kalmanFilter.errorCovPre.copyTo(kalmanFilter.errorCovPost);

                 cv::Point predictPt(prediction.at<float>(0), prediction.at<float>(1));
                 cv::Point Mc = oldTrackeables[i].getMassCenter();          

                 cv::circle(kalmat, predictPt, 16, cv::Scalar(0,255,0), 3, 2, 1);


                 std::cout<<"prediction : x = " << predictPt.x << " - y = " << predictPt.y <<std::endl;
                 std::cout<<"position captée : x = " << oldTrackeables[i].getTrack()[j].x << " - y = " << oldTrackeables[i].getTrack()[j].y << std::endl;
                 std::cout<<"size of frame : rows = " << frame.rows << " - width = " << frame.cols <<std::endl;
                 std::cout<<"size of kalmat : rows = " << kalmat.rows << " - width = " << kalmat.cols <<std::endl;
                 cv::imshow("kalmat", kalmat);

Где oldTrackeables[i].getTrack()[j] — это всего лишь некоторые Points2f из вектора.

Отслеживание правильное, но фильтр Калмана не дает "правильных" значений для прогноза. Например, программа отображает: прогноз: x = 0 - y = 0 - позиция захвата: x = 138,29 - y = 161,078 (позиция исходный пункт).

Я действительно много искал ответы и пробовал много разных способов сделать это, но я не могу найти ничего, что действительно помогло бы мне... Более близким, который я нашел, был этот: http://answer.opencv.org/question/24865/why-kalman-filter-keeps-returning-the-same-prediction/ Но это не помогло мне решить мою проблему...

Если у кого-то из вас есть элемент ответа, который может помочь мне понять проблему, я был бы очень благодарен. Спасибо.


person Myriam Sarah    schedule 23.05.2017    source источник
comment
Ps: я пытался добавить Привет! но я не могу его успешно отредактировать - Но привет, хотя :)   -  person Myriam Sarah    schedule 23.05.2017
comment
У вашего for I loop нет getTrack.   -  person stark    schedule 23.05.2017
comment
Спасибо за ваш ответ. Но я не думаю, что это причина проблемы... oldTackeables - это вектор‹vector‹Point2f››, и я хочу изучить точки 2f вектора векторов‹Point2f› (настолько старый Trackeables[i].getTrack() здесь). Цикл работает, поскольку он может отображать все исходные точки в мате, но предсказанные точки совсем не хороши...   -  person Myriam Sarah    schedule 23.05.2017


Ответы (2)


Прежде всего, я бы переместил все элементы инициализации за пределы цикла, иначе вы переопределите внутренние состояния в фильтре. Также измените statePre на statPost

  //Initialisation of the Kalman filter
  kalmanFilter.statePost.at<float>(0) = (float) 0;   
  kalmanFilter.statePost.at<float>(1) = (float) 0;
  kalmanFilter.statePost.at<float>(2) = (float) 2;
  kalmanFilter.statePost.at<float>(3) = (float) 3;

  cv::setIdentity(kalmanFilter.measurementMatrix);
  cv::setIdentity(kalmanFilter.processNoiseCov, cv::Scalar::all(1e-4));
  cv::setIdentity(kalmanFilter.measurementNoiseCov,cv::Scalar::all(.1));
  cv::setIdentity(kalmanFilter.errorCovPost, cv::Scalar::all(.1));

Часть:

 kalmanFilter.statePre.copyTo(kalmanFilter.statePost);                     
 kalmanFilter.errorCovPre.copyTo(kalmanFilter.errorCovPost);

следует удалить, так как это делается внутри на этапе predict.

Наконец, как говорит @Mozfox, фаза correct отсутствует в предоставленном вами коде цикла. Добавлять:

kalmanFilter.predict(measurementMat);
person Claes Rolen    schedule 31.05.2017
comment
Большое спасибо за ваш ответ ! Прошло некоторое время, поэтому я вынес инициализацию за пределы цикла и с тех пор использовал kalmanFilter.predict(Mat) :). Спасибо и за другие советы, я их раньше нигде не читала. Спасибо еще раз ! - person Myriam Sarah; 31.05.2017

Я думаю, что вам не хватает фазы коррекции для расчета измерений.

person Mandar    schedule 23.05.2017