Предсказание и коррекция Калмана такие же, как начальные значения

Я внедряю фильтр Калмана, который получает реальные измерения от отслеживания головы кулачкового переключения после предварительного обнаружения лица с помощью каскада Хаара. Я инициализирую переменные состояния до и после состояния из фильтра Калмана с положением головы из каскада Хаара и вызываю предсказание и исправление Калмана при выполнении кулачкового переключения, чтобы получить некоторое сглаживание. Проблема в том, что предсказанные и скорректированные значения всегда являются начальными значениями каскада Хаара. Должен ли я обновлять переменные состояния до или после состояния во время переключения распредвала?

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 вызывается один раз при выполнении каскада хаара, а окно отслеживания — это начальное положение головы.

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;

}

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


person Jack Eisenherz    schedule 26.02.2014    source источник
comment
Покажите нам свой код предсказания и коррекции Калмана. Скорее всего, здесь вы ошибаетесь...   -  person MoonKnight    schedule 26.02.2014
comment
Я использую стандартные методы из библиотеки opencvsharp. Но, как я уже сказал, я думаю, что что-то не так с переменными состояния pre и post и их инициализацией. Также может быть внутренняя проблема со стандартными методами, так как я не видел никого, кроме парня из блога, о котором я упоминал, который использует оболочку opencvsharp. Если это так, я думаю, мне нужно будет сделать свой собственный метод, как вы предложили.   -  person Jack Eisenherz    schedule 26.02.2014
comment
Да, может быть, но в приведенном выше я не вижу массива данных, только одну точку. Если вы запустите фильтр для одной точки, конечно, вы вернете вектор начального состояния. Вся идея фильтра Калмана заключается в том, что он является рекурсивным и в некотором роде «обучается» находить вектор состояния, связанный с вектором наблюдения, за дискретное время. Если это из известной библиотеки, то, скорее всего, все сделано правильно, вам нужно иметь временной ряд векторов наблюдения (может быть 1D) y_{n}[nPoints] и запустить для него фильтр. Я бы вернулся и прочитал больше о реализации...   -  person MoonKnight    schedule 27.02.2014
comment
хорошо понял свою ошибку!! Мне не хватает массивов коррекции и оценки, в которых я храню прогноз и коррекцию! Большое тебе спасибо. Я с ума сходил от этого!!!   -  person Jack Eisenherz    schedule 27.02.2014


Ответы (1)


Я бы не стал писать ваш фильтр так. Я бы использовал следующий контракт для всех фильтров типа Калмана.

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

Я знаю, что это не использует ваш код, но я надеюсь, что это поможет. Если вы решите пойти по этому пути, я помогу вам с фактическим кодом фильтра Калмана...

person MoonKnight    schedule 26.02.2014