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

Трекинг объектов.

Recommended Posts

blobtrack_sample.cpp посмотри. Там вызывается функция cvCreateFGDetectorBase(CV_BG_MODEL_MOG, NULL) - это оно.

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


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

Всем привет

Если ли в opencv реализованные алгоритмы предксказания координат объекта по предыдущим его координат. В моем случае это бегущий человек но может быть в принципе и машина и мячик. Или есть какие то идеи реализовать это. Я смотрел пример калмена, но работает он на сглаживание, а не на предсказание координат

Хотя может я его не понял.

Всем заранее спасибо ;)

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


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

А насколько далеко в будущее надо предсказывать? Также важен характер движения: есть ли резкие повороты, ускорение или замедление.

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


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

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

хотя не знаю как это будет работать

http://ru.wikipedia.org/wiki/%D0%AD%D0%BA%D1%81%D1%82%D1%80%D0%B0%D0%BF%D0%BE%D0%BB%D1%8F%D1%86%D0%B8%D1%8F

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


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

Ну получаеться у меня человек мы можем снимать его координату в секунду 30 раз, ну а на сколько предсказывать это буквально три -пять секунд.

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


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

Фильтр Кальмана содержит в себе модель динамики системы, то есть, если мы говорим о простейшем механическом движении, то это законы типа:

F=m*a; x=x0+v*dt; v=v0+a*dt;

они нам говорят, что тело не может изменить вектор своей скорости, быстрее чем a=F/m; исходя из этого мы имеем для тяжелых тел гладкие траектории и медленный разгон/торможение, а для легких менее гладкие траектории и быстрый разгон/торможение.

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

Можете еще Particle filter покопать.

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


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

Для начала можно попробовать фильтр Кальмана. У него есть два этапа: измерение и предсказание (на один квант времени), которые происходят по очереди. Когда необходимо предсказать положение, скажем, на 3 секунды, делаем копию фильтра и вызываем цикл: предсказание - результат в измерение, предсказание - результат в измерение,... Делаем это N = (3 сек * 1000 млсек) / (30 кадров/сек).

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


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

Я взял за основу код Kalmen

Сделал как советовал Nuzhny, то есть результат предсказания засовывал в измерение. Однако у меня всегда короче значение уходит в ноль.

вот что я поменял в исходном коде

measurement(0) = predictPt.x;

measurement(1) = predictPt.y;

раньше было

measurement(0) = mouse_info.x;

measurement(1) = mouse_info.y;

Вот код с моими изменениями

http://dl.dropbox.com/u/20178650/bgfg_segm.cpp

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


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

Уважаемые форумчане, я смотрю на код blobtrack_sample.cpp я не понимаю как запустить бинарник, какие ему нужны

argc[], и вообще как работает эта программа... научите меня пожалуйста. А еще я не понимаю как мне запустить Adaptive background mixture. cvCreateFGDetectorBase(CV_BG_MODEL_MOG, NULL) - как использовать эту функцию ... ?? .. В теории понимаю как это делается а на практике , то есть на языке opencv не понимаю.

Очень жду совета, помощи и разъяснений. Заранее спасибо.

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


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

Если запустить exe ьез параметров, то в командной строке выдаётся подробная информация. Если нужна только Adaptive background mixture, то:

blobtrack_sample.exe fg=FG_1 d:\1.avi
  • Like 1

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


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

Я смог запустить программу, разобрался с описанием. Только я не могу понять , а где же тогда blob_track.exe выделяет передний план?? Что это за normal и abnormal блобы??

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

С нетерпением жду ответа.

post-4978-0-85304400-1332928433_thumb.jp

post-4978-0-50356700-1332928713_thumb.jp

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


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

Передний план выделяется одним из классов, создаваемых функциями: cvCreateFGDetector0, cvCreateFGDetector0Simple или cvCreateFGDetector1. Зависит от того, какой параметр ты укажешь в fg. Можешь просто создать свой проект и в нём создать один из вычитателей фона.

  • Like 1

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


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

1. Так, хорошо, а есть прям вот конкретный пример какой конкретно класс, какой конкретно параметр надо указывать в cvCreateFGDetector ? И где про это прочитать? В O'Reilly "learning open cv" не было этого вроде...

