Professional Documents
Culture Documents
на OpenFrameworks
Обратите внимание:
похоже, что точка обзора
камеры движется вниз, но
в малотекстурированной
области поток не
находится - так как не
видно, что куда там
движется
http://www.ultimategraphics.co.jp/jp/images/stories/ultimate/BCC/optical.jpg
Основные применения оптического
потока
1. Для определения направления, в котором движутся
объекты в кадре. (В этой лекции мы будем так применять)
Обычно его считают не для всех пикселов изображения, а для "точек интереса" типа
углов. То есть сначала находятся точки интереса, а затем только на них считаются
вектора оптического потока.
ofVideoGrabber vidGrabber;
int w = 320;
int h = 240;
vidGrabber.initGrabber(320,240);
//оптический поток
ofSetColor( 0, 0, 0 );
int r = 10;
for (int y = 0; y < h; y += r) {
for (int x = 0; x < w; x += r ) {
float dx = cvmGet( motionX, y, x ); //Берем значение из матриц,
float dy = cvmGet( motionY, y, x ); //обратите внимание - (y,x)
ofCircle( x, y, 1 );
ofLine( x, y, x + dx, y + dy );
}
}
}
Пример 1. Вычисление оптического
потока методом Lucas-Kanade
Результат - алгоритм очень "шумит".
Путь к улучшению - брать усредненные вектора по некоторому локальному окну.
Кроме того, игнорировать явные "выбросы" - слишком длинные вектора сдвига.
Пример 2.
Lucas-Kanade + сглаживание
void testApp::draw(){
...
//оптический поток
for (int y = 0; y < h-r; y += r) {
for (int x = 0; x < w-r; x += r ) {
ofPoint sum( 0, 0 ); //суммарный вектор
int n = 0; //число точек для суммирования
for (int y1 = 0; y1 < r; y1++) { //суммирование
for (int x1 = 0; x1 < r; x1++) {
float dx = cvmGet( motionX, y + y1, x + x1 );
float dy = cvmGet( motionY, y + y1, x + x1 );
if ( dx * dx + dy * dy <= ( w/10 * w/10 ) ) { //контроль, что не выброс
sum += ofPoint( dx, dy );
n++;
}}}
ofPoint d = sum;
if ( n > 0 ) { d /= n; }
ofCircle( x, y, 1 ); ofLine( x, y, x + d.x, y + d.y );
}
}
Пример 2.
Lucas-Kanade + сглаживание
Результат заметно лучше.
Пример 3.
Horn-Schunk + сглаживание
void testApp::update(){
...
//Horn-Schunk
cvCalcOpticalFlowHS( grayPrev.getCvImage(), grayImage.getCvImage(),
(inited) ? 0 : 1, //использовать ли предыдущие вектора движения
motionX, motionY,
1.0, //lambda - параметр алгоритма (сглаживание?)
term );
//обратите внимание, что нет задания размера окна,
//только условие остановки итераций
...
Пример 3.
Horn-Schunk + сглаживание
Заметно, что вектора сдвига распространились и внутрь
нетекстурированных областей.
Вычисляется обычно медленней чем Lucas-Kanade.
Проект "Шарики в оптическом
потоке"
Размер, цвет и положение N шариков генерируются
случайным образом. Затем шарики летают, при этом сила,
действиющая на шарик, считается как средний вектор
оптического потока внутри пикселов, на которых лежит
шарик.
http://www.youtube.com/watch?v=CUaxE7dctrc
Проект "Шарики в оптическом
потоке"
...
...
}}}}}
ofPoint d = sum;
if ( n > 0 ) {
d /= n;
}
Проект "Шарики в оптическом
потоке"
//физика
ofPoint force = d;
float m = 0.005;
speed[ i ] += force / m * dt;
speed[ i ] *= 0.95;
pos[ i ] += speed[ i ] * dt;
}
Проект "Шарики в оптическом
потоке"
void testApp::draw() {
//камера
ofBackground(255,255,255);
ofSetColor( 255, 255, 255, 255);
vidGrabber.draw( 0, 0 );
//шарики
for (int i=0; i<N; i++) {
ofSetColor( color[i].r, color[i].g, color[i].b);
ofCircle( pos[i].x, pos[i].y, size[i] );
}
}
Проект по управлению сеткой с
помощью оптического потока
Как сделать:
к шарикам добавить связи по закону Гука.
http://www.youtube.com/watch?v=QX5TlIHXhd0