Перейти к содержимому
Compvision.ru
RinOS

Фильтр Калмана

Recommended Posts

Всем привет!

В книжке по OpenCV есть пример по фильтру Калмана, несколько раз пытался понять листинг, но ни чего непонял...

К тому же тут еще не понятно зачем введены шумы (x_k).

Обясните пожалуйста этот листинг, можно вырезать все лишнее оставив, нужное, а именно (предсказывать где будет объект в следующий момент времени).

#define phi2xy(mat)												  \

  cvPoint( cvRound(img->width/2 + img->width/3*cos(mat->data.fl[0])),\

	cvRound( img->height/2 - img->width/3*sin(mat->data.fl[0])) )


int main(int argc, char** argv) {


	// Initialize, create Kalman Filter object, window, random number

	// generator etc.

	//

	cvNamedWindow( "Kalman", 1 );

	CvRandState rng;

	cvRandInit( &rng, 0, 1, -1, CV_RAND_UNI );


	IplImage* img = cvCreateImage( cvSize(500,500), 8, 3 );

	CvKalman* kalman = cvCreateKalman( 2, 1, 0 );

	// state is (phi, delta_phi) - angle and angular velocity

	// Initialize with random guess.

	//

	CvMat* x_k = cvCreateMat( 2, 1, CV_32FC1 );

	cvRandSetRange( &rng, 0, 0.1, 0 );

	rng.disttype = CV_RAND_NORMAL;

	cvRand( &rng, x_k );


	// process noise

	//

	CvMat* w_k = cvCreateMat( 2, 1, CV_32FC1 );


	// measurements, only one parameter for angle

	//

	CvMat* z_k = cvCreateMat( 1, 1, CV_32FC1 );

	cvZero( z_k );


	// Transition matrix 'F' describes relationship between

	// model parameters at step k and at step k+1 (this is 

	// the "dynamics" in our model.

	//

	const float F[] = { 1, 1, 0, 1 };

	memcpy( kalman->transition_matrix->data.fl, F, sizeof(F));

	// 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(1));


	// choose random initial state

	//

	cvRand( &rng, kalman->state_post );


	while( 1 ) {

		// predict point position

		const CvMat* y_k = cvKalmanPredict( kalman, 0 );


		// generate measurement (z_k)

		//

		cvRandSetRange( 

			&rng, 

			0, 

			sqrt(kalman->measurement_noise_cov->data.fl[0]), 

			0 

		);

		cvRand( &rng, z_k );

		cvMatMulAdd( kalman->measurement_matrix, x_k, z_k, z_k );

		// plot points (eg convert to planar co-ordinates and draw)

		//

		cvZero( img );

		cvCircle( img, phi2xy(z_k), 4, CVX_YELLOW );   // observed state

		cvCircle( img, phi2xy(y_k), 4, CVX_WHITE, 2 ); // "predicted" state

		cvCircle( img, phi2xy(x_k), 4, CVX_RED );	  // real state

		cvShowImage( "Kalman", img );

		// adjust Kalman filter state

		//

		cvKalmanCorrect( kalman, z_k );


		// Apply the transition matrix 'F' (eg, step time forward)

		// and also apply the "process" noise w_k.

		//

		cvRandSetRange( 

			&rng, 

			0, 

			sqrt(kalman->process_noise_cov->data.fl[0]), 

			0 

			);

		cvRand( &rng, w_k );

		cvMatMulAdd( kalman->transition_matrix, x_k, w_k, x_k );


		// exit if user hits 'Esc'

		if( cvWaitKey( 100 ) == 27 ) break;

	}

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Листинг попытаюсь пояснить (что сам понял) потом. А пока вот что перевел (очень сырой вариант), может чего добавите :)

Фильтр_Кальмана.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Листинг попытаюсь пояснить (что сам понял) потом. А пока вот что перевел (очень сырой вариант), может чего добавите :)

Фильтр_Кальмана.rar

Есть еще такой класс для двумерных координат, откопал на просторах и-нета (перевел часть комментов, но не тестил правда пока):

Вот файл: Kalman2.rar,

А вот что внутри:

class KalmanFilter
{
public:
KalmanFilter();
~KalmanFilter();

virtual void predictionBegin(float x,float y);
virtual void predictionUpdate(float x,float y);
virtual void predictionReport(CvPoint &pnt);

private:
CvKalman *m_pKalmanFilter;
CvRandState rng;
CvMat* state;
CvMat* process_noise;
CvMat* measurement;
CvMat* measurement_noise;
bool m_bMeasurement;
clock_t m_timeLastMeasurement;
CRITICAL_SECTION mutexPrediction;
};

// Инициализация фильтра Кальмана

KalmanFilter::KalmanFilter()
{
m_timeLastMeasurement = clock();
int dynam_params = 4; // x,y,dx,dy
int measure_params = 2;
m_pKalmanFilter = cvCreateKalman(dynam_params, measure_params);
state = cvCreateMat( dynam_params, 1, CV_32FC1 );

// Генератор случайных чисел
cvRandInit( &rng, 0, 1, -1, CV_RAND_UNI );
cvRandSetRange( &rng, 0, 1, 0 );
rng.disttype = CV_RAND_NORMAL;
cvRand( &rng, state );

process_noise = cvCreateMat( dynam_params, 1, CV_32FC1 ); // (w_k)
measurement = cvCreateMat( measure_params, 1, CV_32FC1 ); // two parameters for x,y (z_k)
measurement_noise = cvCreateMat( measure_params, 1, CV_32FC1 ); // two parameters for x,y (v_k)
cvZero(measurement);

// F matrix data
// F is transition matrix. It relates how the states interact
// For single input fixed velocity the new value
// depends on the previous value and velocity- hence 1 0 1 0
// on top line. Новое значение скорости не зависит от предыдущего
// значения координаты, и зависит только от предыдущей скорости- поэтому 0 1 0 1 on second row
const float F[] =
{
1, 0, 1, 0,//x + dx
0, 1, 0, 1,//y + dy
0, 0, 1, 0,//dx = dx
0, 0, 0, 1,//dy = dy
};
memcpy( m_pKalmanFilter->transition_matrix->data.fl, F, sizeof(F));
cvSetIdentity( m_pKalmanFilter->measurement_matrix, cvRealScalar(1) ); // (H)
cvSetIdentity( m_pKalmanFilter->process_noise_cov, cvRealScalar(1e-5) ); // (Q)
cvSetIdentity( m_pKalmanFilter->measurement_noise_cov, cvRealScalar(1e-1) ); // (R)
cvSetIdentity( m_pKalmanFilter->error_cov_post, cvRealScalar(1));

// choose random initial state
cvRand( &rng, m_pKalmanFilter->state_post );

InitializeCriticalSection(&mutexPrediction);
}

KalmanFilter::~KalmanFilter()
{
// Деструктор
cvReleaseMat( &state );
cvReleaseMat( &process_noise );
cvReleaseMat( &measurement );
cvReleaseMat( &measurement_noise );
cvReleaseKalman( &m_pKalmanFilter );

DeleteCriticalSection(&mutexPrediction);
}



// Устанавливаем значения переменных фильтра на первом шаге
// Если этого не сделать, то объект не будет трекаться
void KalmanFilter::predictionBegin(float x,float y)
{
//В переменной m_pKalmanFilter->state_post хранится предыдущее состояние

m_pKalmanFilter->state_post->data.fl[0] = x; //координата x
m_pKalmanFilter->state_post->data.fl[1] = y; //координата y
m_pKalmanFilter->state_post->data.fl[2] = (float)0; //dx - скорость по x
m_pKalmanFilter->state_post->data.fl[3] = (float)0; //dy - скорость по y
}

void KalmanFilter::predictionUpdate(float x,float y)
{
EnterCriticalSection(&mutexPrediction);
state->data.fl[0] = x; //center x
state->data.fl[1] = y; //center y
m_bMeasurement = true;
LeaveCriticalSection(&mutexPrediction);
}