2. и еще Nuzhny, не могли бы просветить меня все таки что за normal и abnormal блобы выделяются в программе blobtrack.exe ?

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


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

1. Я по исходникам ориентируюсь. Есть абстрактный базовый класс для вычитания фона CvFGDetector.

Ты создаёшь объект этого класса. Например: CvFGDetector* fg_detector = cvCreateFGDetectorBase(CV_BG_MODEL_FGD, NULL);

После для каждого кадра: fg_detector->Process(frame);

И получаешь результат - чёрно-белую маску: IplImage* mask = fg_detector->GetMask();

Маска тебе и нужна.

В конце вызовешь: fg_detector->Release();

Всё.

2. С abnormal я не разбирался. Сравнивается с каким-то порогом. Такое ощущение, что зависит от траектории объекта.

  • Like 1

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


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

вот такой код написал , все проинклюдил

#include "D:/blobtrack.hpp"

#include "D:/highgui.hpp"

int main(int argc, char* argv[])

{

CvCapture *capture = cvCreateCameraCapture(0); // Думаю тут всё понятно

if(capture == NULL) // Если камер не обнаружено - выходим

return 0;

IplImage *bgr_frame = NULL;

CvFGDetector* fg_detector = cvCreateFGDetectorBase(CV_BG_MODEL_FGD, NULL);

while(1)

{

bgr_frame = cvQueryFrame(capture);

fg_detector->Process(bgr_frame);

IplImage* mask = fg_detector->GetMask();

cvNamedWindow( "original", 1 );

cvShowImage( "original", mask);

char c = cvWaitKey(100);

if(c == 27)break; }

cvReleaseCapture(&capture);

return 0;

}

ну и показывает тупо белый экран...=(

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


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

Подключил web-камеру, твой код нормально отрабатывает, объекты выделяются. Попробуй ещё параметры: CV_BG_MODEL_FGD_SIMPLE и CV_BG_MODEL_MOG. Хотя и так должно быть всё в порядке.

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


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

Итак, наложил маску, начал тестить.

Первое что мне не понравилось это скорость (fps) , мне кажется это очень медленно ...

Далее, начал двигаться, смотреть как программа выделяет меня... вначале сидел на стуле, потом встал (рисунок 111) потом вообще скрылся от камеры, А СТУЛ ОСТАЛСЯ!!! как так??? (рисунок 222)

потом взял и закрыл рукой камеру на 3-5 секунд (рисунок 333)

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

Подскажите пожалуйста, как мне действовать?

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

КОД ПРОГРАММЫ:

#include "D:/background_segm.hpp"

#include "D:/blobtrack.hpp"

#include "D:/highgui.hpp"

#include <D:/imgproc_c.h>

#include <stdio.h>

int main(int argc, char* argv[])

{

CvCapture *capture = cvCreateCameraCapture(0); // Думаю тут всё понятно

if(capture == NULL) // Если камер не обнаружено - выходим

return 0;

IplImage *frame = NULL;

CvFGDetector* fg_detector = cvCreateFGDetectorBase(CV_BG_MODEL_FGD, NULL);

cvNamedWindow( "mask", 1 );

cvNamedWindow("frame",1);

cvNamedWindow("frame1",1);

IplImage *frame1 = NULL; //это будет изображение с наложенной маской

frame = cvQueryFrame(capture);

frame1 = cvCreateImage(cvGetSize(frame),frame->depth,3);

while(1) {

cvSetZero(frame1);

frame = cvQueryFrame(capture);

fg_detector->Process(frame);

IplImage* mask = fg_detector->GetMask();

cvShowImage( "mask", mask);//маска выглядит так

cvAdd(frame,frame1,frame1,mask);//накладываю маску

cvShowImage("frame",frame1); //показываю что получилось

char c = cvWaitKey(1);

if(c == 27)break; }

cvReleaseCapture(&capture);

return 0;

}

post-4978-0-33832200-1333367526_thumb.jp

post-4978-0-84072200-1333367534_thumb.jp

post-4978-0-29379600-1333367539_thumb.jp

post-4978-0-47755100-1333367543_thumb.jp

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


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

Модель заднего плана строится, она и остаётся. Нужна реакция побыстрей - используй CV_BG_MODEL_MOG. Сама проблема называется "detecting ghost-objects"

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


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

Модель заднего плана строится, она и остаётся. Нужна реакция побыстрей - используй CV_BG_MODEL_MOG. Сама проблема называется "detecting ghost-objects"

MOG еще ужаснее... Как мне себя то выделить? (рисунок 555)

post-4978-0-67932300-1333369061_thumb.jp

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


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

есть что то навроде adaptive skin detector

читая тему я кстати не понял что значит передний и задний фон? это по глубине?

и разве так сложно выделить движущийся объект если камера не двигается и фон\освещение не меняется? или я не вижу тут каких то подводных камней?

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


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

Неясны исходные данные и цели.

Допустим у тебя есть фон, камера его снимает, всё тихо и спокойно.

Ты заходишь в кадр, садишься на кресло. И ждёшь, что будешь идеально выделен алгоритмом. Так?

Если так, то могут быть погрешности по двум причинам:

1. цвет твоей одежды совпадает с цветом фона, полностью или частично;

2. камера автоматически начнёт подстройку яркости и баланса белого.

Это надо учитывать.

  • Like 1

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


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

Добрый день!

Во-первых хочу выразить огромное спасибо за то,что вы помогаете мне разобраться с моей задачей:)

