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

Шаблоны движения (motion templates)

Recommended Posts

Спасибо за ответ. К сожалению в вашем списке нет сорцов по MHI.

Прилепил работу Брадского к посту. А вот результат:

OpenCV motion segmentation and pose recognition.

Хочу то-же самое, но не фронтальной камерой, а 360° fish eye, которая висит под потолком.

В любой части комнаты встаю в позу Y - включается вентилятор. Скрещиваю руки над головой - выключается. :)

wacv00.pdf

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


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

Прилепил работу Брадского к посту. А вот результат:

OpenCV motion segmentation and pose recognition.

Хочу то-же самое, но не фронтальной камерой, а 360° fish eye, которая висит под потолком.

В любой части комнаты встаю в позу Y - включается вентилятор. Скрещиваю руки над головой - выключается. :)

Насколько я понимаю, фон не меняется, иначе получите много трудно отделяемых помех.

А если фон не меняется, то зачем Вам знать что куда движется?

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

А изображение с fish eye нужно преобразовать к обычному линейному (например калибровкой):

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

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

Можно попробовать еще использовать скелетные изображения:

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

которые уже нормировать и скармливать классификатору, нейросетке например.

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


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

Вы правы, но я наивно полагаю, что шаблоны движения реализовать будет значительно проще, да и ресурсы им достаточны самые эмБЕДНЫЕ.

Вот нашёл систему прототайпинга:

http://eyepatch.stanford.edu/

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

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

Угол мне не нужен, придётся вырезать его из распознавалки айпетча.

Если определение будет нестабильным, пойду Вашим путём с отсечением фона, контурами, классификаторами.

Преобразование рыбьего глаза в панораму камера умеет делать сама.

Вам интересна задачка? Хотите пару фильмов для тестов? :)

