Ho studiato il funzionamento del filtro Kalman per un paio di giorni per migliorare le prestazioni del mio programma di rilevamento del volto. Dalle informazioni che ho raccolto ho messo insieme un codice. Il codice per la parte del filtro di Kalman è il seguente.Filtri Kalman con quattro parametri di input
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;
}
Nella parte di rilevamento del volto (non mostrata), viene disegnata una casella per il viso rilevato. 'X, Y, faceWidth e faceHeight' sono le coordinate della casella e la larghezza e l'altezza passate nel filtro di Kalman. 'img1' è il frame corrente di un video.
Risultati:
Anche se io capisco due nuovi rettangoli dal 'state_post' e dei dati 'predizione' (come si vede nel codice), nessuno di loro sembrano essere più stabili rispetto al dialogo iniziale disegnato senza il filtro di Kalman.
Ecco le mie domande:
- Sono le matrici inizializzati (transizione matrice A, matrice di misura H, ecc), corretto per questo caso di ingresso di quattro? (es. 4 * 4 matrici per quattro ingressi?)
- Non possiamo impostare ogni matrice come matrice di identità?
- Il metodo che ho seguito fino alla creazione dei rettangoli è teoricamente corretto? Ho seguito gli esempi in this e nel libro "Learning OpenCV" che non utilizza input esterni.
Qualsiasi aiuto in merito sarebbe molto apprezzato!
Grazie mille per la risposta informativa! Non ho potuto cambiare nulla, anche se ho deciso di lasciare fuori il filtro di Kalman per questa fase. Ma sono sicuro che qualcuno troverà utile la tua risposta! Grazie ancora. – Kavo