А теперь по порядочку:

1) Исходные данные: Есть комната, зал, помещение. В ней ходят люди, бегают кошки и собаки:) Также есть камера, которая прикреплена к стене, ближе к потолку. Конкретнее, это web-камера фирмы genius.

2) Задачи: Мне надо выяснить сколько людей прошли какую то невидимую прямую линию (которая заранее обозначена в программе) в одном направлении и в обратном. Соответственно, я буду знать сколько людей находится в комнате.

Насчет переднего и заднего "фона" - я ошибся со словом, я имел ввиду "передний план и задний план" .

Я начал думать над тем как решить эту проблему, и прочитал книгу Лукьяницы и Шишкина "Цифровая обработка видеоизображений". И подумал что мне нужно осуществлять трекинг за объектами. Но ведь для того чтобы это сделать надо вначале их выделить, что эти движущиеся объекты это передний план! То есть не относятся к фону.

Вот с этого места я начал думать, как мне тогда выделить передний план. Если я просто сфотографирую в начальный момент картинку то на ней могут быть

во-первых объекты которые не относятся к фону, и будет ошибка - если пользоваться "вычитанием фона"

во-вторых камера может трястись в некоторый момент и нарушиться.

в-третьих освещенность может изменяться

значит мне надо чтобы фон моделировался на протяжении работы всей программы.

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

#include "stdafx.h"

#include "iostream"

#include "stdlib.h"

#include "cv.h"

#include "highgui.h"

using namespace std;


int main(int argc, char* argv[])