void KalmanFilter::predictionReport(CvPoint &pnt)
{
clock_t timeCurrent = clock();

EnterCriticalSection(&mutexPrediction);

const CvMat* prediction = cvKalmanPredict( m_pKalmanFilter, 0 );
pnt.x = prediction->data.fl[0];
pnt.y = prediction->data.fl[1];
// Если мы получили действительные данные недавно, тогда используем полученные данные для корректировки
// состояния фильтра. Если мы не получили данные, тогда корректируем состояние фильтра, используя предсказанные значения
if (m_bMeasurement) //(timeCurrent - m_timeLastMeasurement < TIME_OUT_LOCATION_UPDATE) // используем действительные данные
{
m_bMeasurement = false;

}
// Обычно фильтр работает быстрее чем поступают данные измерений..
// Таким образом, можно дать фильтру брать данные из предсказанных значений в промежутках между измерениями
// (делает работу трекера более плавной)
else // используем предсказанные данные
{
state->data.fl[0] = pnt.x;
state->data.fl[1] = pnt.y;
}

// генерируем шум измерения noise(z_k)
cvRandSetRange( &rng, 0, sqrt(m_pKalmanFilter->measurement_noise_cov->data.fl[0]), 0 );
cvRand( &rng, measurement_noise );

// zk = Hk * xk + vk
// measurement = measurement_error_matrix * current_state + measurement_noise
cvMatMulAdd( m_pKalmanFilter->measurement_matrix, state, measurement_noise, measurement );

// уточняем состояние фильтра
cvKalmanCorrect( m_pKalmanFilter, measurement );

// гененрируем шум процесса(w_k)
cvRandSetRange( &rng, 0, sqrt(m_pKalmanFilter->process_noise_cov->data.fl[0]), 0 );
cvRand( &rng, process_noise );

// xk = F * xk-1 + B * uk + wk
// state = transition_matrix * previous_state + control_matrix * control_input + noise
cvMatMulAdd( m_pKalmanFilter->transition_matrix, state, process_noise, state );
LeaveCriticalSection(&mutexPrediction);
}[/code]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Есть еще такой класс для двумерных координат, откопал на просторах и-нета (перевел часть комментов, но не тестил правда пока):

