Od kilku dni badam działanie filtra Kalmana, aby poprawić wydajność mojego programu do wykrywania twarzy. Na podstawie zebranych informacji zestawiłem kod. Kod części filtra Kalmana jest następujący.Filtry Kalmana z czterema parametrami wejściowymi
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;
}
W części wykrywania twarzy (nie pokazano), dla wykrytej twarzy zostanie wyświetlone pole. "X, Y, faceWidth i faceHeight" są współrzędnymi pola, a szerokość i wysokość przechodzi do filtra Kalmana. "img1" jest bieżącą klatką filmu wideo.
Wyniki:
Chociaż ja dostać dwa nowe prostokąty z "state_post i danych„przewidywania”(jak widać w kodzie), żaden z nich nie wydają się być bardziej stabilny niż w pierwszym oknie sporządzonej bez filtr Kalmana.
Oto moje pytania:
- matryce są inicjowane przejście (macierz A, H macierzą pomiaru itp) odpowiednie dla tego czwartego wejścia przypadku? (np. 4 * 4 matryce dla czterech wejść?)
- Czy nie możemy ustawić każdej matrycy na matrycę tożsamości?
- Czy sposób, w jaki postępowałem, aż do prawidłowego wykreślenia prostokątów? Śledziłem przykłady w this oraz w książce "Learning OpenCV", która nie korzysta z zewnętrznych wejść.
Każda pomoc w tej sprawie byłaby bardzo cenna!
Dziękuję bardzo za odpowiedź informacyjną! Jednak niczego nie zmieniłem, ponieważ zdecydowałem się pominąć filtr Kalmana na tym etapie. Ale jestem pewien, że ktoś znajdzie twoją odpowiedź pomocną! Dzięki jeszcze raz. – Kavo