4

我实现了一个卡尔曼滤波器,该滤波器在先前使用 Haar Cascade 检测到面部之后接收来自 camshift 头部跟踪的实际测量值。我使用来自 Haar Cascade 的头部位置初始化来自卡尔曼滤波器的状态前和状态后变量,并在进行 camshift 时调用卡尔曼预测和校正以获得一些平滑。问题是预测值和校正值始终是 haar 级联的起始值。在进行 camshift 时我应该更新状态前变量还是状态后变量?

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);
}

我在每次 camshift 迭代中调用 processKalman 函数,现在正在跟踪窗口实际头部位置

    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;

}

这是行不通的,总是只返回初始头部位置。来自这个优秀博客的人在调用预测函数之前用实际测量值更改状态帖子,但这样做对我来说唯一改变的是预测和修正后的值现在与每帧的 camshift 头位置相同。

4

1 回答 1

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]);
}

我知道这没有使用您的代码,但我希望它有所帮助。如果您决定要走这条路,我将帮助您使用实际的卡尔曼滤波器代码......

于 2014-02-26T16:25:01.650 回答