2014-02-26 47 views
4

在实施了卡尔曼滤波器之后,该卡尔曼滤波器在用Haar级联先前检测到人脸后接收来自camshift头部追踪的真实测量值。我用来自Haar Cascade的头部位置初始化来自卡尔曼滤波器的状态前置和后置变量,并且在进行camshift时调用kalman预测和校正以获得一些平滑。问题在于预测值和校正值始终是haar级联的起始值。我应该在做camshift时更新state pre或state post变量吗?卡尔曼预测和校正与起始值相同

private CvKalman Kf ; 
public CvMat measurement = new CvMat(2,1, MatrixType.F32C1); 
public int frameCounter = 0; 
public float[] A = {1,0,1,0, 0,1,0,1, 0,0,1,0, 0,0,0,1}; 
public float[] H = {1,0,0,0, 0,1,0,0}; 
public float[] Q = {0.0001f,0,0,0, 0,0.0001f,0,0, 0,0,0.0001f,0, 0,0,0,0.0001f}; 
public float[] R = {0.2845f,0.0045f,0.0045f,0.0455f}; 
public float[] P = {100,0,0,0, 0,100,0,0, 0,0,100,0, 0,0,0,100}; 

initkalman在做haar级联时被调用一次,并且跟踪窗口是初始头部位置。

void initKalman(CvRect trackinWindow){ 
    Kf = new CvKalman (4, 2, 0); 
    Marshal.Copy (A, 0, Kf.TransitionMatrix.Data, A.Length); 
    Marshal.Copy (H, 0, Kf.MeasurementMatrix.Data, H.Length); 
    Marshal.Copy (Q, 0, Kf.ProcessNoiseCov.Data, Q.Length); 
    Marshal.Copy (R, 0, Kf.MeasurementNoiseCov.Data, R.Length); 
    Marshal.Copy (P, 0, Kf.ErrorCovPost.Data, P.Length); 
    measurement.mSet (0, 0, trackingWindow.X); 
    measurement.mSet (1, 0, trackingWindow.Y); 

    Kf.StatePost.mSet(0,0,trackingWindow.X); 
    Kf.StatePost.mSet(1,0,trackingWindow.Y); 
    Kf.StatePost.mSet(2, 0, 0); 
    Kf.StatePost.mSet(3, 0, 0); 
} 

我所说的processKalman功能在每个迭代CAMSHIFT,现在正在跟踪窗口中的实际头部位置

CvPoint processKalman(CvRect trackingwindow) 
{ 

    CvMat prediction = Cv.KalmanPredict(Kf); 

    CvPoint predictionPoint; 
    predictionPoint.X = (int)prediction.DataArraySingle [0]; 
    predictionPoint.Y = (int)prediction.DataArraySingle [1]; 

    Debug.Log (predictionPoint.X); 

    measurement.mSet (0, 0, trackingWindow.X); 
    measurement.mSet (1, 0, trackingWindow.Y); 

    CvMat estimated = Cv.KalmanCorrect(Kf,measurement); 

    CvPoint auxCP; 

    auxCP.X = (int)estimated.DataArraySingle [0]; 
    auxCP.Y = (int)estimated.DataArraySingle [1]; 
    return auxCP; 

} 

这不是工作,始终只返回从this出色的初始头position.The家伙在调用预测函数之前,博客正在用实际测量值来更改状态帖子,但唯一改变的是,预测值和校正值现在与每帧的camshift头部位置相同。

+0

向我们展示您的卡尔曼预测和修正代码。这很可能出现在你错误的地方...... – MoonKnight

+0

我使用opencvsharp库中的标准方法。但就像我说的那样,我认为在状态变量前和变量初始化的时候有些事情是不正确的。也可能是标准方法的内部问题,因为我没有看到任何人,除了我提到的使用opencvsharp包装的博客。如果是这样,我想我需要按照你的建议制定我自己的方法。 –

+1