Лимит темы на прикрепление файлов исчерпался, а то бы я Вам уже картинку рыбоглазую скинул 2048 х 1536. :(

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


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

Своял грубейший прототип. РАБОТАЕТ! В приложении "мой" грязнокод.

Мотрек записывает по нажатию клавиши битмэпы с шаблонами движения. Дальше глазами просматривается записанное и один желаемый битмэп переносится в папку к моту.

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

Быдлокод слизан с примера OpenCV и очень сырой. Путь к камере и имя файла с шаблоном надо прописывать в коде жёстко.

OpenCV 2.0 with IPP and ffmpeg, Ubuntu Linux, gcc, qmake, Qt Creator

Камера 360° fish eye Mobotix Q24 800 х 600

Ругайте!

mot.zip

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


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

Добрый день!. вопрос про шаблоны движения. Как мне укоротить хвост который идет за объектом. Я пробовал выставлять такие параметры

const double MHI_DURATION = 0.1;

const double MAX_TIME_DELTA = 0.1;

const double MIN_TIME_DELTA = 0.05;

const int N = 10;

в результате получил post-803-1288347724_thumb.jpg

как видите я получил как бы 2е копии машины.. как мне от этого избавиться ?

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


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

const double MHI_DURATION = 0.1;

const double MAX_TIME_DELTA = 0.1;

const double MIN_TIME_DELTA = 0.05;

const int N = 10;

в результате получил post-803-1288347724_thumb.jpg

как видите я получил как бы 2е копии машины.. как мне от этого избавиться ?

Может Вам лучше использовать что то типа bgfg_codebook или bgfg_segmentation? Эти примеры есть в opencv.

ЗЫ: codebook вначале собирает статистику фона, и показывает черный экран вместо результата. Дождитесь пока соберет, это секунд 15.

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


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

Попробуй перебрать всевозможные результаты параметров, посмотри, что можно "выжать" из этого.

Вообще, всё зависит от того, что ты хочешь получить. Что-то вроде вычитания фона?

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


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

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

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


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

По данному сабжу возникла проблема. :unsure:

При использовании update_mhi потребовалось изменять размеры захватываемых объектов в пикселях.

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

Идея в том, чтобы ограничить comp_rect, чтобы не менее 100 пикселей и не более 300 пикселей.

конкретно в этом условии стандартной функции:

if( (comp_rect.width + comp_rect.height > sb4pos ) && (comp_rect.width + comp_rect.height < sb5pos) ) 

Проблема в том, что возвращаемое значение comp_rect.width превышает 3 миллиона, а comp_rect.height=1920.

Вопрос: почему так происходит и что необходимо исправить, чтобы всё заработало? :rolleyes:

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


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

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

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


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

А куда смотреть то конкретно?

Лучше один раз увидеть, поэтому...

В прикрепленном: проект под OpenCV 2.4 в MVS 2010

6 реализаций update_mhi в отдельности для каждой камеры. Вызов функции из первого таймера.

Работает с файлом 18.avi, производит сохранение на D:\

Вот целиком проект:

Скачать (~350Mb)

Скачать с другого файлообменника (~350Mb)

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


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

Вот пример функции update_mhi:

void update_mhi1( IplImage* img, IplImage* dst, int diff_threshold, int sb4pos, int sb5pos)

{

	double timestamp = (double)clock()/CLOCKS_PER_SEC; // get current time in seconds

	CvSize size = cvSize(img->width,img->height); // get current frame size

	int i, idx1 = last1, idx2;

	IplImage* silh=0;

	CvSeq* seq=0;

	CvRect comp_rect;

	double count;

	double angle;

	CvPoint center;

	double magnitude;

	CvScalar color;


// number of cyclic frame buffer used for motion detection

// (should, probably, depend on FPS)


	// allocate images at the beginning or

	// reallocate them if the frame size is changed

	if( !mhi1 || mhi1->width != size.width || mhi1->height != size.height ) 

	{

		if( buf1 == 0 ) 

		{

			buf1 = (IplImage**)malloc(N*sizeof(buf1[0]));

			memset( buf1, 0, N*sizeof(buf1[0]));

		}

		for( i = 0; i < N; i++ ) 

		{

			cvReleaseImage( &buf1[i] );

			buf1[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 );

			cvZero( buf1[i] );

		}

	  cvReleaseImage( &mhi1 );

	  cvReleaseImage( &orient1 );

	  cvReleaseImage( &segmask1 );

	  cvReleaseImage( &mask1 );

	  mhi1 = cvCreateImage( size, IPL_DEPTH_32F, 1 );

	  cvZero( mhi1 ); // clear MHI at the beginning

	  orient1 = cvCreateImage(size, IPL_DEPTH_32F, 1 );

	  segmask1 = cvCreateImage(size, IPL_DEPTH_32F, 1 );

	  mask1 = cvCreateImage(size, IPL_DEPTH_8U, 1 );

	}

	cvCvtColor( img, buf1[last1], CV_BGR2GRAY ); // convert frame to grayscale

	idx2 = (last1 + 1) % N; // index of (last - (N-1))th frame

	last1 = idx2;

	silh = buf1[idx2];

	cvAbsDiff( buf1[idx1], buf1[idx2], silh ); // get difference between frames

	cvThreshold( silh, silh, diff_threshold, 1, CV_THRESH_BINARY ); // and threshold it

	cvUpdateMotionHistory( silh, mhi1, timestamp, MHI_DURATION ); // update MHI

	// convert MHI to blue 8u image

	cvCvtScale( mhi1, mask1, 255./MHI_DURATION,

	(MHI_DURATION - timestamp)*255./MHI_DURATION );

	cvZero( dst );

	cvCvtPlaneToPix( mask1, 0, 0, 0, dst );

	// calculate motion gradient orientation and valid orientation mask

	cvCalcMotionGradient( mhi1, mask1, orient1, MAX_TIME_DELTA, MIN_TIME_DELTA, 3 );

	if( !storage1 )

	storage1 = cvCreateMemStorage(0);

	else

	cvClearMemStorage(storage1);

	// segment motion: get sequence of motion components

	// segmask is marked motion components map. It is not used further

	seq = cvSegmentMotion( mhi1, segmask1, storage1, timestamp, MAX_TIME_DELTA );

	// iterate through the motion components,

	// One more iteration (i == -1) corresponds to the whole image (global motion)

	for( i = -1; i < seq->total; i++ ) 

	{

		if( i < 0 ) 

		{ // case of the whole image

			comp_rect = cvRect( 0, 0, size.width, size.height );

			color = CV_RGB(255,255,255);

			magnitude = 100;

		}

		else 

		{ // i-th motion component

		comp_rect = ((CvConnectedComp*)cvGetSeqElem( seq, i ))->rect;

		if( (comp_rect.width + comp_rect.height > sb4pos ) && (comp_rect.width + comp_rect.height < sb5pos) ) 

			// reject very small and very big components

		continue;

		color = CV_RGB(0,255,0);

		magnitude = 100;

		}

	// select component ROI

	cvSetImageROI( silh, comp_rect );

	cvSetImageROI( mhi1, comp_rect );

	cvSetImageROI( orient1, comp_rect );

	cvSetImageROI( mask1, comp_rect );

	// calculate orientation

	angle = cvCalcGlobalOrientation( orient1, mask1, mhi1, timestamp,MHI_DURATION);

	//angle = 360.0 - angle; // adjust for images with top-left origin

	count = cvNorm( silh, 0, CV_L1, 0 ); // calculate number of points within silhouette ROI

	cvResetImageROI( mhi1 );

	cvResetImageROI( orient1 );

	cvResetImageROI( mask1 );

	cvResetImageROI( silh );

	// check for the case of little motion


	if( count < comp_rect.width*comp_rect.height * 0.05 )

	continue;

	// draw a clock with arrow indicating the direction

	center = cvPoint( (comp_rect.x + comp_rect.width/2),(comp_rect.y + comp_rect.height/2) );

	cvCircle( dst, center, cvRound(magnitude*1.2), color, 3, CV_AA, 0 );

	cvLine( dst, center, cvPoint( cvRound( center.x + magnitude*cos(angle*CV_PI/180)),

	cvRound( center.y - magnitude*sin(angle*CV_PI/180))), color, 3, CV_AA,0 );

	cvLine(dst,cvPoint(0,trackleft1pos),cvPoint(640, trackright1pos), color, 2, CV_AA,0);

	if (onkey)

	if (((center.x*k1+trackleft1pos<center.y+2)&&((center.x*k1+trackleft1pos>center.y-2)))&&(angle>-1)&&(angle<181))

	{incount1++;

	allcount=allcount++;}

	if (onkey)

	if (((center.x*k1+trackleft1pos<center.y+2)&&((center.x*k1+trackleft1pos>center.y-2)))&&(angle>180)&&(angle<360))

	{outcount1++;

	allcount=allcount++;}

  }

}

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


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

У меня Линукс стоит и очень не хочется переделывать твой проект под него. А насколько проблемно тебе скомпилировать всё в Дебаге и пошариться в отладчике по функциям OpenCV?

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


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

И в моей (2.49) версии OpenCV не находится функция cvCvtPlaneToPix. Короче, по правилам хорошего тона тебе надо сделать минимальный консольный проектик, в котором повторяется проблема. Или даже не проекти, а исходник с main, в котором захватывается определённое видео.

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×