OpenCV卡尔曼滤波(Kalman Filter)详细注释以及#include "cvx_defs.h"的问题

//本代码是关于learning OpenCV 394页的代码写的注释(前提:我买的书不是盗版的话。。。。)

#include "cv.h"

#include "highgui.h"
#include "math.h"
 
  
#define phi2xy(mat)                                                  \
  cvPoint( cvRound(img->width/2 + img->width/3*cos(mat->data.fl[0])),\
    cvRound( img->height/2 - img->width/3*sin(mat->data.fl[0])) )
 
  
//注释下, 作者指定圆心在图片width/2, height/2处,  圆周运动半径是width/3
using namespace cv;
//我们从main函数开始解析,去除了#include "cvx_defs.h"...我试了在vs2015与qt5.6和qt.5.9上由两个人分别配置的opencv2.4.9
//和2.4.13以及。3.1.0的环境,都没有这个头文件,网上居然说有。。。。我不知道是我太菜还是他们直接贴代码。。跪求配置出来的人贴图
int main()
{
      //创建卡尔曼滤波对象,窗口,随机数生成器
    cvNamedWindow("Boss Kalman",1);
    CvRandState rng;  //创建生成随机数的结构体
//    typedef struct CvRandState
//   {
//   CvRNG state;   //64位无符号整数
//   int disttype;
//   CvScalar param[2];
//   }
//   CvRandState;
    cvRandInit(&rng,0,1,-1,CV_RAND_UNI);
    //CvRandState结构,随机分布下限,随机分布上限,时间种子,可以用-1代替,也可以用getTickCount 代替
    IplImage  *img=cvCreateImage(cvSize(500,500),8,3);   //长宽500,8位,三通道
    CvKalman *kalman=cvCreateKalman(2,1,0);
    //状态变量维数2,测量值维数1,控制维数0,
 
  
 
  
    //空间分配完毕,接下来我们为状态x_k,过程噪声w_k,测量值z_k,传递矩阵F创建矩阵
    //公式如下 Ⅰ,x_k^-=Fx_(k-1)+Bu_(k-1)+w_k
    //注释:这里Bu_(k-1)项忽略,因为传入的控制维数为0,F是2x2矩阵,因为状态变量维数为2(即右侧的x_(k-1)是2x1的矩阵),分别是角度位置和角度。
    //自然过程噪声也应该是2x1的矩阵,x_k^-(先验估计)计算出后,带入下列公式
    //Ⅱ x_k=x_k^-+K_k(z_k^-+H_k*x_k^-)
    //P_k=(I-K_k*H_k)P_k
 
  
    //初始化操作
    //x_k 为[角度位置(phi),角速度(delta_phi)]^T
    //传递矩阵即为:[(1,dt),[0,1]],F*x_k相乘即为[(phi+velocity*dt),(velocity)],线代知识,哈哈
    CvMat *x_k=cvCreateMat(2,1,CV_32FC1);
    cvRandSetRange(&rng,0,0.1,0);
    //rng_state,生成的随机数下界,生成的随机数上界
    //index
    //The 0-based index of dimension/channel for which the parameter are changed,
    //-1 means changing the parameters for all dimensions.
 
  
    rng.disttype=CV_RAND_NORMAL;  //设为正态分布
    cvRand(&rng,x_k);  //将x_k的数据随机化
 
  
    CvMat *w_k=cvCreateMat(2,1,CV_32FC1);
 
  
    //测量数据,只有角度位置
    CvMat *z_k=cvCreateMat(1,1,CV_32FC1);
    cvZero(z_k);
 
  
    //设置传递矩阵
    const float F[]={1,1,0,1};
    memcpy(kalman->transition_matrix->data.fl,F,sizeof(F));
 
  
    //初始化kalman的其他参数
    cvSetIdentity(kalman->measurement_matrix,cvRealScalar(1));
    //初始化测试协方差矩阵
    cvSetIdentity(kalman->process_noise_cov,cvRealScalar(1e-5));
    //初始过程协方差矩阵
    cvSetIdentity(kalman->measurement_noise_cov,cvRealScalar(1e-1));
    //初始测量噪音协方差矩阵
    cvSetIdentity(kalman->error_cov_post,cvRealScalar(1));
    //测量误差矩阵,v_k.
    cvRand(&rng,kalman->state_post);
    //初始化纠正后的矩阵
    //开始卡尔曼学习
    while(1)
    {
      //估计点的位置
        const CvMat *y_k=cvKalmanPredict(kalman,0);
        //产生测量值
        cvRandSetRange(&rng,0,sqrt(kalman->measurement_matrix->data.fl[0]),0);
        //这个数大概在0到0.6之间
        cvRand(&rng,z_k);//这里是误差v_k...原书作者真是骚气
        cvMatMulAdd(kalman->measurement_matrix,x_k,z_k,z_k);
       //将src1*src2+src3=dst4
        //z_k=H*x_k+v_k
        cvZero(img);
        //画画
        cvZero(img);
        //观测值,标记为红色
        cvCircle(img,phi2xy(z_k),6,cvScalar(0,0,255));
        //预测值  //标记为蓝色
        cvCircle(img,phi2xy(y_k),4,cvScalar(255,0,0));
        //纠正值(前一次的)  //标记为绿色
        cvCircle(img,phi2xy(x_k),8,cvScalar(0,255,0));
        cvShowImage("Boss Kalman",img);
 
  
        //下面开始调整卡尔曼滤波
        //只需要传入观测值即可
        cvKalmanCorrect(kalman,z_k);
        //运用传递矩阵F算出下次的x_k的值
        cvRandSetRange(&rng,0,sqrt(kalman->process_noise_cov->data.fl[0]),0);
        cvRand(&rng,w_k);
        //w_k大概在0到10的-3次方之间
        cvMatMulAdd(kalman->transition_matrix,x_k,w_k,x_k);
        //就是那个著名的公式:,x_k^-=Fx_(k-1)+Bu_(k-1)+w_k
        //即F*x_k+w_k=x_k
        if(cvWaitKey(40)==27)
            break;
 
  
    }
 
  
        return 0;
 
  
 
  
}

//程序开始后我们会看到绿圈渐渐趋于稳定,并且绿圈总是滞后与篮圈一点,因为是上一次的啦,不过它们都渐渐趋于稳定
 
 

你可能感兴趣的:(OpenCV卡尔曼滤波(Kalman Filter)详细注释以及#include "cvx_defs.h"的问题)