也许,但在上面我看不到数据的数组,只有一个点。如果你运行一个过滤器,当然你会得到起始状态向量。卡尔曼滤波器的整体思想是它是递归的,并以某种方式'训练'自己在谨慎的时间内找到与观测矢量相关的状态向量。如果这是来自一个众所周知的库,它可能会做正确的事情,你需要有一个时间序列的观察向量(可能是1D)y_ {n} [nPoints]并运行该过滤器。我会回去阅读更多关于实施... – MoonKnight

回答

3

我不会写这样的过滤器。我会为所有卡尔曼型滤波器使用以下合约。

public interface IKalmanFilter 
{ 
    /// <summary> 
    /// The current observation vector being used. 
    /// </summary> 
    Vector<double> Observation { get; } 

    /// <summary> 
    /// The best estimate of the current state of the system. 
    /// </summary> 
    Vector<double> State { get; } 

    /// <summary> 
    /// The covariance of the current state of the filter. Higher covariances 
    /// indicate a lower confidence in the state estimate. 
    /// </summary> 
    Matrix<double> StateVariance { get; } 

    /// <summary> 
    /// The one-step-ahead forecast error of y given the previous measurement. 
    /// </summary> 
    Vector<double> ForecastError { get; } 

    /// <summary> 
    /// The one-step ahead forecast error variance. 
    /// </summary> 
    Matrix<double> ForecastErrorVariance { get; } 

    /// <summary> 
    /// The Kalman Gain matrix. 
    /// </summary> 
    Matrix<double> KalmanGain { get; } 

    /// <summary> 
    /// Performs a prediction of the next state of the system. 
    /// </summary> 
    /// <param name="T">The state transition matrix.</param> 
    void Predict(Matrix<double> T); 

    /// <summary> 
    /// Perform a prediction of the next state of the system. 
    /// </summary> 
    /// <param name="T">The state transition matrix.</param> 
    /// <param name="R">The linear equations to describe the effect of the noise 
    /// on the system.</param> 
    /// <param name="Q">The covariance of the noise acting on the system.</param> 
    void Predict(Matrix<double> T, Matrix<double> R, Matrix<double> Q); 

    /// <summary> 
    /// Updates the state estimate and covariance of the system based on the 
    /// given measurement. 
    /// </summary> 
    /// <param name="y">The measurements of the system.</param> 
    /// <param name="T">The state transition matrix.</param> 
    /// <param name="Z">Linear equations to describe relationship between 
    /// measurements and state variables.</param> 
    /// <param name="H">The covariance matrix of the measurements.</param> 
    void Update(Vector<double> y, Matrix<double> T, 
     Matrix<double> Z, Matrix<double> H, Matrix<double> Q); 
} 

凡我自己的实现Vector<T>Matrix<T>是那些从MathNet.Numerics。我已经证明这一点的原因是,这种结构将使您能够对已过滤的数据集运行平滑递归并执行最大似然参数估计(如果您需要的话)。

一旦你使用上面的模板实现了线性高斯卡尔曼滤波器,你可以在时间序列中为每个数据点的循环中的一些数据集调用它(注意循环没有在过滤代码)。对于一维状态/观察向量,我们可以这样写:

// Set default initial state and variance. 
a = Vector<double>.Build.Dense(1, 0.0d); 
P = Matrix<double>.Build.Dense(1, 1, Math.Pow(10, 7)); 

// Run the filter. 
List<double> filteredData = new List<double>(); 
IKalmanFilter filter = new KalmanFilter(a, P); 
for (int i = 0; i < Data.Length; i++) 
{ 
    filter.Predict(T, R, Q); 
    Vector<double> v = DenseVector.Create(1, k => Convert.ToDouble(Data[i])); 
    filter.Update(v, T, Z, H, Q); 

    // Now to get the filtered state values, you use. (0 as it is one-dimensional data) 
    filteredData.Add(filter.State[0]); 
} 

我知道这不是使用你的代码,但我希望它有一些帮助。如果您决定要沿着这条路线走下去,我会用实际卡尔曼滤波器代码来帮助您...