{

	//Create a new window.

	cvNamedWindow("My Window", CV_WINDOW_AUTOSIZE);


	//Create a new movie capture object.

	CvCapture *input;


	//Assign the movie to capture.


	char *fileName = "D:\\highway.avi";

	input = cvCreateCameraCapture(0);

	if (!input)

	{

		cout << "Can't open file" << fileName ; }


	//Size of the image.

	IplImage* colourImage = cvQueryFrame(input);

	CvSize imgSize = cvGetSize(colourImage);

	cvZero(colourImage);


	//Images to use in the program.

	IplImage* greyImage = cvCreateImage( imgSize, IPL_DEPTH_8U, 1);


	IplImage* movingAverage = cvCreateImage( imgSize, IPL_DEPTH_32F, 3);

	IplImage* difference;

	IplImage* temp;

	IplImage* motionHistory = cvCreateImage( imgSize, IPL_DEPTH_8U, 3);


	//Rectangle to use to put around the people.

	CvRect bndRect = cvRect(0,0,0,0);


	//Points for the edges of the rectangle.

	CvPoint pt1, pt2;


	//Create a font object.

	CvFont font;


	//Create video to output to.

	char* outFilename = argc==2 ? argv[1] : "D:\\outputMovie.avi";

	CvVideoWriter* outputMovie = cvCreateVideoWriter(outFilename, 

		CV_FOURCC('M', 'P', 'E', 'G'), 29.97, cvSize(720, 576));


	//Capture the movie frame by frame.

	int prevX = 0;

	int numPeople = 0;


	//Buffer to save the number of people when converting the integer

	//to a string.

	char wow[65];


	//The midpoint X position of the rectangle surrounding the moving objects.

	int avgX = 0;


	//Indicates whether this is the first time in the loop of frames.

	bool first = true;


	//Indicates the contour which was closest to the left boundary before the object

	//entered the region between the buildings.

	int closestToLeft = 0;

	//Same as above, but for the right.

	int closestToRight = imgSize.width;


	//Keep processing frames...

	for(;

	{

		//Get a frame from the input video.

		colourImage = cvQueryFrame(input);


		//If there are no more frames, jump out of the for.

		if( !colourImage )

		{

			break;

		}


		//If this is the first time, initialize the images.

		if(first)

		{

			difference = cvCloneImage(colourImage);

			temp = cvCloneImage(colourImage);

			cvConvertScale(colourImage, movingAverage, 1.0, 0.0);

			first = false;

		}

		//else, make a running average of the motion.

		else

		{

			cvRunningAvg(colourImage, movingAverage, 0.020, NULL);

		}

		cvNamedWindow("movinAverage",1);


		//Convert the scale of the moving average.

		cvConvertScale(movingAverage,temp, 1.0, 0.0);


		//Minus the current frame from the moving average.

		cvAbsDiff(colourImage,temp,difference);


		//cvShowImage("movinAverage",difference);


		//Convert the image to grayscale.

		cvCvtColor(difference,greyImage,CV_RGB2GRAY);


		//Convert the image to black and white.

		cvThreshold(greyImage, greyImage, 70, 255, CV_THRESH_BINARY);


		//Dilate and erode to get people blobs

		cvDilate(greyImage, greyImage, 0, 18);

		cvErode(greyImage, greyImage, 0, 10);


			cvShowImage("movinAverage",greyImage);


		//Find the contours of the moving images in the frame.

		CvMemStorage* storage = cvCreateMemStorage(0);

		CvSeq* contour = 0;

		cvFindContours( greyImage, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );


		//Process each moving contour in the current frame...

		for( ; contour != 0; contour = contour->h_next )

		{

			//Get a bounding rectangle around the moving object.

			bndRect = cvBoundingRect(contour, 0);


			pt1.x = bndRect.x;

			pt1.y = bndRect.y;

			pt2.x = bndRect.x + bndRect.width;

			pt2.y = bndRect.y + bndRect.height;


			//Get an average X position of the moving contour.

			avgX = (pt1.x + pt2.x) / 2;


			//If the contour is within the edges of the building...

			if(avgX > 90 && avgX < 250)

			{

				//If the the previous contour was within 2 of the left boundary...

				if(closestToLeft >= 78 && closestToLeft <= 90)

				{

					//If the current X position is greater than the previous...

					if(avgX > prevX)

					{

						//Increase the number of people.

						numPeople++;


						//Reset the closest object to the left indicator.

						closestToLeft = 0;

					}

				}

				//else if the previous contour was within 2 of the right boundary...

				else if(closestToRight >= 250 && closestToRight <= 262)

				{

					//If the current X position is less than the previous...

					if(avgX < prevX)

					{

						//Increase the number of people.

						numPeople++;


						//Reset the closest object to the right counter.

						closestToRight = 320;

					}

				}


				//Draw the bounding rectangle around the moving object.

				cvRectangle(colourImage, pt1, pt2, CV_RGB(255,0,0), 1);

			}


			//If the current object is closer to the left boundary but still not across

			//it, then change the closest to the left counter to this value.

			if(avgX > closestToLeft && avgX <= 90)

			{

				closestToLeft = avgX;

			}


			//If the current object is closer to the right boundary but still not across

			//it, then change the closest to the right counter to this value.

			if(avgX < closestToRight && avgX >= 250)

			{

				closestToRight = avgX;

			}


			//Save the current X value to use as the previous in the next iteration.

			prevX = avgX; 

		}



		//Write the number of people counted at the top of the output frame.

		cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.8, 0.8, 0, 2);

		cvPutText(colourImage, _itoa(numPeople, wow, 10), cvPoint(60, 200), &font, cvScalar(0, 0, 300));


		//Show the frame.

		cvLine(colourImage, cvPoint(90,colourImage->height),cvPoint(90,0),CV_RGB(255,255,255),5);

		cvLine(colourImage, cvPoint(250,colourImage->height),cvPoint(250,0),CV_RGB(255,255,255),5);


		cvShowImage("My Window", colourImage);


		//Wait for the user to see it.

		cvWaitKey(10);


		//Write the frame to the output movie.

			cvWriteFrame(outputMovie, colourImage);


		CHAR c = cvWaitKey(1); // Ждём

	        if(c == 27)break; // Если Esc - выходим

	}


	// Destroy the image, movies, and window.

	cvReleaseImage(&temp);

	cvReleaseImage(&difference);

	cvReleaseImage(&greyImage);

	cvReleaseImage(&movingAverage);

	cvDestroyWindow("My Window");

	cvReleaseCapture(&input);

	cvReleaseVideoWriter(&outputMovie);

	return 0;

}

 [/code]

