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

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

Recommended Posts

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

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


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

Есть, но вроде сейчас не поддерживается разработчиками.

См. CvConDensation.

Посмотрите здесь: http://answers.ros.org/question/55316/using-the-opencv-particle-filter-condensation/

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


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

спасибо за ссылку разбираюсь ниже прикрепляю код из ссылки


// Example of how to use the OpenCV Particle Filter.

// 

// Stolen largely from morethantechnical.com's nice mouse_kalman project.

//


#include <iostream>

#include <vector>


#include <opencv2/highgui/highgui.hpp>

#include <opencv2/video/tracking.hpp>

#include <opencv2/legacy/legacy.hpp>


using namespace std;


#define drawCross( center, color, d )                  \

  line( img, cv::Point( center.x - d, center.y - d ),           \

    cv::Point( center.x + d, center.y + d ), color, 2, CV_AA, 0);   \

  line( img, cv::Point( center.x + d, center.y - d ),           \

    cv::Point( center.x - d, center.y + d ), color, 2, CV_AA, 0 )



struct mouse_info_struct { int x,y; };

struct mouse_info_struct mouse_info = {-1,-1}, last_mouse;


vector<cv::Point> mouseV, particleV;

int counter = -1;


// Define this to proceed one click at a time.

//#define CLICK 1

#define PLOT_PARTICLES 1


void on_mouse(int event, int x, int y, int flags, void* param) 

{


#ifdef CLICK

  if (event == CV_EVENT_LBUTTONUP) 

#endif

  {

    last_mouse = mouse_info;

    mouse_info.x = x;

    mouse_info.y = y;

    counter = 0;

  }


}


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

{

  cv::Mat img(650, 650, CV_8UC3);

  char code = (char)-1;


  cv::namedWindow("mouse particle");

  cv::setMouseCallback("mouse particle", on_mouse, 0);


  cv::Mat_<float> measurement(2,1); 

  measurement.setTo(cv::Scalar(0));


  int dim = 2;

  int nParticles = 25;

  float xRange = 650.0;

  float yRange = 650.0;


  float minRange[] = { 0, 0 };

  float maxRange[] = { xRange, yRange };

  CvMat LB, UB;

  cvInitMatHeader(&LB, 2, 1, CV_32FC1, minRange);

  cvInitMatHeader(&UB, 2, 1, CV_32FC1, maxRange);


  CvConDensation* condens = cvCreateConDensation(dim, dim, nParticles);


  cvConDensInitSampleSet(condens, &LB, &UB);


  // The OpenCV documentation doesn't tell you to initialize this

  // transition matrix, but you have to do it.  For this 2D example, 

  // we're just using a 2x2 identity matrix.  I'm sure there's a slicker 

  // way to do this, left as an exercise for the reader.

  condens->DynamMatr[0] = 1.0;

  condens->DynamMatr[1] = 0.0;

  condens->DynamMatr[2] = 0.0;

  condens->DynamMatr[3] = 1.0;  


  for(;

  {


    if (mouse_info.x < 0 || mouse_info.y < 0) 

	{

      imshow("mouse particle", img);

      cv::waitKey(30);

      continue;

    }


    mouseV.clear();

    particleV.clear();


    for(;

	{

      code = (char)cv::waitKey(100);


      if( code > 0 ) break;


#ifdef CLICK

      if (counter++ > 0) {

    continue;

      } 

#endif


      measurement(0) = mouse_info.x;

      measurement(1) = mouse_info.y;


      cv::Point measPt(measurement(0),measurement(1));

      mouseV.push_back(measPt);


      // Clear screen

      img = cv::Scalar::all(100);


      for (int i = 0; i < condens->SamplesNum; i++) 

	  {


		float diffX = (measurement(0) - condens->flSamples[i][0])/xRange;

		float diffY = (measurement(1) - condens->flSamples[i][1])/yRange;


		condens->flConfidence[i] = 1.0 / (sqrt(diffX * diffX + diffY * diffY));


	// plot particles

#ifdef PLOT_PARTICLES

	cv::Point partPt(condens->flSamples[i][0], condens->flSamples[i][1]);

	drawCross(partPt , cv::Scalar(255,0,255), 2);

#endif


      }


      cvConDensUpdateByTime(condens);


      cv::Point statePt(condens->State[0], condens->State[1]);

      particleV.push_back(statePt);


      // plot points

      drawCross( statePt, cv::Scalar(255,255,255), 5 );

      drawCross( measPt, cv::Scalar(0,0,255), 5 );


      for (int i = 0; i < mouseV.size() - 1; i++) {

    line(img, mouseV[i], mouseV[i+1], cv::Scalar(255,255,0), 1);

      }

      for (int i = 0; i < particleV.size() - 1; i++) {

    line(img, particleV[i], particleV[i+1], cv::Scalar(0,255,0), 1);

      }


      imshow( "mouse particle", img );

    }


    if( code == 27 || code == 'q' || code == 'Q' )

      break;

  }


  return 0;

}

[/code]

не могли бы вы пояснить что такое тут

float xRange = 650.0;

float yRange = 650.0;

что это за диапазон такой.. не понятно...

и ещё я собрался попробовать заменить в программе выложенной выше фильтр Калмана на фильтр частиц, в связи с этим возникли следующие вопросы. Могу ли я вообще это делать ну т.к. на пример в случае с тараканами движущихся областей много не будет ли фильтр частиц запущенный для i-го таракана перескакивать на j-го таракана... или это в принципе невозможно?..

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


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

float xRange = 650.0;

float yRange = 650.0;

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

Могу ли я вообще это делать ну т.к. на пример в случае с тараканами движущихся областей много не будет ли фильтр частиц запущенный для i-го таракана перескакивать на j-го таракана... или это в принципе невозможно?

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

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


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

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

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

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

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

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


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

Вот смотрите, фильтр частиц действует так:

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

2) Для этого распределения генерируется N частиц.

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

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

5) Все частицы порождают новое поколение (с немного рандомизированными свойствами), причем каждый родитель порождает количество потомков, пропорциональное полученному на предыдущем шаге значению вероятности (N*P частиц). В сумме имеем опять N частиц.