За пример спасибо) С помощью него я понял что не могу использовать фильтр Кальмана в моём случае(

Моя цель была найти объект в следующем кадре... Но что бы передать фильтру Кальмана predictionUpdate() надо знать где этот объект находиться...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Пример фильтра Кальмана + запись видео в файл. Используется OpenCV2.0. Его DLL надо покидать в видное программе место (можно к exe-шнику в папку)

Kalman_puck.jpg

Архив с проектом: kalman_track.rar

У меня путь к нему: C:\Program Files\Borland\CBuilder6\Projects\Cv2Programs\kalman_track\

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Помойму такие вещи можно складировать в вике, например в разделе туториалы. В дальнейшем будет проще искать и возможно дорабатывать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Помойму такие вещи можно складировать в вике, например в разделе туториалы. В дальнейшем будет проще искать и возможно дорабатывать.

Спасибо за совет.

Я так и сделаю, пока не хочу там беспорядка.

Форум просмотрю и вынесу такие примеры туда, к тому же еще текст надо к нему написать.

Пока тут полежит - пройдет проверку, на нужность и заодно узнаю, какие вопросы вызывает программа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Пример фильтра Кальмана + запись видео в файл. Используется OpenCV2.0. Его DLL надо покидать в видное программе место (можно к exe-шнику в папку)

Спасибо, пример очень порадовал!

Как бы его переделать под VS2008...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Как бы его переделать под VS2008...
Если автор не против, то выложу переделку - делал как-то для себя, поиграть. Немного перегруппировал код, отформатировал по своему вкусу, но всё работает также как и в оригинале:
#include "stdafx.h"
#include <highgui.h>
#include <cv.h>

#pragma comment(lib, "cv.lib")
#pragma comment(lib, "cxcore.lib")
#pragma comment(lib, "highgui.lib")
////////////////////////////////////////////////////////////////////////////
//function to find the biggest blob and to get the top left position
CvPoint2D32f findBigBlob(IplImage *mask)
{
int maxval = 0;
int minval = 100;

//начинаем поиск контуров
CvMemStorage *storage = cvCreateMemStorage(0);
CvContourScanner traverse = cvStartFindContours(mask, storage, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

//находим контуры с длиной периметра между minval и maxval
CvSeq *mContour = 0;
for (CvSeq *contour = cvFindNextContour(traverse); contour; contour = cvFindNextContour(traverse))
{
int contourarea = (int)abs(cvContourArea(contour, CV_WHOLE_SEQ));
if (contourarea > maxval)
{
mContour = contour;
maxval = contourarea;
}
}

CvPoint2D32f ret_val = cvPoint2D32f(-1.0, -1.0);
if (maxval > minval)
{
//находим центр масс
CvMoments moments;
cvMoments(mContour, &moments, 0);
ret_val.x = (float)(moments.m10 / moments.m00);
ret_val.y = (float)(moments.m01 / moments.m00);
}

//освобождаем память
cvEndFindContours(&traverse);
cvReleaseMemStorage(&storage);

return ret_val;
}
////////////////////////////////////////////////////////////////////////////
//находим участки, подходящие нам по цвету (шайба)
void region_color_range(const IplImage *color, IplImage *mask, uchar bmin, uchar bmax, uchar gmin, uchar gmax, uchar rmin, uchar rmax)
{
uchar *dst_ptr = (uchar *)mask->imageData;
for (const uchar *src_ptr = (uchar *)color->imageData, *stop = src_ptr + color->imageSize; src_ptr != stop; src_ptr += color->nChannels)
{
uchar b = src_ptr[0];
uchar g = src_ptr[1];
uchar r = src_ptr[2];
//проверяем диапазон составляющих цвета
if (b <= bmax && b >= bmin &&
g <= gmax && g >= gmin &&
r <= rmax && r >= rmin)
*dst_ptr = 255;
else
*dst_ptr = 0;

++dst_ptr;
}
}
////////////////////////////////////////////////////////////////////////////
int main()
{
//параметры, для идентификации шайбы по цвету
uchar bmin = 0;
uchar bmax = 51;
uchar gmin = 120;
uchar gmax = 225;
uchar rmin = 102;
uchar rmax = 235;

CvMat *measurement = cvCreateMat(2, 1, CV_32FC1);
cvZero(measurement);

CvRNG rng = cvRNG(-1);

CvMat *state = cvCreateMat(4, 1, CV_32FC1); // (x, y, deltax, deltay)
cvRandArr(&rng, state, CV_RAND_NORMAL, cvRealScalar(0), cvRealScalar(0.1));

//стандартный набор функций для фильтра кальмана
CvKalman *kalman = cvCreateKalman(4, 2, 0); //4 переменных состояния, 2 переменных измерения

float deltatime = 50.f; //приращение времени
float transition_matrix[] = { 1, 0, deltatime, 0, 0, 1, 0, deltatime, 0, 0, 1, 0, 0, 0, 0, 1}; //transition matrix
memcpy(kalman->transition_matrix->data.fl, transition_matrix, sizeof(transition_matrix));

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(1));
//выбираем случайное начальное состояние
cvRandArr(&rng, kalman->state_post, CV_RAND_NORMAL, cvRealScalar(0), cvRealScalar(0.1));

cvNamedWindow("frame", 1);
cvNamedWindow("color_segm", 1);
cvNamedWindow("contours", 1);

CvCapture *video = cvCaptureFromAVI("vid1.avi");
IplImage *mask = NULL;
for (IplImage *frame = cvQueryFrame(video); frame; frame = cvQueryFrame(video))
{
if (!mask)
mask = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 1);
//находим положение шайбы, используя поиск по цвету
region_color_range(frame, mask, bmin, bmax, gmin, gmax, rmin, rmax);

cvShowImage("color_segm", mask);

CvPoint2D32f position = findBigBlob(mask);

cvShowImage("contours", mask);

const CvMat *kalman_predict = cvKalmanPredict(kalman, 0);
float predict_x = kalman_predict->data.fl[0];
float predict_y = kalman_predict->data.fl[1];
if (position.x < 0.0)
{
//уточняем используя предсказание
measurement->data.fl[0] = predict_x;
measurement->data.fl[1] = predict_y;
}
else
{
//уточняем, используя данные измерений
measurement->data.fl[0] = position.x;
measurement->data.fl[1] = position.y;
}

//Предсказанное и измеренное положение центра объекта
cvDrawCircle(frame, cvPoint((int)position.x, (int)position.y), 3, cvScalar(255, 255, 255), -1, 8, 0);
cvDrawCircle(frame, cvPoint((int)predict_x, (int)predict_y), 3, cvScalar(0, 0, 0), -1, 8, 0);
//обновляем состояние фильтра
cvKalmanCorrect(kalman, measurement);

cvWaitKey(100);

cvShowImage("frame", frame);
}

cvReleaseCapture(&video);
if (mask)
cvReleaseImage(&mask);
cvDestroyWindow("frame");
cvDestroyWindow("color_segm");
cvDestroyWindow("contours");

return 0;
}
////////////////////////////////////////////////////////////////////////////[/codebox]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Если автор не против, то выложу переделку - делал как-то для себя, поиграть. Немного перегруппировал код, отформатировал по своему вкусу, но всё работает также как и в оригинале:

