我实现了一个卡尔曼滤波器,该滤波器在先前使用 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 头位置相同。