5.а) Применяем переходный закон. Ну например если система механическая, то будет что то типа x1=x+v*dt; v1=v+a*dt; То есть частицы "знают" динамику объекта.

6) удаляем предыдущее поколение.

7) теперь наши частицы распределены согласно новому закону распределения (полученное на 4-м шаге).

8) считываем максимумы распределения (они и будут объектами).

9) идем на шаг 3.

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


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

большое спасибо за разъяснения по работе фильтра:) вот ещё вопрос

я составляю класс ParticleFilter по аналогии с классом Kalman из вашей программы. Приведу заголовочный файл


class TKalmanFilter

{

public:

	KalmanFilter* kalman;

	double deltatime; //приращение времени

	Point2f LastResult;

	TKalmanFilter(Point2f p,float dt=0.2,float Accel_noise_mag=0.5);

	~TKalmanFilter();

	Point2f GetPrediction();

	Point2f Update(Point2f p, bool DataCorrect);

};

для класса ParticleFilter всё довольно похоже(там конечно свои параметры) метод GetPrediction() получается довольно просто cv::Point statePt(condens->State[0], condens->State[1]); и у нас есть точка. а вот метод Point2f Update(Point2f p, bool DataCorrect); пока ставит меня в тупик если смотреть на калмана, то там вызывается специальный метод внутреннего класса Калмана для коррекции

// Коррекция

		Mat estimated = kalman->correct(measurement);

		LastResult.x=estimated.at<float>(0);  //уточняем, используя данные измерений

		LastResult.y=estimated.at<float>(1);

ничего похожего у CvConDensation я не нашёл... но как-то же надо обновлять координаты...

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


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