Спасибо большое за помощь!

Буду теперь пытаться решить поставленную задачу:

Вместо шарика у меня должно быть лицо человека, и прямоугольник, захватывающий его, прямоугольник мне и надо сопровождать, при перемещении лица.

В идеале хотелось бы вообще нужное лицо из толпы выделять мышкой и дальше его сопровождать...

Буду пробовать :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Подниму темку)

Как использовать фильтр Калмана для 3D трекинга?

Кому ни будь попадалась на руки реализация по мимо этой: http://www.roninworks.com/?p=218

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Презентация с хорошим описанием есть здесь: http://www.probabilistic-robotics.org/

(книжка, кстати тоже интересная :) )

Из объяснения понятно, что для корректного использования фильтра нужна динамическая модель системы, которая затем преобразуется в матрицу переходов.Матрица переходов содержит вероятности переходов из состояния A в состояние Б. См. Марковские процессы.

Для фильтрации координат, обычно, в качестве модели используют линеаризованные дифференциальные уравнения движения. В случае линейных перемещений они тривиальны X'=X'+X"*dt; X=X+X'*dt;. В случае добавления вращения лучше перейти к плюккеровым (Plukker) координатам и винтовому исчислению. Вот тут уже посложнее будет :) и матрицы будут 6х6.

Именно вследствие сильной зависимости от параметров модели (механических, статистических, и т.д.), как мне кажется, универсальные реализации и не получили широкого распространения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

>В случае добавления вращения

Наверно глубины? (третье измерение)

Буквально прям сейчас нашел реализацию, вроде 3D но матрица создается 6х3, оно ли это))?

#ifndef _KALMAN_FILTER_H_

#define _KALMAN_FILTER_H_



#include <vector>



#include <cv.h>

#include "base.h"



#include "Structures/Vector.h"

#include "Structures/Calibration.h"



namespace windage

{

        namespace Algorithms

        {

                /**

                 * @defgroup Algorithms Algorithm classes

                 * @brief

                 *              algorithm classes

                 * @addtogroup Algorithms

                 * @{

                 */



                /**

                 * @defgroup AlgorithmsPoseEstimator Pose Estimator

                 * @brief

                                camera pose estimator in 3D

                 * @addtogroup AlgorithmsPoseEstimator

                 * @{

                 */



                /**

                 * @brief       class for kalman filtering to prevent zitering

                 * @author      Woonhyuk Baek

                 */

                class DLLEXPORT KalmanFilter

                {

                private:

                        /** Tx, Ty, Tz, dTx, dTy, dTz */

                        CvKalman* kalman;

                        CvMat* measurement;



                public:

                        virtual char* GetFunctionName(){return "KalmanFilter";};

                        KalmanFilter()

                        {

                                kalman = cvCreateKalman( 6, 3, 0 );

                                measurement = cvCreateMat( 3, 1, CV_32FC1 );

                                this->Initialize();

                        }

                        ~KalmanFilter()

                        {

                                if(kalman) cvReleaseKalman(&kalman);

                                if(measurement) cvReleaseMat(&measurement);

                        }



                        void Initialize();

                        windage::Vector3 Predict();

                        bool Correct(windage::Vector3 T);

                };

                /** @} */ // addtogroup AlgorithmsPoseEstimator

                /** @} */ // addtogroup Algorithms

        }

}

#endif // _KALMAN_FILTER_H_


#include "Algorithms/KalmanFilter.h"

using namespace windage;

using namespace windage::Algorithms;



void KalmanFilter::Initialize()

{

        const float A[] = { 1, 0, 0, 1, 0, 0,

                                                0, 1, 0, 0, 1, 0,

                                                0, 0, 1, 0, 0, 1,

                                                0, 0, 0, 1, 0, 0,

                                                0, 0, 0, 0, 1, 0,

                                                0, 0, 0, 0, 0, 1,};



        memcpy( this->kalman->transition_matrix->data.fl, A, sizeof(A));

        cvSetIdentity( this->kalman->measurement_matrix, cvRealScalar(1) );

        cvSetIdentity( this->kalman->process_noise_cov, cvRealScalar(1e-5) );

        cvSetIdentity( this->kalman->measurement_noise_cov, cvRealScalar(1e-1) );

        cvSetIdentity( this->kalman->error_cov_post, cvRealScalar(1));

}



