2012-05-02 11 views
6

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:

  1. 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?)
  2. ¿No podemos establecer que cada matriz sea una matriz de identidad?
  3. ¿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!

Respuesta

4

H [] debe ser identidad si mide directamente desde la imagen. Si tiene 4 medidas y hace 0 valores en la diagonal, está haciendo esas medidas esperadas (x * H) 0, cuando no es verdadero. Entonces la innovación (z- x * H) en el filtro de kalman será alta.

R [] también debe ser diagonal, aunque la covarianza del error de medición puede ser diferente de uno. Si tiene coordenadas normalizadas (ancho = altura = 1), R podría ser algo así como 0.01. Si se trata de coordenadas de píxeles, R = diagonal_ones significa un error de un píxel, y eso está bien. Puede probar con 2,3,4, etc ...

Su matriz de transición A [], que se supone que debe propagar el estado en cada cuadro, parece una matriz de transición para un estado compuesto por x, y, v_x y v_y. No mencionas la velocidad en tu modelo, solo hablas de medidas. Tenga cuidado, no confunda State (describe la posición de la cara) con Measurements (usado para actualizar el estado). Su estado puede ser posición, velocidad y aceleración, y sus medidas pueden ser n puntos en la imagen. O la posición xey de la cara.

Espero que esto ayude.

+1

¡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

Cuestiones relacionadas