Тут, как я понял из кода примера фильтра частиц приведенного выше, нужно сначала задать степень вероятности для каждой частицы (не обязательно чтобы они суммировались в 1, нормирование, судя по всему производится фильтром):

condens->flConfidence[i] = 1.0 / (sqrt(diffX * diffX + diffY * diffY));
,затем уточнить состояние фильтра:
cvConDensUpdateByTime(condens);

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


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

Спасибо за ответ ниже даю ссылки на ролики работы трекера с разными фильтрами, фильтром частиц и фильтром Калмана

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


//condens->flConfidence[i] = exp(1.0 / (sqrt(diffX * diffX + diffY * diffY)));

//condens->flConfidence[i] = exp(-(sqrt(diffX * diffX + diffY * diffY)));

//condens->flConfidence[i] = exp(-((diffX*diffX)/(2*diffX * diffX + 2*diffY * diffY)))*exp(-((diffY*diffY)/(2*diffX * diffX + 2*diffY * diffY)));

//condens->flConfidence[i] = exp(-((diffX*diffX)/(2*xRange *yRange)))*exp(-((diffY*diffY)/(2*xRange *yRange)));

condens->flConfidence[i] = 1.0 / (sqrt(diffX * diffX + diffY * diffY));

ParticleFilter.h

ParticleFilter.cpp

  • Like 2

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


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

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

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


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

а вот то что периодически возникают полосы от трека в разные стороны это из-за того, что на частицы влияют другие движущиеся объекты?...

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


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

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

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


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

Да, трек живет некоторое время после потери объекта (это задается вроде maximum_allowed_skip_frames или что-то в этом духе).

Это делается для того чтобы он мог "поймать" объект после пропуска детекта.

Т.к. система линейная, то и летит трек по прямой. Эти линии, я полагаю, Вы и имеете ввиду.

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


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

Да да их они в фильтре частиц очень видны поэтому я подумал, что это выбросы самого фильтра) спасибо за подсказку попробую подправить

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


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

Пока удалить эти полосы не получилось.. странно ещё то, что для фильтра Калмана их нету, а для фильтра частиц они есть...

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


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

Еще один трекер с исходниками (не OpenCV):

Домашняя страница: http://perso.ensta-paristech.fr/~garrigues/video_extruder.html

Видео оттуда:

Репозиторий:

Используемая либа: https://github.com/matt-42/cuimg

Сам проект: https://github.com/matt-42/cuimg/tree/master/samples/tracking

  • Like 1

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


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

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

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


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

Думаю, что очень даже можно.

Ещё из интереса можно попробовать подсунуть выход трекера в pcl.

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


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

что то разговор зашел уже не о трекере

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

http://photosynth.net/discussion.aspx?cat=ceca0f30-0f7c-4468-811a-32b623ea8563&dis=38fa4600-62ec-4c86-94c3-35c1b118766d

но у меня кадры получались смазанными.

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


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

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

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


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

хмм ну видео было с мобильного телефона и там смазанность была не такая как например на зеркалке (хотя может быть так казалось из-за качества картинки).

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

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

и какого уровня камера примерно позволяет снимать нормальное видео?

там пишут

due to video compression and camera motion during capture, often video frames will be too blurry or have too much of the visual texture of objects removed in compression for Photosynth to have enough image features to lock onto to form an excellent point cloud.

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


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

Любые промышленные камеры и почти все камеры для охранного видеонаблюдения. Там важны именно детали на видео, а не красота кадра и сочность картинки. Плохое освещение? Ставьте ИК-прожекторы и ли прожекторы видимого диапазона.

кодеки, конечно, портят видео, добавляя артефакты сжатия, но они специально не делают ни дефокус, ни motion blur. Да и основные потери лежат в основном в цветовых составляющих.

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


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

Еще одна трекалака с исходниками:

Мануал: http://en.wikibooks.org/wiki/SwisTrack

Файлы: http://sourceforge.net/projects/swistrack/

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×