windage::Vector3 KalmanFilter::Predict()

{

        windage::Vector3 prediction;



        const CvMat* predictionMat = cvKalmanPredict( this->kalman, 0 );



        prediction.x = (double)predictionMat->data.fl[0];

        prediction.y = (double)predictionMat->data.fl[1];

        prediction.z = (double)predictionMat->data.fl[2];



        return prediction;

}



bool KalmanFilter::Correct(windage::Vector3 T)

{

        measurement->data.fl[0] = (float)T.x;

        measurement->data.fl[1] = (float)T.y;

        measurement->data.fl[2] = (float)T.z;



        cvKalmanCorrect( kalman, measurement );

        return true;

}

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Извиняюсь, напутал матрицы с учетом вращения будут матрица А например 12х12 (если не учитывать ускорения). Три линейных координаты это как раз тот тривиальный случай. Если Напишите уравнения по этим матрицам, то и получите для каждой координаты то что я написал выше. Только без учета ускорения:

Вот строка из матрицы А: 1, 0, 0, 1, 0, 0 означает x=1*x+0*y+0*z+1*vx+0*vy+0*vz => x=x+vx*dt здесь (dt = 1), аналогично для y и z. Все скорости равны сами себе vx=vx; vy=vy; vz=vz;

Так же видно что все координаты независимы, что не верно в случае учета поворота.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Потестил этот код, неплохо ведет цель.


X  Y  Z


predict -0.466858  0.808474  2.26073

real    -0.309018  0.486225  1.53683


-0.423659  0.684607  2.0921

-0.296634  0.412955  1.49816


-0.358051  0.502584  1.80924

-0.284429  0.322137  1.45931


-0.302884  0.319587  1.56944

-0.24458  0.255752  1.44207


-0.23795  0.192976  1.43535

-0.23719  0.200144  1.42542


-0.211506  0.116637  1.37693

-0.21606  0.155456  1.42932


-0.190204  0.0749303  1.37846

-0.202409  0.0838827  1.41801


-0.178239  0.0161604  1.38489

-0.193323  0.047973  1.42875


-0.173382  -0.0163037  1.40925

-0.185071  -0.00390054  1.43147


-0.170241  -0.0576007  1.42664

-0.18052  -0.0539902  1.43713


-0.169671  -0.103587  1.43971

-0.185037  -0.0819764  1.44412


-0.177794  -0.130038  1.4502

-0.20676  -0.128047  1.44989


-0.205006  -0.169031  1.45739

-0.239146  -0.156521  1.45426


-0.247401  -0.196648  1.46161

-0.260618  -0.190315  1.46437


-0.280221  -0.226259  1.47075

-0.27879  -0.215011  1.47307

Хочу реализовать мультитрекинг, есть у кого ни будь примеры или инфа?

Свой уже написал но довольно косячно работает путает цели которые пересекаются.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В мультитрекинге, при пересечении траекторий, объекты можно по направлению вектора скорости различать.

Т.к. скорость обычно мгновенно не меняется, особенно у массивных объектов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Определение ориентации (в кватернионном представлении) на основе показаний акселерометра и магнетометра:

http://code.google.com/p/9dof-orientation-estimation/

Хороший теоретический материал на англ.

http://campar.in.tum.de/Chair/KalmanFilter

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

При задании матрицы перехода используются

школьные формулы (раздел механики, движение материальной точки) :)

                          X  =   1*X + 0*Y + Vx*deltatime + Vy*0, 
Y = 0*X + 1*Y + 0*Vx + Vy*deltatime,
Vx = 0*X + 0*Y + 1*Vx + 0*Vy,
Vy = 0*X + 0*Y + 0*Vx + 1*Vy[/code]

deltatime - малый интервал времени, который задает скорость реакции фильтра (при уменьшении deltatime можно это видеть как эффект увеличение инерции, хотя это несколько другое)

В общем если полностью, то так:

Для оси X:

ax=M/Fx; vx=vx+ax*dt; x=x+vx*dt

где M - масса тела, ax - ускорение вдоль x, vx - скорость вдоль x, x - координата, dt - малый интервал времени, Fx - приложенное к точке усилие вдоль оси x.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

