2012-05-02 20 views
6

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:

  1. 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ść?)
  2. Czy nie możemy ustawić każdej matrycy na matrycę tożsamości?
  3. 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!

Odpowiedz

4

H [] powinna być tożsamością, jeśli mierzy się bezpośrednio z obrazu. Jeśli masz 4 pomiary i 0 wartości na przekątnej, robisz te spodziewane pomiary (x * H) 0, kiedy to nie jest prawdą. Wtedy innowacja (z- x * H) na filtrze kalmana będzie wysoka.

R [] powinny być również przekątne, chociaż kowariancja błędu pomiaru może być różna od jednej. Jeśli masz znormalizowane współrzędne (szerokość = wysokość = 1), R może wynosić około 0.01. Jeśli masz do czynienia ze współrzędnymi pikselowymi, R = diagonal_ones oznacza błąd jednego piksela, i to jest w porządku. Możesz spróbować z 2,3,4, itd ...

Twoja macierz przejścia A [], która ma propagować stan w każdej ramce, wygląda jak macierz przejścia dla stanu złożonego z x, y, v_x i v_y. Nie wspominasz o prędkości w swoim modelu, mówisz tylko o pomiarach. Bądź ostrożny, nie mieszaj stanu (opisuje pozycję twarzy) z pomiarami (używany do aktualizacji stanu). Twój stan może być pozycją, prędkością i przyspieszeniem, a twoje pomiary mogą wynosić n punktów na obrazie. Lub pozycja x i y twarzy.

Mam nadzieję, że to pomoże.

+1

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