首页 > 其他分享 >卡尔曼滤波二维图像点跟踪

卡尔曼滤波二维图像点跟踪

时间:2023-08-09 19:44:55浏览次数:37  
标签:Eigen int 卡尔曼滤波 二维 image 图像 kalmanFilter include cv

原理

参考 https://zh.wikipedia.org/wiki/%E5%8D%A1%E5%B0%94%E6%9B%BC%E6%BB%A4%E6%B3%A2

代码

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

/** 
 * predict 
 *  x = Fx + Bu + w   B是作用在控制器向量u上的输入-控制模型
 *  z = Hz + v        其中H是观测模型 v是观测噪声 其均值为零 协方差矩阵为R
 *  p = FpF_trans + Q
 * 
 *  
 * 
 * Update
 * measurement pre-fit residual                 y = z - Hx
 * Innovation (or pre-fit residual) covariance  S = HpH_trans + R
 * Optimal Kalman gain                          K = PHS
 * 
 * 
 * Updated (a posteriori) state estimate        x = x + Ky
 * Updated (a posteriori) estimate covariance   p = (I - KH)P
 * Measurement post-fit residual                y = z - Hx
 * 
 **/


//状态转移矩阵
Eigen::Matrix4d m_F;
//状态矩阵
Eigen::Matrix<double, 4, 1> m_x;
//观测模型
Eigen::Matrix<double, 2, 4> m_H;
//测量矩阵
Eigen::Matrix<double, 2, 1> m_z;
//残差
Eigen::Matrix<double, 2, 1> m_y;
//过程噪声
Eigen::Matrix4d m_Q;
//状态协方差矩阵
Eigen::Matrix4d m_P;
//测量噪声
Eigen::Matrix<double, 2, 2> m_R;
//kalman增益
Eigen::Matrix<double, 4, 2> m_K;
//covariance
Eigen::Matrix2d m_S;

Eigen::Matrix4d m_I{Eigen::Matrix4d::Identity()};

cv::Point mousePos(0, 0);
void mouseMoveCallback(int event, int x, int y, int flags, void* userData) {
  if (event == cv::EVENT_MOUSEMOVE) {
    mousePos.x = x;
    mousePos.y = y;
  }
}
void init(double X, double Y){
  m_F << 1, 0, 1, 0,
         0, 1, 0, 1,
         0, 0, 1, 0,
         0, 0, 0, 1;

  m_x << X, //pose x
         Y, //pose y
         1, //vel x
         1; //vel y

  m_H << 1, 0, 0, 0,
	       0, 1, 0, 0;

  m_Q << 1, 0, 1, 0,
         0, 1, 0, 1,
         0, 0, 1, 0,
         0, 0, 0, 1;

  m_P << 1, 0, 1, 0,
         0, 1, 0, 1,
         0, 0, 1, 0,
         0, 0, 0, 1;

  m_R << 1, 0,
	       0, 1;
}
void predict(){
  m_x = m_F * m_x;
  m_P = m_F * m_P * m_F.transpose() + m_Q;
}
void updata(double X, double Y, double* predict_X, double* predict_Y){
  m_z << X,
         Y;
  m_y = m_z - m_H*m_x;
  m_S = m_H*m_P*m_H.transpose() + m_R;
  m_K = m_P*m_H.transpose()*m_S.inverse();

  m_x = m_x + m_K*m_y;
  m_P = (m_I - m_K*m_H)*m_P;
  *predict_X = m_x[0];
  *predict_Y = m_x[1];
}
int main(){
  cv::namedWindow("kalman2D");
	cv::setMouseCallback("kalman2D", mouseMoveCallback);
  cv::Mat image(500, 500, CV_8UC3);
  init(mousePos.x, mousePos.y);//初始化
  double km_x;
  double km_y;
  while (1) {
    updata(mousePos.x, mousePos.y, &km_x, &km_y);
    predict();
    circle(image, mousePos, 13, cv::Scalar(0, 255, 0), 3); //真实点, 用空心圈表示
    circle(image, cv::Point(km_x, km_y), 9, cv::Scalar(255, 0, 255), -1); //状态向量, 用实心点表示
    cv::imshow("kalman2D", image);
    image = cv::Scalar::all(0);
		int key = cv::waitKey(3);
		if (key == 27) {//esc   
			break;
    }
  }
}

/* int main(void) {
  cv::KalmanFilter kalmanFilter(4, 2, 0); //状态向量四维, 测量变量二维, 无控制向量

  float F[4][4] = { { 1, 0, 1, 0 },
                    { 0, 1, 0, 1 },
                    { 0, 0, 1, 0 },
                    { 0, 0, 0, 1 } };
  kalmanFilter.transitionMatrix = cv::Mat(4, 4, CV_32F, F);

  cv::Mat matMeasurement(2, 1, CV_32F, cv::Scalar::all(0));

  kalmanFilter.statePre.at<float>(0) = (float)mousePos.x;
  kalmanFilter.statePre.at<float>(1) = (float)mousePos.y;
  kalmanFilter.statePre.at<float>(2) = 0;
  kalmanFilter.statePre.at<float>(3) = 0;

  setIdentity(kalmanFilter.measurementMatrix); //H
  setIdentity(kalmanFilter.processNoiseCov, cv::Scalar::all(1e-4)); //Q
  setIdentity(kalmanFilter.measurementNoiseCov, cv::Scalar::all(10)); //R, 设置越小回归越快,但转弯时容易冲出太远
  setIdentity(kalmanFilter.errorCovPost, cv::Scalar::all(.1)); //\sigma_k

  cv::Mat image(500, 500, CV_8UC3);

  std::vector<cv::Point> mousevec, kalmanvec; //这是为了画出轨迹而准备的点的向量组

  mousevec.clear();
  kalmanvec.clear();

  cv::namedWindow("image");
  cv::setMouseCallback("image", mouseMoveCallback);

  while (1) {
    cv::Mat matPrediction = kalmanFilter.predict(); //更新statePre

    //更新测量向量
    matMeasurement.at<float>(0, 0) = (float)mousePos.x;
    matMeasurement.at<float>(1, 0) = (float)mousePos.y;

    cv::Mat estimated = kalmanFilter.correct(matMeasurement); //更新statePost

    cv::Point measPt((int)matMeasurement.at<float>(0, 0), (int)matMeasurement.at<float>(1, 0));
    cv::Point statePt((int)estimated.at<float>(0), (int)estimated.at<float>(1));

    imshow("image", image);
    image = cv::Scalar::all(0);

    mousevec.push_back(measPt);
    kalmanvec.push_back(statePt);

    circle(image, measPt, 13, cv::Scalar(0, 255, 0), 3); //真实点, 用空心圈表示
    circle(image, statePt, 9, cv::Scalar(255, 0, 255), -1); //状态向量, 用实心点表示
  
    if (cv::waitKey(10) == 27)break;
  }

  return 0;
}
 */

 