а где можно прочитать (желательно на руском так как математический английский очень слаб) или кто пояснит, про другие матрицы и почему мы используем именно эти значения (часть я понимаю но целой картины нет)

Именно то что описанно в примере

cvSetIdentity( this->kalman->measurement_matrix, cvRealScalar(1) );

        cvSetIdentity( this->kalman->process_noise_cov, cvRealScalar(1e-5) );

        cvSetIdentity( this->kalman->measurement_noise_cov, cvRealScalar(1e-1) );

        cvSetIdentity( this->kalman->error_cov_post, cvRealScalar(1));

Читал то что описаннов opencv-книге помогло отчасти, но повторюсь нет общей картины

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

а где можно прочитать (желательно на руском так как математический английский очень слаб) или кто пояснит, про другие матрицы и почему мы используем именно эти значения (часть я понимаю но целой картины нет)

Именно то что описанно в примере

cvSetIdentity( this->kalman->measurement_matrix, cvRealScalar(1) );
cvSetIdentity( this->kalman->process_noise_cov, cvRealScalar(1e-5) );
cvSetIdentity( this->kalman->measurement_noise_cov, cvRealScalar(1e-1) );
cvSetIdentity( this->kalman->error_cov_post, cvRealScalar(1));
[/code]

Читал то что описаннов opencv-книге помогло отчасти, но повторюсь нет общей картины

Вот кусок моей незаконченной статьи:

KalmanFilter.pdf

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

кто пояснит, про другие матрицы и почему мы используем именно эти значения (часть я понимаю но целой картины нет)

Именно то что описанно в примере

cvSetIdentity( this->kalman->measurement_matrix, cvRealScalar(1) );

        cvSetIdentity( this->kalman->process_noise_cov, cvRealScalar(1e-5) );

        cvSetIdentity( this->kalman->measurement_noise_cov, cvRealScalar(1e-1) );

        cvSetIdentity( this->kalman->error_cov_post, cvRealScalar(1));

Это матрицы измерения, ковариации шума процесса, ковариации шума измерения, начальная матрица ковариации ошибки соответственно.

Про первый листинг в теме пока не могу ничего сказать, а вот для второго листинга и далее такое определение матрицы ковариации шума процесса и переходной матрицы не совсем корректно. Если только шаг решения задачи у вас не 1 секунда. В противном случае эти матрицы будут иметь другой вид.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ну почему обязательно 1 секунда?

1 мс, 1 мкс, 1час, 1 такт, 1 цикл, здесь ничего не сказано о единицах измерения, важно чтобы эти единицы сильно не менялись во время работы программы и у всех величин одной природы были одинаковые единицы измерения.

И не проводить операции над величинами, обозначающими одну и ту же физическую величину, представленными в разных единицах измерения ([м]+[пикселы]) или ([с]+[мс]).

Аналогичная ситуация с координатами (1 м, 1 пиксел,...).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ну почему обязательно 1 секунда?

1 мс, 1 мкс, 1час, 1 такт, 1 цикл, здесь ничего не сказано о единицах измерения, важно чтобы эти единицы сильно не менялись во время работы программы и у всех величин одной природы были одинаковые единицы измерения.

И не проводить операции над величинами, обозначающими одну и ту же физическую величину, представленными в разных единицах измерения ([м]+[пикселы]) или ([с]+[мс]).

Аналогичная ситуация с координатами (1 м, 1 пиксел,...).

Ну тогда и скорость у вас должна измеряться в соответствующих единицах: 1 метр/цикл, 1 пиксел/такт :)

А если для примера взять систему уравнений, в которой вектор состояния это расстояние и скорость, то в дискретном представлении имеем следующие матрицы (если их расчитывать по теории):

вектор состояния:

x=[r v]

матрица перехода:

Fk=[1 dt; 0 1]

матрица ковариации шума процесса:

Qk=[(dt^3)/3 (dt^2)/2; (dt^2)/2 dt]Q

где dt-шаг по времени.

Матрицы представлены в таком же виде, как это делают в матлабе, но суть думаю будет ясна.

А тут уж решайте сами, что это - мкс , цикл или такт :D

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ну у Вас опечатка наверное, в wiki http://en.wikipedia.org/wiki/Kalman_filter

Это немного по-другому:

post-1-0-09186900-1348947041_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×