He estado estudiando el funcionamiento del filtro de Kalman durante un par de días para mejorar el rendimiento de mi programa de detección de rostros. De la información que he reunido, he reunido un código. El código para la parte del filtro de Kalman es el siguiente.Filtros de Kalman con cuatro parámetros de entrada
int Kalman(int X,int faceWidth,int Y,int faceHeight, IplImage *img1){
CvRandState rng;
const float T = 0.1;
// Initialize Kalman filter object, window, number generator, etc
cvRandInit(&rng, 0, 1, -1, CV_RAND_UNI);
//IplImage* img = cvCreateImage(cvSize(500,500), 8, 3);
CvKalman* kalman = cvCreateKalman(4, 4, 0 );
// Initializing with random guesses
// state x_k
CvMat* state = cvCreateMat(4, 1, CV_32FC1);
cvRandSetRange(&rng, 0, 0.1, 0);
rng.disttype = CV_RAND_NORMAL;
cvRand(&rng, state);
// Process noise w_k
CvMat* process_noise = cvCreateMat(4, 1, CV_32FC1);
// Measurement z_k
CvMat* measurement = cvCreateMat(4, 1, CV_32FC1);
cvZero(measurement);
/* create matrix data */
const float A[] = {
1, 0, T, 0,
0, 1, 0, T,
0, 0, 1, 0,
0, 0, 0, 1
};
const float H[] = {
1, 0, 0, 0,
0, 0, 0, 0,
0, 0, 1, 0,
0, 0, 0, 0
};
//Didn't use this matrix in the end as it gave an error:'ambiguous call to overloaded function'
/* const float P[] = {
pow(320,2), pow(320,2)/T, 0, 0,
pow(320,2)/T, pow(320,2)/pow(T,2), 0, 0,
0, 0, pow(240,2), pow(240,2)/T,
0, 0, pow(240,2)/T, pow(240,2)/pow(T,2)
}; */
const float Q[] = {
pow(T,3)/3, pow(T,2)/2, 0, 0,
pow(T,2)/2, T, 0, 0,
0, 0, pow(T,3)/3, pow(T,2)/2,
0, 0, pow(T,2)/2, T
};
const float R[] = {
1, 0, 0, 0,
0, 0, 0, 0,
0, 0, 1, 0,
0, 0, 0, 0
};
//Copy created matrices into kalman structure
memcpy(kalman->transition_matrix->data.fl, A, sizeof(A));
memcpy(kalman->measurement_matrix->data.fl, H, sizeof(H));
memcpy(kalman->process_noise_cov->data.fl, Q, sizeof(Q));
//memcpy(kalman->error_cov_post->data.fl, P, sizeof(P));
memcpy(kalman->measurement_noise_cov->data.fl, R, sizeof(R));
//Initialize other Kalman Filter parameters
//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(1e-5));
/* choose initial state */
kalman->state_post->data.fl[0]=X;
kalman->state_post->data.fl[1]=faceWidth;
kalman->state_post->data.fl[2]=Y;
kalman->state_post->data.fl[3]=faceHeight;
//cvRand(&rng, kalman->state_post);
/* predict position of point */
const CvMat* prediction=cvKalmanPredict(kalman,0);
//generate measurement (z_k)
cvRandSetRange(&rng, 0, sqrt(kalman->measurement_noise_cov->data.fl[0]), 0);
cvRand(&rng, measurement);
cvMatMulAdd(kalman->measurement_matrix, state, measurement, measurement);
//Draw rectangles in detected face location
cvRectangle(img1,
cvPoint(kalman->state_post->data.fl[0], kalman->state_post->data.fl[2]),
cvPoint(kalman->state_post->data.fl[1], kalman->state_post->data.fl[3]),
CV_RGB(0, 255, 0), 1, 8, 0);
cvRectangle(img1,
cvPoint(prediction->data.fl[0], prediction->data.fl[2]),
cvPoint(prediction->data.fl[1], prediction->data.fl[3]),
CV_RGB(0, 0, 255), 1, 8, 0);
cvShowImage("Kalman",img1);
//adjust kalman filter state
cvKalmanCorrect(kalman,measurement);
cvMatMulAdd(kalman->transition_matrix, state, process_noise, state);
return 0;
}
En la parte de detección de caras (no mostrada), se dibuja una caja para la cara detectada. 'X, Y, faceWidth y faceHeight' son coordenadas de la caja y el ancho y la altura pasaron al filtro de Kalman. 'img1' es el fotograma actual de un video.
Resultados:
Aunque me pongo dos nuevos rectángulos de los datos de 'predicción' (como se ve en el código) 'state_post' y, ninguno de ellos parecen ser más estable que el cuadro inicial elaborado sin el filtro de Kalman
Aquí están mis preguntas:
- son las matrices inicializadas (transición de la matriz A, matriz de medición H etc.), correcto para este cuatro caso de entrada? (por ejemplo, 4 * 4 matrices para cuatro entradas?)
- ¿No podemos establecer que cada matriz sea una matriz de identidad?
- ¿El método que seguí para trazar los rectángulos es teóricamente correcto? Seguí los ejemplos en this y el libro 'Learning OpenCV' que no usa entradas externas.
¡Cualquier ayuda con respecto a esto sería muy apreciada!
¡Muchas gracias por la respuesta informativa! No pude cambiar nada porque decidí dejar de lado el filtro de Kalman para esta etapa. ¡Pero estoy seguro de que alguien encontrará útil su respuesta! Gracias de nuevo. – Kavo