Вот такая программа, но она имеет свои недостатки ,

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

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

В третьих , самое главное, эта программа сделана только под ОДИН движущийся контур. переменная numPeople инкрементируется засчет условий которые проверяют avgX c переменной closestToLeft и переменной closestToRight при чем если на картинке много контуров движется, то надо каждому контуру сопоставлять свои выше упомянутые переменные, в этой программе такое не делается.

Дело в том, что я не совсем хорошо освоился с OpenCv и толком не могу понять как мне сделать так чтобы через некоторую линию могло проходить много человек, программа всех бы их обнаружила, даже если они перекрывают друг друга. Поэтому просто факт движения мне не подойдет, мне нужно именно делать слежение за объектом, а как это сделать ума не приложу.

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

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


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

сделайте сначала для неизменяемых условий камеры и отдельных объектов.

потом для изменяемых условий камеры.

слияние и разделение объектов это проблема.

есть что то типа crowd tracking.

если изначально зашла куча людей в кадр неразделенная, то мне кажется никак и не определишь, что это не 1 объект, предварительно не объяснив компьютеру, что считать за человека, а это некое обучение.

во всяком случае я видел видео, где довольно удачно трэкали людей играющий в баскетбол при условии, что они там в кучу сбивались.

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

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


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

слияние и разделение объектов это проблема.

есть что то типа crowd tracking.

1 . про crowd tracking где прочитать можно? примеры, код....

если изначально зашла куча людей в кадр неразделенная, то мне кажется никак и не определишь, что это не 1 объект, предварительно не объяснив компьютеру, что считать за человека, а это некое обучение.

2 . как научить компьютер "что считать за человека?"

3 . в продолжение предыдущего вопроса, я так понимаю что это можно осуществить с помощью нейронных сетей, какую книгу посоветуете почитать новичку?

4 . для трека можно использовать "Особые точки и метод Лукаса Канаде" , а также различные моменты контуров и гистограммы. Какой метод проще в реализации, мне новичку?

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


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

вот еще тема была

http://www.compvision.ru/forum/index.php?showtopic=630

вот можно погонять

http://www.aforgenet.com/framework/features/motion_detection_2.0.html

http://www.codeproject.com/Articles/10248/Motion-Detection-Algorithms

как научить компьютер "что считать за человека?"

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

типа такого http://pascallin.ecs.soton.ac.uk/challenges/VOC/voc2011/index.html

нейросеть не обязательно, там вон используют SVM.

вроде бы там даже решаются такие сложные случаи как перекрытие

http://pascallin.ecs.soton.ac.uk/challenges/VOC/voc2006/examples/bicycle_02.jpg

вообще я вопросом трекинга не занимался и классификации тоже, так что всё из общих соображений.

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×