cmakelist

cmake_minimum_required(VERSION 3.8)

project(TEST)

find_package(OpenCV 4.7 REQUIRED)
find_package(Eigen3 REQUIRED)

message(STATUS "Opnecv ;ibrary status:")
message(STATUS "> version: ${OpenCV_VERSION}")
message(STATUS "libraries: ${OpenCV_LIBS}")
message(STATUS "> include: ${OpenCV_INCLUDE_DIRS}")

include_directories(${OpenCV_INCLUDE_DIRS})

add_executable(kalman cv_kalman.cpp)
target_link_libraries(kalman 
${OpenCV_LIBS}
Eigen3::Eigen)

 

标签:Eigen,int,卡尔曼滤波,二维,image,图像,kalmanFilter,include,cv
From: https://www.cnblogs.com/chenlinchong/p/17617842.html

相关文章

  • 视频监控—在LCD上显示摄像头图像
    一、框架1、程序框架仿照之前数码相册的框架来进行改造,完成在开发板上动态显示摄像头的数据信息: 对于上述完成主要功能的5个部分:display显示部分、debug调试信息输出部分、render渲染部分、video视频设备部分、convert格式转换部分 video视频设备部分:负责获得摄像头的原......
  • LeetCode 热题 100 之 240. 搜索二维矩阵 II
    题目编写一个高效的算法来搜索mxn矩阵matrix中的一个目标值target。该矩阵具有以下特性:每行的元素从左到右升序排列。每列的元素从上到下升序排列。示例一输入:matrix=[[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]],target=5......
  • 解一类二维递推
    解一类二维递推WC2021讲课题为例thefollowingrecurrencecomesfromWC2021有n个桶和2n−1个球,其中第i个桶可以装前2i−1个球,一个桶只能装一个球问有多少种方案取m个桶,再取m个球,再将这些球分别放在一个桶里;暴力是下面递推式 f[0][0]=1; fr(i,1,n)fr(j,0,n)f[i][j]......
  • 《VTK图形图像开发进阶》第3章VTK基本数据结构——数据对象和数据集
    3.1可视化数据的基本特点离散性数据具有规则或不规则的结构(结构化与非结构化)数据具有维度3.2数据对象和数据集vtkDataObject下图为vtkDataObject类的继承图vtkDataSetVTK里与数据集对应的类是vtkDataSet,该类从vtkDataObject直接派生。vtkDataSet由两个部分组成,即组织......
  • opencv-python 图像分割
    本章节介绍图像分割方面的算法:分水岭算法,grabcut算法,meanshift算法等知识。图像分割:将前景物体从背景中提取出来。图像分割分为传统图像分割和基于深度学习的图像分割。传统图像分割有:分水岭算法,grabcut算法,meanshift算法,背景抠出等。1分水岭算法分水岭算法是基于图像形态学......
  • php中计算二维数组中某一元素之和
    [0] => array(5){    ["id"] => string(2) "11"    ["name"] => string(5) "1.jpg"    ["suffix"] => string(3) "jpg"    ["url"] => string(29) "./Uploads/1/5292f55d208e......
  • 二维数组排序,按其中某项排序
    /** * 二维数组排序 * @param $arrays         目标数组 * @param $sort_key       要排序的键 * @param int $sort_order 升序|降序 * @param int $sort_type  数字|字符串|通常 * @return $arrays         */function ......
  • 《VTK图形图像开发进阶》第2章——VTK智能指针
    2.1引用计数如果很多对象有相同的值,在程序里没有必要将这个值存储多次。更好的办法是让所有的对象共享这个值。这么做不但节省内存,而且可以使程序运行得更快,因为不需要构造和析构这个值的副本。引用计数就是这样一个技巧,它允许多个有相同值的对象共享这个值。引用计数是个简单......
  • 《VTK图形图像开发进阶》第2章——坐标系统及空间变换
    2.1坐标系统计算机图形学里常用的坐标系统主要有4种,分别是Model坐标系统、World坐标系统、View坐标系统和Display坐标系统,此外还有两种表示坐标点的方式:以屏幕像素值为单位和归一化坐标值(各坐标轴取值范围为[-1,1])。它们之间的关系如下图。Model坐标系统:定义模型时所采用的......
  • C关于一维数组以及二维数组的创建和简单利用(下)
    #include<stdio.h>intmain(){inta[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}};intb=0;for(b=0;b<3;b+=1){intc=0;for(c=0;c<4;c+=1){printf("%p||",&a[b][c]);......